"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = configureModule;
function _fsExtra() {
const data = _interopRequireDefault(require("fs-extra"));
_fsExtra = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _klawSync() {
const data = _interopRequireDefault(require("klaw-sync"));
_klawSync = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};
/**
* Renames files names
* @param {path} directoryPath - directory that holds files to be renamed
* @param {string[]} extensions - array of extensions for files that would be renamed, must be provided with leading dot or empty for no extension, e.g. ['.html', '']
* @param {{ from: string, to: string }[]} renamings - array of filenames and their replacers
*/
const renameFilesWithExtensions = async (directoryPath, extensions, renamings) => {
await asyncForEach(renamings, async ({
from,
to
}) => await asyncForEach(extensions, async extension => {
const fromFilename = `${from}${extension}`;
if (!(await _fsExtra().default.exists(_path().default.join(directoryPath, fromFilename)))) {
return;
}
const toFilename = `${to}${extension}`;
await _fsExtra().default.rename(_path().default.join(directoryPath, fromFilename), _path().default.join(directoryPath, toFilename));
}));
};
/**
* Enters each file recursively in provided dir and replaces content by invoking provided callback function
* @param {path} directoryPath - root directory
* @param {(contentOfSingleFile: string) => string} replaceFunction - function that converts current content into something different
*/
const replaceContents = (directoryPath, replaceFunction) => {
for (let file of (0, _klawSync().default)(directoryPath, {
nodir: true
})) {
replaceContent(file.path, replaceFunction);
}
};
/**
* Replaces content in file
* @param {path} filePath - provided file
* @param {(contentOfSingleFile: string) => string} replaceFunction - function that converts current content into something different
*/
const replaceContent = async (filePath, replaceFunction) => {
const content = await _fsExtra().default.readFile(filePath, 'utf8');
const newContent = replaceFunction(content);
if (newContent !== content) {
await _fsExtra().default.writeFile(filePath, newContent);
}
};
/**
* Removes all empty subsdirs up to rootDir
* Recursively enters all subdirs and removes them if one is empty or cantained only empty subdirs
* @param {path} dirPath - directory path that is being inspected
* @returns {boolean} whether directory was deleted or not
*/
const removeUponEmptyOrOnlyEmptySubdirs = async dirPath => {
const contents = await _fsExtra().default.readdir(dirPath);
const results = await Promise.all(contents.map(async file => {
const filePath = _path().default.join(dirPath, file);
const fileStats = await _fsExtra().default.lstat(filePath);
return fileStats.isDirectory() && (await removeUponEmptyOrOnlyEmptySubdirs(filePath));
}));
const isRemovable = results.reduce((acc, current) => acc && current, true);
if (isRemovable) {
await _fsExtra().default.remove(dirPath);
}
return isRemovable;
};
/**
* Prepares iOS part, mainly by renaming all files and some template word in files
* Versioning is done automatically based on package.json from JS/TS part
* @param {path} modulePath - module directory
* @param {string} podName - PodName
* @param {{ npmModuleName: string, podName: string, javaPackage: string, jsModuleName: string }} configuration - naming configuration
*/
async function configureIOS(modulePath, {
podName,
jsModuleName
}) {
const iosPath = _path().default.join(modulePath, 'ios');
await renameFilesWithExtensions(_path().default.join(iosPath, 'EXModuleTemplate'), ['.h', '.m'], [{
from: 'EXModuleTemplateModule',
to: `${podName}Module`
}, {
from: 'EXModuleTemplateView',
to: `${podName}View`
}, {
from: 'EXModuleTemplateViewManager',
to: `${podName}ViewManager`
}]);
await renameFilesWithExtensions(iosPath, ['', '.podspec'], [{
from: 'EXModuleTemplate',
to: `${podName}`
}]);
await replaceContents(iosPath, singleFileContent => singleFileContent.replace(/EXModuleTemplate/g, podName).replace(/ExpoModuleTemplate/g, jsModuleName));
}
/**
* Prepares Android part, mainly by renaming all files and template words in files
* Sets all version in gradle to 1.0.0
* @param {path} modulePath - module directory
* @param {{ npmModuleName: string, podName: string, javaPackage: string, jsModuleName: string }} configuration - naming configuration
*/
async function configureAndroid(modulePath, {
javaPackage,
jsModuleName
}) {
const androidPath = _path().default.join(modulePath, 'android');
const sourceFilesPath = _path().default.join(androidPath, 'src', 'main', 'java', 'expo', 'module', 'template');
const destinationFilesPath = _path().default.join(androidPath, 'src', 'main', 'java', ...javaPackage.split('.'));
await _fsExtra().default.mkdirp(destinationFilesPath);
await _fsExtra().default.copy(sourceFilesPath, destinationFilesPath); // Remove leaf directory content
await _fsExtra().default.remove(sourceFilesPath); // Cleunp all empty subdirs up to provided rootDir
await removeUponEmptyOrOnlyEmptySubdirs(_path().default.join(androidPath, 'src', 'main', 'java', 'expo'));
const moduleName = jsModuleName.startsWith('Expo') ? jsModuleName.substring(4) : jsModuleName;
await replaceContents(androidPath, singleFileContent => singleFileContent.replace(/expo\.module\.template/g, javaPackage).replace(/ModuleTemplate/g, moduleName).replace(/ExpoModuleTemplate/g, jsModuleName));
await replaceContent(_path().default.join(androidPath, 'build.gradle'), gradleContent => gradleContent.replace(/version = ['"][\w.-]+['"]/, "version = '1.0.0'").replace(/versionCode \d+/, 'versionCode 1').replace(/versionName ['"][\w.-]+['"]/, "versionName '1.0.0'"));
await renameFilesWithExtensions(destinationFilesPath, ['.java'], [{
from: 'ModuleTemplateModule',
to: `${moduleName}Module`
}, {
from: 'ModuleTemplatePackage',
to: `${moduleName}Package`
}, {
from: 'ModuleTemplateView',
to: `${moduleName}View`
}, {
from: 'ModuleTemplateViewManager',
to: `${moduleName}ViewManager`
}]);
}
/**
* Prepares JS/TS part with npm package with package.json and README.md
* @param {string} modulePath - module directory
* @param {{ npmModuleName: string, podName: string, javaPackage: string, jsModuleName: string }} configuration - naming configuration
*/
async function configureTS(modulePath, {
npmModuleName,
podName,
jsModuleName
}) {
await replaceContent(_path().default.join(modulePath, 'package.json'), singleFileContent => singleFileContent.replace(/expo-module-template/g, npmModuleName).replace(/"version": "[\w.-]+"/, '"version": "1.0.0"').replace(/ExpoModuleTemplate/g, jsModuleName));
await replaceContent(_path().default.join(modulePath, 'README.md'), readmeContent => readmeContent.replace(/expo-module-template/g, npmModuleName).replace(/ExpoModuleTemplate/g, jsModuleName).replace(/EXModuleTemplate/g, podName));
await replaceContents(_path().default.join(modulePath, 'src'), singleFileContent => singleFileContent.replace(/ExpoModuleTemplate/g, jsModuleName));
await renameFilesWithExtensions(_path().default.join(modulePath, 'src'), ['.tsx'], [{
from: 'ExpoModuleTemplateView',
to: `${jsModuleName}View`
}]);
}
/**
* Configures TS, Android and iOS parts of generated module mostly by applying provided renamings
* @param {string} modulePath - module directory
* @param {{ npmModuleName: string, podName: string, javaPackage: string, jsModuleName: string }} configuration - naming configuration
*/
async function configureModule(newModulePath, configuration) {
await configureTS(newModulePath, configuration);
await configureAndroid(newModulePath, configuration);
await configureIOS(newModulePath, configuration);
}
//# sourceMappingURL=../../__sourcemaps__/commands/generate-module/configureModule.js.map