"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