UNPKG

react-native-integrate

Version:

Automate integration of additional code into React Native projects

287 lines (285 loc) 12.6 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.appDelegateTask = appDelegateTask; 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 findClosingTagIndex_1 = require("../utils/findClosingTagIndex"); const getErrMessage_1 = require("../utils/getErrMessage"); const getIosProjectPath_1 = require("../utils/getIosProjectPath"); const setState_1 = require("../utils/setState"); const stringSplice_1 = require("../utils/stringSplice"); const variables_1 = require("../variables"); const checkCondition_1 = require("../utils/checkCondition"); async function appDelegateTask(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 { content = await (0, applyContentModification_1.applyContentModification)({ action, findOrCreateBlock: findOrCreateBlock(task.lang), configPath, packageName, content, indentation: 2, }); (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; } const findOrCreateBlock = (lang) => { const _lang = lang || 'objc'; return (content, block) => { let blockContent = { start: 0, end: content.length, match: content, space: '', justCreated: false, }; const blockDefinition = blockDefinitions[_lang][block]; if (!blockDefinition) throw new Error(`Invalid block: ${block}`); const { regex, makeNewMethod } = blockDefinition; let blockStart = regex.exec(content); const justCreated = !blockStart; if (!blockStart) { const newMethod = makeNewMethod(); content = appendNewMethod(content, newMethod, _lang); blockStart = regex.exec(content); } if (!blockStart) { throw new Error('block could not be inserted, something wrong?'); } const blockEndIndex = (0, findClosingTagIndex_1.findClosingTagIndex)(content, blockStart.index + blockStart[0].length); const blockBody = content.substring(blockStart.index + blockStart[0].length, blockEndIndex); blockContent = { start: blockStart.index + blockStart[0].length, end: blockEndIndex, match: blockBody, justCreated, space: _lang === 'swift' ? ' '.repeat(2) : '', }; return { blockContent, content, }; }; }; const blockDefinitions = { objc: { didFinishLaunchingWithOptions: { regex: /didFinishLaunchingWithOptions.*?\{/s, makeNewMethod: () => { throw new Error('didFinishLaunchingWithOptions not implemented, something is wrong?'); }, }, applicationDidBecomeActive: { regex: /applicationDidBecomeActive.*?\{/s, makeNewMethod: () => { return '- (void)applicationDidBecomeActive:(UIApplication *)application {}'; }, }, applicationWillResignActive: { regex: /applicationWillResignActive.*?\{/s, makeNewMethod: () => { return '- (void)applicationWillResignActive:(UIApplication *)application {}'; }, }, applicationDidEnterBackground: { regex: /applicationDidEnterBackground.*?\{/s, makeNewMethod: () => { return '- (void)applicationDidEnterBackground:(UIApplication *)application {}'; }, }, applicationWillEnterForeground: { regex: /applicationWillEnterForeground.*?\{/s, makeNewMethod: () => { return '- (void)applicationWillEnterForeground:(UIApplication *)application {}'; }, }, applicationWillTerminate: { regex: /applicationWillTerminate.*?\{/s, makeNewMethod: () => { return '- (void)applicationWillTerminate:(UIApplication *)application {}'; }, }, openURL: { regex: /openURL:.*?options:.*?\{/s, makeNewMethod: () => { // noinspection SpellCheckingInspection return '- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {}'; }, }, restorationHandler: { regex: /continueUserActivity:.*?restorationHandler:.*?\{/s, makeNewMethod: () => { return '- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {}'; }, }, didRegisterForRemoteNotificationsWithDeviceToken: { regex: /didRegisterForRemoteNotificationsWithDeviceToken.*?\{/s, makeNewMethod: () => { return '- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {}'; }, }, didFailToRegisterForRemoteNotificationsWithError: { regex: /didFailToRegisterForRemoteNotificationsWithError.*?\{/s, makeNewMethod: () => { return '- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {}'; }, }, didReceiveRemoteNotification: { regex: /didReceiveRemoteNotification((?!fetchCompletionHandler).)*?\{/s, makeNewMethod: () => { return '- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {}'; }, }, fetchCompletionHandler: { regex: /didReceiveRemoteNotification:.*?fetchCompletionHandler:.*?\{/s, makeNewMethod: () => { return '- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {}'; }, }, }, swift: { didFinishLaunchingWithOptions: { regex: /func application\(.*?didFinishLaunchingWithOptions.*?\{/s, makeNewMethod: () => { throw new Error('didFinishLaunchingWithOptions not implemented, something is wrong?'); }, }, applicationDidBecomeActive: { regex: /func application\(.*?didBecomeActive.*?\{/s, makeNewMethod: () => { return 'func applicationDidBecomeActive(_ application: UIApplication) {}'; }, }, applicationWillResignActive: { regex: /func application\(.*?willResignActive.*?\{/s, makeNewMethod: () => { return 'func applicationWillResignActive(_ application: UIApplication) {}'; }, }, applicationDidEnterBackground: { regex: /func application\(.*?didEnterBackground.*?\{/s, makeNewMethod: () => { return 'func applicationDidEnterBackground(_ application: UIApplication) {}'; }, }, applicationWillEnterForeground: { regex: /func application\(.*?willEnterForeground.*?\{/s, makeNewMethod: () => { return 'func applicationWillEnterForeground(_ application: UIApplication) {}'; }, }, applicationWillTerminate: { regex: /func application\(.*?willTerminate.*?\{/s, makeNewMethod: () => { return 'func applicationWillTerminate(_ application: UIApplication) {}'; }, }, openURL: { regex: /func application\(.*?open url:.*?\{/s, makeNewMethod: () => { return 'func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool { return true }'; }, }, restorationHandler: { regex: /func application\(.*?continue userActivity:.*?\{/s, makeNewMethod: () => { return 'func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { return true }'; }, }, didRegisterForRemoteNotificationsWithDeviceToken: { regex: /func application\(.*?didRegisterForRemoteNotificationsWithDeviceToken.*?\{/s, makeNewMethod: () => { return 'func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {}'; }, }, didFailToRegisterForRemoteNotificationsWithError: { regex: /func application\(.*?didFailToRegisterForRemoteNotificationsWithError.*?\{/s, makeNewMethod: () => { return 'func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {}'; }, }, didReceiveRemoteNotification: { regex: /func application\(.*?didReceiveRemoteNotification.*?\{/s, makeNewMethod: () => { return 'func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {}'; }, }, fetchCompletionHandler: { regex: /func application\(.*?didReceiveRemoteNotification.*?completionHandler.*?\{/s, makeNewMethod: () => { return 'func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {}'; }, }, }, }; function appendNewMethod(content, newMethod, lang) { const appDelegateMatch = lang === 'objc' ? /@implementation AppDelegate.*?@end/s.exec(content) : /class AppDelegate:.*\}/s.exec(content); if (!appDelegateMatch) throw new Error('Could not find @implementation AppDelegate'); const codeToInsert = `${newMethod} `; return (0, stringSplice_1.stringSplice)(content, appDelegateMatch.index + appDelegateMatch[0].length - (lang === 'objc' ? 4 : 1), 0, codeToInsert); } function getAppDelegatePath(lang) { const iosProjectPath = (0, getIosProjectPath_1.getIosProjectPath)(); const appDelegatePath = path_1.default.join(iosProjectPath, lang === 'swift' ? constants_1.Constants.APP_DELEGATE_SWIFT_FILE_NAME : constants_1.Constants.APP_DELEGATE_MM_FILE_NAME); if (!fs_1.default.existsSync(appDelegatePath)) throw new Error(`AppDelegate file not found at ${appDelegatePath}`); return appDelegatePath; } function readAppDelegateContent(lang) { const appDelegatePath = getAppDelegatePath(lang); return fs_1.default.readFileSync(appDelegatePath, 'utf-8'); } function writeAppDelegateContent(content, lang) { const appDelegatePath = getAppDelegatePath(lang); return fs_1.default.writeFileSync(appDelegatePath, content, 'utf-8'); } async function runTask(args) { let content = readAppDelegateContent(args.task.lang); content = await appDelegateTask({ ...args, content, }); writeAppDelegateContent(content, args.task.lang); } exports.summary = 'AppDelegate modification';