react-native-integrate
Version:
Automate integration of additional code into React Native projects
318 lines (317 loc) • 11.3 kB
JavaScript
;
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';