UNPKG

react-native-integrate

Version:

Automate integration of additional code into React Native projects

318 lines (317 loc) 11.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.summary = void 0; exports.podFileTask = podFileTask; exports.runTask = runTask; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const constants_1 = require("../constants"); const applyContentModification_1 = require("../utils/applyContentModification"); const checkCondition_1 = require("../utils/checkCondition"); const findClosingTagIndex_1 = require("../utils/findClosingTagIndex"); const getErrMessage_1 = require("../utils/getErrMessage"); const getProjectPath_1 = require("../utils/getProjectPath"); const setState_1 = require("../utils/setState"); const stringSplice_1 = require("../utils/stringSplice"); const variables_1 = require("../variables"); async function podFileTask(args) { let { content } = args; const { task, configPath, packageName } = args; for (const action of task.actions) { variables_1.variables.set('CONTENT', content); if (action.when && !(0, checkCondition_1.checkCondition)(action.when)) { (0, setState_1.setState)(action.name, { state: 'skipped', reason: 'when', }); continue; } (0, setState_1.setState)(action.name, { state: 'progress', }); try { if (action.staticLibrary) { content = await applyStaticLibraryModification(content, action.staticLibrary, configPath, packageName); } if (action.useFrameworks) { content = await applyUseFrameworksModification(content, action.useFrameworks, configPath, packageName); } if (action.disableFlipper) { content = await applyDisableFlipperModification(content, action.disableFlipper, configPath, packageName); } content = await (0, applyContentModification_1.applyContentModification)({ action, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); (0, setState_1.setState)(action.name, { state: 'done', }); } catch (e) { (0, setState_1.setState)(action.name, { state: 'error', reason: (0, getErrMessage_1.getErrMessage)(e), }); throw e; } } return content; } async function applyStaticLibraryModification(content, staticLibrary, configPath, packageName) { const regExp = /\$static_libs.*?=.*?\[(.*?)]/s; const match = regExp.exec(content); const normalizedStaticLibrary = Array.isArray(staticLibrary) ? staticLibrary : [staticLibrary]; let action; if (!match) { action = { block: 'target', prepend: '$static_libs = [\n' + normalizedStaticLibrary.map(x => ` '${x}'`).join(',\n') + '\n]', }; } else { const existingLibs = match[1] .replace(/\n/g, '') .split(',') .map(x => x.trim().replace(/'/g, '')); for (const staticLib of normalizedStaticLibrary) { if (!existingLibs.includes(staticLib)) existingLibs.push(staticLib); } action = { block: 'target', search: { regex: regExp.source, flags: regExp.flags, }, replace: '$static_libs = [\n' + existingLibs.map(x => ` '${x}'`).join(',\n') + '\n]', }; } content = await (0, applyContentModification_1.applyContentModification)({ action, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); return content; } async function applyUseFrameworksModification(content, useFrameworks, configPath, packageName) { let action; if (useFrameworks == 'static') { // should not change dynamic to static if (/:linkage => :dynamic/.test(content) || /linkage = ['"]dynamic['"]/.test(content)) { return content; } if (/linkage = /.test(content)) action = { search: 'linkage = ', replace: "linkage = 'static'", }; else action = { before: 'target', append: 'use_frameworks! :linkage => :static', }; } else { if (/linkage = /.test(content)) action = { search: 'linkage = ', replace: "linkage = 'dynamic'", }; else action = { before: 'target', append: 'use_frameworks! :linkage => :dynamic', }; if (!/\$static_libs.*?=.*?\[(.*?)]/s.test(content)) { content = await (0, applyContentModification_1.applyContentModification)({ action: { block: 'target', prepend: '$static_libs = []', }, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); } content = await (0, applyContentModification_1.applyContentModification)({ action: { block: 'target.pre_install', ifNotPresent: 'Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies', prepend: `Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {} installer.pod_targets.each do |pod| if $static_libs.include?(pod.name) def pod.build_type; Pod::BuildType.static_library end end end`, }, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); } content = await (0, applyContentModification_1.applyContentModification)({ action: action, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); return content; } async function applyDisableFlipperModification(content, _disableFlipper, configPath, packageName) { let action; { if (/flipper_config = /.test(content)) action = { search: 'flipper_config = ', replace: 'flipper_config = FlipperConfiguration.disabled', }; else action = { search: { regex: ':flipper_configuration =>.*?,', flags: 's', }, replace: ':flipper_configuration => FlipperConfiguration.disabled,', exact: true, }; } content = await (0, applyContentModification_1.applyContentModification)({ action: action, findOrCreateBlock, configPath, packageName, content, indentation: 2, buildComment: buildPodComment, }); return content; } function buildPodComment(comment) { return comment.split('\n').map(x => `# ${x}`); } function findOrCreateBlock(content, block) { let blockContent = { start: 0, end: content.length, match: content, space: '', justCreated: false, }; const blockPath = block.split('.'); let contentOffset = 0; for (let i = 0; i < blockPath.length; i++) { const matcherRegex = new RegExp(`^((\\s+)?)${blockPath[i]}.*?\\bdo\\b(\\s\\|.*?\\|)? ?`, 'ms'); let blockStart = matcherRegex.exec(blockContent.match); const justCreated = !blockStart; if (!blockStart) { const blockName = blockPath[i]; // create block in block const space = ' '.repeat(2 * i); const previousSpace = ' '.repeat(Math.max(0, 2 * (i - 1))); const newBlock = buildBlock(space, blockName); const codeToInsert = ` ${newBlock} ${previousSpace}`; const contentLengthBeforeInsert = content.length; content = (0, stringSplice_1.stringSplice)(content, blockContent.end, 0, codeToInsert); if (codeToInsert.length && contentLengthBeforeInsert < content.length) { blockContent.match += codeToInsert; blockContent.end += codeToInsert.length; blockStart = matcherRegex.exec(blockContent.match); } } if (!blockStart) { throw new Error('block could not be inserted, something wrong?'); } const blockEndIndex = (0, findClosingTagIndex_1.findClosingTagIndex)(content, contentOffset + blockStart.index + blockStart[0].length, findClosingTagIndex_1.TagDefinitions.POD); const blockBody = content.substring(contentOffset + blockStart.index + blockStart[0].length, blockEndIndex); blockContent = { start: contentOffset + blockStart.index + blockStart[0].length, end: blockEndIndex, match: blockBody, justCreated, space: ' '.repeat(2 * i), }; contentOffset += blockStart.index + blockStart[0].length; } return { blockContent, content, }; } function buildBlock(space, blockName) { if (blockName === 'target') { // name is not specified so cannot create, throw error throw new Error('target not found, something is wrong?'); } else if (/target '.*?'/.test(blockName)) { // name is specified, create block return `${space}${blockName} do end`; } else if (podHooks.includes(blockName)) { return `${space}${blockName} do |installer| end`; } else { throw new Error('invalid block: ' + blockName); } } const podHooks = [ 'pre_install', 'pre_integrate', 'post_install', 'post_integrate', ]; function getPodFilePath() { const projectPath = (0, getProjectPath_1.getProjectPath)(); const podFilePath = path_1.default.join(projectPath, 'ios', constants_1.Constants.POD_FILE_NAME); if (!fs_1.default.existsSync(podFilePath)) throw new Error(`Pod file not found at ${podFilePath}`); return podFilePath; } function readPodFileContent() { const podFilePath = getPodFilePath(); return fs_1.default.readFileSync(podFilePath, 'utf-8'); } function writePodFileContent(content) { const podFilePath = getPodFilePath(); return fs_1.default.writeFileSync(podFilePath, content, 'utf-8'); } async function runTask(args) { let content = readPodFileContent(); content = await podFileTask({ ...args, content, }); writePodFileContent(content); } exports.summary = 'Podfile modification';