UNPKG

@embrace-io/react-native

Version:
187 lines (185 loc) 10.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.withIosEmbraceAddUploadPhase = exports.withIosEmbraceAddBridgingHeader = exports.withIosEmbraceInvokeInitializer = exports.withIosEmbraceAddInitializer = void 0; const config_plugins_1 = require("@expo/config-plugins"); const xcodeproj_1 = require("./xcodeproj"); const textUtils_1 = require("./textUtils"); const fileUtils_1 = require("./fileUtils"); const path = require("path"); const fs = require("fs"); const importAppDelegateHeaderRE = /(\s*)#import "AppDelegate\.h"/; const objcAppLaunchRE = /(\s*)self.moduleName = @"main"/; const swifthAppLaunchRE = /(\s*)func\s+application\(\s*_\s*[^}]*\{/; const swifthUpdatedAppLaunchRE = /(\s*)let.*ExpoReactNativeFactory.*/; const rnBundleScript = "react-native-xcode.sh"; const sourceMapPath = "$CONFIGURATION_BUILD_DIR/embrace-assets/main.jsbundle.map"; const exportSourcemapLine = `export SOURCEMAP_FILE="${sourceMapPath}"`; const getEmbraceInitializerContents = (appId) => { return `import Foundation import EmbraceIO @objcMembers class EmbraceInitializer: NSObject { // Start the EmbraceSDK with the minimum required settings, for more advanced configuration options see: // https://embrace.io/docs/ios/open-source/integration/embrace-options/ static func start() -> Void { do { try Embrace .setup( options: Embrace.Options( appId: "${appId}", platform: .reactNative ) ) .start() } catch let e { print("Error starting Embrace \\(e.localizedDescription)") } } } `; }; const getBridgingHeaderContents = () => { return `// // Use this file to import your target's public headers that you would like to expose to Swift. // `; }; const withIosEmbraceAddInitializer = (expoConfig, props) => { return (0, config_plugins_1.withXcodeProject)(expoConfig, (config) => __awaiter(void 0, void 0, void 0, function* () { const project = config.modResults; const projectName = config.modRequest.projectName || ""; const filePath = path.join(config.modRequest.platformProjectRoot, projectName, "EmbraceInitializer.swift"); (0, fileUtils_1.writeIfNotExists)(filePath, getEmbraceInitializerContents(props.iOSAppId), "withIosEmbraceAddInitializer"); const projectRelativePath = path.join(projectName, "EmbraceInitializer.swift"); if (!project.hasFile(projectRelativePath)) { (0, xcodeproj_1.addFile)(project, projectName, projectRelativePath, "source"); fs.writeFileSync(project.filepath, project.writeSync()); } return config; })); }; exports.withIosEmbraceAddInitializer = withIosEmbraceAddInitializer; const withIosEmbraceInvokeInitializer = (expoConfig, props) => { return (0, config_plugins_1.withAppDelegate)(expoConfig, config => { const lines = config.modResults.contents.split("\n"); const language = config.modResults.language; // Don't add the Embrace initialize line again if it's already there if ((0, textUtils_1.hasMatch)(lines, "Embrace")) { return config; } // Add the objective-c bridging header import if required if (language === "objcpp") { // https://developer.apple.com/documentation/swift/importing-swift-into-objective-c#Overview const headerName = props.productModuleName || config.modRequest.projectName || ""; const alphanumericOnly = headerName.replace(/\W+/g, "_"); const firstNumberReplaced = alphanumericOnly.replace(/^\d/, "_"); const bridgingHeaderName = `${firstNumberReplaced}-Swift.h`; if (!bridgingHeaderName) { throw new Error("failed to determine bridging header name for the AppDelegate file"); } const addedImport = (0, textUtils_1.addAfter)(lines, // Look for the import of AppDelegate.h and add the import underneath importAppDelegateHeaderRE, `#import "${bridgingHeaderName}"`); if (!addedImport) { throw new Error("failed to add the bridging header import to the AppDelegate file"); } const addedExpoModulesImport = (0, textUtils_1.addAfter)(lines, // Look for the import of AppDelegate.h and add the import underneath importAppDelegateHeaderRE, `#import "ExpoModulesCore-Swift.h"`); if (!addedExpoModulesImport) { throw new Error("failed to add the expo modules import to the AppDelegate file"); } } const addedInit = (0, textUtils_1.addAfter)(lines, // Want the Embrace SDK initialization to happen right after at the start of the AppDelegate application method language === "swift" ? swifthAppLaunchRE : objcAppLaunchRE, language === "swift" ? " EmbraceInitializer.start()" // Add indentation since we're matching on the method signature's whitespace : "[EmbraceInitializer start];"); if (!addedInit) { if (language !== "swift") { throw new Error("failed to add the Embrace initialization to the AppDelegate application method"); } // Default AppDelegate.swift changed on later versions of expo, try one more time with a different regex const addedInitUpdatedSwift = (0, textUtils_1.addAfter)(lines, swifthUpdatedAppLaunchRE, "EmbraceInitializer.start()"); if (!addedInitUpdatedSwift) { throw new Error("failed to add the Embrace initialization to the AppDelegate application method"); } } config.modResults.contents = lines.join("\n"); return config; }); }; exports.withIosEmbraceInvokeInitializer = withIosEmbraceInvokeInitializer; const withIosEmbraceAddBridgingHeader = expoConfig => { return (0, config_plugins_1.withXcodeProject)(expoConfig, (config) => __awaiter(void 0, void 0, void 0, function* () { const project = config.modResults; const projectName = config.modRequest.projectName || ""; const bridgingHeader = project.getBuildProperty("SWIFT_OBJC_BRIDGING_HEADER", undefined, projectName); if (bridgingHeader) { // Nothing to do if the bridging header already exists; return config; } const filename = `${projectName}-Bridging-Header.h`; const filePath = path.join(config.modRequest.platformProjectRoot, projectName, filename); const projectRelativePath = path.join(projectName, filename); (0, fileUtils_1.writeIfNotExists)(filePath, getBridgingHeaderContents(), "withIosEmbraceAddBridgingHeader"); if (!project.hasFile(projectRelativePath)) { (0, xcodeproj_1.addFile)(project, projectName, projectRelativePath, "resource"); (0, xcodeproj_1.updateBuildProperty)(project, projectName, "SWIFT_OBJC_BRIDGING_HEADER", `"${projectRelativePath}"`); fs.writeFileSync(project.filepath, project.writeSync()); } return config; })); }; exports.withIosEmbraceAddBridgingHeader = withIosEmbraceAddBridgingHeader; const withIosEmbraceAddUploadPhase = (expoConfig, props) => { return (0, config_plugins_1.withXcodeProject)(expoConfig, (config) => __awaiter(void 0, void 0, void 0, function* () { let modified = false; const project = config.modResults; const bundlePhase = (0, xcodeproj_1.findPhase)(project, rnBundleScript); if (!bundlePhase) { throw new Error("Could not find React Native bundle phase to modify"); } if (!(0, textUtils_1.hasMatch)(bundlePhase.code, "embrace-assets")) { (0, xcodeproj_1.modifyPhase)(project, bundlePhase.key, /^.*?\/(packager|scripts)\/react-native-xcode\.sh\s*/m, `mkdir -p "$CONFIGURATION_BUILD_DIR/embrace-assets"\n` + `${exportSourcemapLine}\n`); modified = true; } /* shellScript = "REACT_NATIVE_MAP_PATH=\"$CONFIGURATION_BUILD_DIR/embrace-assets/main.jsbundle.map\" EMBRACE_ID=ios789 EMBRACE_TOKEN=apiToken456 \"${PODS_ROOT}/EmbraceIO/run.sh\"\nrm \"$CONFIGURATION_BUILD_DIR/embrace-assets/main.jsbundle.map\""; */ if (!(0, xcodeproj_1.findPhase)(project, "EmbraceIO/run.sh")) { project.addBuildPhase([], "PBXShellScriptBuildPhase", "Upload Debug Symbols to Embrace", null, { shellPath: "/bin/sh", shellScript: `REACT_NATIVE_MAP_PATH="${sourceMapPath}" EMBRACE_ID=${props.iOSAppId} EMBRACE_TOKEN=${props.apiToken} "\${PODS_ROOT}/EmbraceIO/run.sh"`, }); modified = true; } if (modified) { fs.writeFileSync(project.filepath, project.writeSync()); } return config; })); }; exports.withIosEmbraceAddUploadPhase = withIosEmbraceAddUploadPhase; const withIosEmbrace = (config, props) => { try { config = withIosEmbraceAddInitializer(config, props); config = withIosEmbraceInvokeInitializer(config, props); config = withIosEmbraceAddBridgingHeader(config, props); config = withIosEmbraceAddUploadPhase(config, props); } catch (e) { config_plugins_1.WarningAggregator.addWarningIOS("@embrace-io/expo-config-plugin", e instanceof Error ? e.message : "", "https://embrace.io/docs/react-native/integration/add-embrace-sdk/"); } return config; }; exports.default = withIosEmbrace;