@embrace-io/react-native
Version:
A React Native wrapper for the Embrace SDK
201 lines (199 loc) • 9.74 kB
JavaScript
;
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.addEmbraceInitializerSwift = exports.addUploadBuildPhase = exports.patchXcodeBundlePhase = exports.iosPodfileKSCrashPatch = exports.iOSPodfilePatch = exports.iosInitializeEmbrace = exports.patchPodFileWithKSCrash = exports.getIOSProjectName = exports.patchPodfile = exports.tryToPatchAppDelegate = void 0;
const ios_1 = require("../util/ios");
const EmbraceLogger_1 = require("../../src/utils/EmbraceLogger");
const patch_1 = require("./patches/patch");
const common_1 = require("./common");
const path = require("path");
const fs = require("fs");
const semverGte = require("semver/functions/gte");
const LOGGER = new EmbraceLogger_1.default(console);
const tryToPatchAppDelegate = (iOSProjectName) => __awaiter(void 0, void 0, void 0, function* () {
const project = yield (0, ios_1.xcodePatchable)(iOSProjectName);
const bridgingHeader = project.getBridgingHeaderName(iOSProjectName);
const response = (0, patch_1.default)("objectivec", iOSProjectName, { bridgingHeader });
if (response) {
return project.addBridgingHeader(iOSProjectName);
}
return (0, patch_1.default)("swift", iOSProjectName) || false;
});
exports.tryToPatchAppDelegate = tryToPatchAppDelegate;
/**
* Getting iOS project name either from user's input ('CustomBeautifulApp') or from package.json ({ name: 'custom.beautiful.app' })
*/
const getIOSProjectName = (wizard) => __awaiter(void 0, void 0, void 0, function* () {
const [customProjectName, pJSON] = yield wizard.fieldValueList([
common_1.iosProjectFolderName,
common_1.packageJSON,
]);
return customProjectName && customProjectName !== ""
? customProjectName // if the user decided to customize the project's name when creating the app using the RN cli
: pJSON.name; // fallback to what package.json contains as name
});
exports.getIOSProjectName = getIOSProjectName;
const iosInitializeEmbrace = {
name: "iOS initialize Embrace",
run: (wizard) => __awaiter(void 0, void 0, void 0, function* () {
const name = yield getIOSProjectName(wizard);
return tryToPatchAppDelegate(name);
}),
docURL: "https://embrace.io/docs/react-native/integration/add-embrace-sdk/?platform=ios#manually",
};
exports.iosInitializeEmbrace = iosInitializeEmbrace;
const patchPodFileWithKSCrash = () => __awaiter(void 0, void 0, void 0, function* () {
return (0, ios_1.podfilePatchable)().then(podfile => {
if (podfile.hasLine(ios_1.EMBR_KSCRASH_MODULAR_HEADER_POD)) {
LOGGER.warn("Already has 'KSCrash' pod with modular headers enabled");
return;
}
podfile.addBefore("linkage = ENV['USE_FRAMEWORKS']", `${ios_1.EMBR_KSCRASH_MODULAR_HEADER_POD}\n`);
return podfile.patch();
});
});
exports.patchPodFileWithKSCrash = patchPodFileWithKSCrash;
const patchPodfile = (json) => {
const rnVersion = (json.dependencies || {})["react-native"];
if (!rnVersion) {
throw Error("react-native dependency was not found");
}
const rnVersionSanitized = rnVersion.replace("^", "");
// If 6.0.0, autolink should have linked the Pod.
if (semverGte("6.0.0", rnVersionSanitized)) {
LOGGER.log("Skipping patching Podfile since react-native is on an autolink supported version");
return;
}
return (0, ios_1.podfilePatchable)().then(podfile => {
if (podfile.hasLine(ios_1.EMBR_NATIVE_POD)) {
LOGGER.warn("Already has 'EmbraceIO' pod");
return;
}
podfile.addBefore("use_react_native", `${ios_1.EMBR_NATIVE_POD}\n`);
return podfile.patch();
});
};
exports.patchPodfile = patchPodfile;
const iOSPodfilePatch = {
name: "Podfile patch (Only React Native v < 0.6)",
run: (wizard) => __awaiter(void 0, void 0, void 0, function* () {
return wizard.fieldValue(common_1.packageJSON).then(patchPodfile);
}),
docURL: "https://embrace.io/docs/react-native/integration/add-embrace-sdk/?platform=ios#native-modules",
};
exports.iOSPodfilePatch = iOSPodfilePatch;
const iosPodfileKSCrashPatch = {
name: "KSCrash enabling modular headers",
run: (_wizard) => __awaiter(void 0, void 0, void 0, function* () {
return patchPodFileWithKSCrash();
}),
docURL: "https://embrace.io/docs/react-native/integration/add-embrace-sdk/?platform=ios#native-modules",
};
exports.iosPodfileKSCrashPatch = iosPodfileKSCrashPatch;
const patchXcodeBundlePhase = {
name: "Update bundle phase",
run: (wizard) => __awaiter(void 0, void 0, void 0, function* () {
return getIOSProjectName(wizard)
.then(ios_1.xcodePatchable)
.then(project => {
const bundlePhaseKey = project.findPhase(ios_1.BUNDLE_PHASE_REGEXP);
if (!bundlePhaseKey) {
LOGGER.error("Could not find Xcode React Native bundle phase");
return;
}
if (project.hasLine(bundlePhaseKey, ios_1.EXPORT_SOURCEMAP_RN_VAR)) {
LOGGER.warn("Already patched Xcode React Native bundle phase");
return;
}
LOGGER.log("Patching Xcode React Native bundle phase");
project.modifyPhase(bundlePhaseKey, ios_1.BUNDLE_PHASE_REGEXP, `${ios_1.MKDIR_SOURCEMAP_DIR}\n${ios_1.EXPORT_SOURCEMAP_RN_VAR}\n`);
return project.patch();
});
}),
docURL: "https://embrace.io/docs/react-native/integration/upload-symbol-files/#uploading-source-maps",
};
exports.patchXcodeBundlePhase = patchXcodeBundlePhase;
const addUploadBuildPhase = {
name: `Add '${ios_1.UPLOAD_SYMBOLS_PHASE}' phase`,
run: (wizard) => getIOSProjectName(wizard).then((name) => __awaiter(void 0, void 0, void 0, function* () {
return (0, ios_1.xcodePatchable)(name).then(project => {
const uploadBuildPhaseKey = project.findPhase(ios_1.EMBR_RUN_SCRIPT);
if (uploadBuildPhaseKey) {
LOGGER.warn(`Already added '${ios_1.UPLOAD_SYMBOLS_PHASE}' phase`);
return;
}
return wizard.fieldValueList([common_1.iosAppID, common_1.apiToken]).then(list => {
const [appId, token] = list;
const proj = project.project;
proj.addBuildPhase([], "PBXShellScriptBuildPhase", ios_1.UPLOAD_SYMBOLS_PHASE, null, {
shellPath: "/bin/sh",
shellScript: `REACT_NATIVE_MAP_PATH="$CONFIGURATION_BUILD_DIR/embrace-assets/main.jsbundle.map" EMBRACE_ID=${appId} EMBRACE_TOKEN=${token} ${ios_1.EMBR_RUN_SCRIPT}`,
});
return project.patch();
});
});
})),
docURL: "https://embrace.io/docs/react-native/integration/upload-symbol-files/#uploading-native-and-javascript-symbol-files",
};
exports.addUploadBuildPhase = addUploadBuildPhase;
const addEmbraceInitializerSwift = {
name: "Adding EmbraceInitializer.swift",
run: (wizard) => __awaiter(void 0, void 0, void 0, function* () {
const appId = yield wizard.fieldValue(common_1.iosAppID);
const name = yield getIOSProjectName(wizard);
const project = yield (0, ios_1.xcodePatchable)(name);
const filePath = path.join("ios", name, "EmbraceInitializer.swift");
try {
const fd = fs.openSync(filePath, "wx");
fs.writeFileSync(fd, getEmbraceInitializerContents(appId));
}
catch (e) {
if (e instanceof Error && e.message.includes("EEXIST")) {
LOGGER.warn("EmbraceInitializer.swift already exists");
return;
}
else if (e instanceof Error && e.message.includes("ENOENT")) {
throw `${e}. ${ios_1.ENOENT_XCODE_PROJ_ERROR_MESSAGE}`;
}
else {
throw e;
}
}
const nameWithCaseSensitive = (0, ios_1.findNameWithCaseSensitiveFromPath)(project.path, name);
project.addFile(nameWithCaseSensitive, `${nameWithCaseSensitive}/EmbraceInitializer.swift`, "source");
return project.patch();
}),
docURL: "https://embrace.io/docs/react-native/integration/add-embrace-sdk/#manually",
};
exports.addEmbraceInitializerSwift = addEmbraceInitializerSwift;
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)")
}
}
}
`;
};