@sentry/wizard 3.24.0 → 3.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/package.json +1 -1
- package/dist/src/nextjs/templates.js +1 -1
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/react-native/expo-env-file.d.ts +2 -0
- package/dist/src/react-native/expo-env-file.js +127 -0
- package/dist/src/react-native/expo-env-file.js.map +1 -0
- package/dist/src/react-native/expo-metro.d.ts +7 -0
- package/dist/src/react-native/expo-metro.js +236 -0
- package/dist/src/react-native/expo-metro.js.map +1 -0
- package/dist/src/react-native/expo.d.ts +16 -0
- package/dist/src/react-native/expo.js +195 -0
- package/dist/src/react-native/expo.js.map +1 -0
- package/dist/src/react-native/git.d.ts +1 -0
- package/dist/src/react-native/git.js +85 -0
- package/dist/src/react-native/git.js.map +1 -0
- package/dist/src/react-native/javascript.d.ts +3 -0
- package/dist/src/react-native/javascript.js +119 -1
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/metro.d.ts +3 -0
- package/dist/src/react-native/metro.js +17 -15
- package/dist/src/react-native/metro.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.d.ts +12 -0
- package/dist/src/react-native/react-native-wizard.js +91 -78
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-native/xcode.js +14 -3
- package/dist/src/react-native/xcode.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +2 -1
- package/dist/src/utils/clack-utils.js +2 -2
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/test/nextjs/templates.test.js +1 -1
- package/dist/test/nextjs/templates.test.js.map +1 -1
- package/dist/test/react-native/expo-metro.test.d.ts +1 -0
- package/dist/test/react-native/expo-metro.test.js +26 -0
- package/dist/test/react-native/expo-metro.test.js.map +1 -0
- package/dist/test/react-native/expo.test.d.ts +1 -0
- package/dist/test/react-native/expo.test.js +57 -0
- package/dist/test/react-native/expo.test.js.map +1 -0
- package/dist/test/react-native/xcode.test.js +5 -0
- package/dist/test/react-native/xcode.test.js.map +1 -1
- package/package.json +1 -1
- package/src/nextjs/templates.ts +1 -1
- package/src/react-native/expo-env-file.ts +55 -0
- package/src/react-native/expo-metro.ts +212 -0
- package/src/react-native/expo.ts +175 -0
- package/src/react-native/git.ts +25 -0
- package/src/react-native/javascript.ts +68 -1
- package/src/react-native/metro.ts +3 -3
- package/src/react-native/react-native-wizard.ts +72 -76
- package/src/react-native/xcode.ts +21 -5
- package/src/sourcemaps/sourcemaps-wizard.ts +1 -1
- package/src/utils/clack-utils.ts +4 -4
- package/test/nextjs/templates.test.ts +1 -1
- package/test/react-native/expo-metro.test.ts +81 -0
- package/test/react-native/expo.test.ts +86 -0
- package/test/react-native/xcode.test.ts +90 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
4
|
+
var magicast_1 = require("magicast");
|
|
5
|
+
var expo_metro_1 = require("../../src/react-native/expo-metro");
|
|
6
|
+
describe('expo-metro config', function () {
|
|
7
|
+
test('patches minimal expo config', function () {
|
|
8
|
+
var mod = (0, magicast_1.parseModule)("\nconst { getDefaultConfig } = require(\"expo/metro-config\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getDefaultConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n ");
|
|
9
|
+
var result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
10
|
+
expect(result).toBe(true);
|
|
11
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getSentryExpoConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n".trim());
|
|
12
|
+
});
|
|
13
|
+
test('keeps expo metro config if other imports are present', function () {
|
|
14
|
+
var mod = (0, magicast_1.parseModule)("\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst config = getDefaultConfig(__dirname);\n\nmodule.exports = config;\n ");
|
|
15
|
+
var result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
16
|
+
expect(result).toBe(true);
|
|
17
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n".trim());
|
|
18
|
+
});
|
|
19
|
+
test('does not modify when sentry already present', function () {
|
|
20
|
+
var mod = (0, magicast_1.parseModule)("\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n");
|
|
21
|
+
var result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
22
|
+
expect(result).toBe(false);
|
|
23
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n".trim());
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=expo-metro.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo-metro.test.js","sourceRoot":"","sources":["../../../test/react-native/expo-metro.test.ts"],"names":[],"mappings":";;AAAA,4EAA4E;AAC5E,qCAAqD;AACrD,gEAAuE;AAEvE,QAAQ,CAAC,mBAAmB,EAAE;IAC5B,IAAI,CAAC,6BAA6B,EAAE;QAClC,IAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,gTAYrB,CAAC,CAAC;QAEL,IAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,6TAcL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE;QAC3D,IAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,gKAMrB,CAAC,CAAC;QAEL,IAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,6OAUL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6CAA6C,EAAE;QAClD,IAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,8EAE3B,CAAC,CAAC;QAEC,IAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,8EAEL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { generateCode, parseModule } from 'magicast';\nimport { patchMetroInMemory } from '../../src/react-native/expo-metro';\n\ndescribe('expo-metro config', () => {\n test('patches minimal expo config', () => {\n const mod = parseModule(`\nconst { getDefaultConfig } = require(\"expo/metro-config\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getDefaultConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n `);\n\n const result = patchMetroInMemory(mod);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getSentryExpoConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n`.trim(),\n );\n });\n\n test('keeps expo metro config if other imports are present', () => {\n const mod = parseModule(`\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst config = getDefaultConfig(__dirname);\n\nmodule.exports = config;\n `);\n\n const result = patchMetroInMemory(mod);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`.trim(),\n );\n });\n\n test('does not modify when sentry already present', () => {\n const mod = parseModule(`\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n`);\n\n const result = patchMetroInMemory(mod);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n`.trim(),\n );\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var expo_1 = require("../../src/react-native/expo");
|
|
4
|
+
describe('expo', function () {
|
|
5
|
+
var MOCK_CONFIG = {
|
|
6
|
+
url: 'https://sentry.mock/',
|
|
7
|
+
org: 'sentry-mock',
|
|
8
|
+
project: 'project-mock',
|
|
9
|
+
authToken: 'authToken-mock',
|
|
10
|
+
};
|
|
11
|
+
describe('addWithSentryToAppConfigJson', function () {
|
|
12
|
+
test('do not add if sentry-expo present', function () {
|
|
13
|
+
var appConfigJson = "{\n \"expo\": {\n \"plugins\": [\"sentry-expo\"]\n }\n }";
|
|
14
|
+
expect((0, expo_1.addWithSentryToAppConfigJson)(appConfigJson, MOCK_CONFIG)).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
test('do not add if sentry-react-native/expo present', function () {
|
|
17
|
+
var appConfigJson = "{\n \"expo\": {\n \"plugins\": [\"@sentry/react-native/expo\"]\n }\n }";
|
|
18
|
+
expect((0, expo_1.addWithSentryToAppConfigJson)(appConfigJson, MOCK_CONFIG)).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
test.each([
|
|
21
|
+
[
|
|
22
|
+
"{\n \"expo\": {\n \"plugins\": \"should be an array, but it is not\"\n }\n }",
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"{\n \"expo\": [\"should be an object, but it is not\"]\n }",
|
|
26
|
+
],
|
|
27
|
+
])('do not add if plugins is not an array', function (appConfigJson) {
|
|
28
|
+
expect((0, expo_1.addWithSentryToAppConfigJson)(appConfigJson, MOCK_CONFIG)).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
test.each([
|
|
31
|
+
[
|
|
32
|
+
"{\n \"expo\": {\n \"plugins\": []\n }\n }",
|
|
33
|
+
],
|
|
34
|
+
["{}"],
|
|
35
|
+
[
|
|
36
|
+
"{\n \"expo\": {}\n }",
|
|
37
|
+
],
|
|
38
|
+
])('add sentry react native expo plugin configuration', function (appConfigJson) {
|
|
39
|
+
var result = (0, expo_1.addWithSentryToAppConfigJson)(appConfigJson, MOCK_CONFIG);
|
|
40
|
+
expect(JSON.parse(result !== null && result !== void 0 ? result : '{}')).toStrictEqual({
|
|
41
|
+
expo: {
|
|
42
|
+
plugins: [
|
|
43
|
+
[
|
|
44
|
+
'@sentry/react-native/expo',
|
|
45
|
+
{
|
|
46
|
+
url: 'https://sentry.mock/',
|
|
47
|
+
organization: 'sentry-mock',
|
|
48
|
+
project: 'project-mock',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=expo.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo.test.js","sourceRoot":"","sources":["../../../test/react-native/expo.test.ts"],"names":[],"mappings":";;AAAA,oDAA2E;AAG3E,QAAQ,CAAC,MAAM,EAAE;IACf,IAAM,WAAW,GAA4B;QAC3C,GAAG,EAAE,sBAAsB;QAC3B,GAAG,EAAE,aAAa;QAClB,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,gBAAgB;KAC5B,CAAC;IAEF,QAAQ,CAAC,8BAA8B,EAAE;QACvC,IAAI,CAAC,mCAAmC,EAAE;YACxC,IAAM,aAAa,GAAG,sFAIpB,CAAC;YACH,MAAM,CACJ,IAAA,mCAA4B,EAAC,aAAa,EAAE,WAAW,CAAC,CACzD,CAAC,QAAQ,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,gDAAgD,EAAE;YACrD,IAAM,aAAa,GAAG,oGAIpB,CAAC;YACH,MAAM,CACJ,IAAA,mCAA4B,EAAC,aAAa,EAAE,WAAW,CAAC,CACzD,CAAC,QAAQ,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC;YACR;gBACE,kHAIE;aACH;YACD;gBACE,4EAEE;aACH;SACF,CAAC,CAAC,uCAAuC,EAAE,UAAC,aAAa;YACxD,MAAM,CACJ,IAAA,mCAA4B,EAAC,aAAa,EAAE,WAAW,CAAC,CACzD,CAAC,QAAQ,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC;YACR;gBACE,+EAIE;aACH;YACD,CAAC,IAAI,CAAC;YACN;gBACE,sCAEE;aACH;SACF,CAAC,CAAC,mDAAmD,EAAE,UAAC,aAAa;YACpE,IAAM,MAAM,GAAG,IAAA,mCAA4B,EAAC,aAAa,EAAE,WAAW,CAAC,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC;gBAC/C,IAAI,EAAE;oBACJ,OAAO,EAAE;wBACP;4BACE,2BAA2B;4BAC3B;gCACE,GAAG,EAAE,sBAAsB;gCAC3B,YAAY,EAAE,aAAa;gCAC3B,OAAO,EAAE,cAAc;6BACxB;yBACF;qBACF;iBACF;aACF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { addWithSentryToAppConfigJson } from '../../src/react-native/expo';\nimport { RNCliSetupConfigContent } from '../../src/react-native/react-native-wizard';\n\ndescribe('expo', () => {\n const MOCK_CONFIG: RNCliSetupConfigContent = {\n url: 'https://sentry.mock/',\n org: 'sentry-mock',\n project: 'project-mock',\n authToken: 'authToken-mock',\n };\n\n describe('addWithSentryToAppConfigJson', () => {\n test('do not add if sentry-expo present', () => {\n const appConfigJson = `{\n \"expo\": {\n \"plugins\": [\"sentry-expo\"]\n }\n }`;\n expect(\n addWithSentryToAppConfigJson(appConfigJson, MOCK_CONFIG),\n ).toBeNull();\n });\n\n test('do not add if sentry-react-native/expo present', () => {\n const appConfigJson = `{\n \"expo\": {\n \"plugins\": [\"@sentry/react-native/expo\"]\n }\n }`;\n expect(\n addWithSentryToAppConfigJson(appConfigJson, MOCK_CONFIG),\n ).toBeNull();\n });\n\n test.each([\n [\n `{\n \"expo\": {\n \"plugins\": \"should be an array, but it is not\"\n }\n }`,\n ],\n [\n `{\n \"expo\": [\"should be an object, but it is not\"]\n }`,\n ],\n ])('do not add if plugins is not an array', (appConfigJson) => {\n expect(\n addWithSentryToAppConfigJson(appConfigJson, MOCK_CONFIG),\n ).toBeNull();\n });\n\n test.each([\n [\n `{\n \"expo\": {\n \"plugins\": []\n }\n }`,\n ],\n [`{}`],\n [\n `{\n \"expo\": {}\n }`,\n ],\n ])('add sentry react native expo plugin configuration', (appConfigJson) => {\n const result = addWithSentryToAppConfigJson(appConfigJson, MOCK_CONFIG);\n expect(JSON.parse(result ?? '{}')).toStrictEqual({\n expo: {\n plugins: [\n [\n '@sentry/react-native/expo',\n {\n url: 'https://sentry.mock/',\n organization: 'sentry-mock',\n project: 'project-mock',\n },\n ],\n ],\n },\n });\n });\n });\n});\n"]}
|
|
@@ -22,6 +22,11 @@ describe('react-native xcode', function () {
|
|
|
22
22
|
var expectedOutput = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\\\"\"";
|
|
23
23
|
expect((0, xcode_1.addSentryWithBundledScriptsToBundleShellScript)(input)).toBe(expectedOutput);
|
|
24
24
|
});
|
|
25
|
+
it('adds sentry cli to expo bundle build phase', function () {
|
|
26
|
+
var input = "\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
|
|
27
|
+
var expectedOutput = "\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n/bin/sh `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"` `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
|
|
28
|
+
expect((0, xcode_1.addSentryWithBundledScriptsToBundleShellScript)(input)).toBe(expectedOutput);
|
|
29
|
+
});
|
|
25
30
|
});
|
|
26
31
|
describe('removeSentryFromBundleShellScript', function () {
|
|
27
32
|
it('removes sentry cli from rn bundle build phase', function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xcode.test.js","sourceRoot":"","sources":["../../../test/react-native/xcode.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-useless-escape */\nimport {\n addSentryWithBundledScriptsToBundleShellScript,\n addSentryWithCliToBundleShellScript,\n doesBundlePhaseIncludeSentry,\n findBundlePhase,\n findDebugFilesUploadPhase,\n removeSentryFromBundleShellScript,\n} from '../../src/react-native/xcode';\n\ndescribe('react-native xcode', () => {\n describe('addSentryWithCliToBundleShellScript', () => {\n it('adds sentry cli to rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"`;\n // actual shell script looks like this:\n // /bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n // but during parsing xcode library removes the quotes\n const expectedOutput = `export SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\\\\"\"\n/bin/sh -c \"$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh\"\n`;\n\n expect(addSentryWithCliToBundleShellScript(input)).toBe(expectedOutput);\n });\n });\n\n describe('addSentryBundledScriptsToBundleShellScript', () => {\n it('adds sentry cli to rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"`;\n // actual shell script looks like this:\n // /bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n // but during parsing xcode library removes the quotes\n const expectedOutput = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\\\\\"\"`;\n\n expect(addSentryWithBundledScriptsToBundleShellScript(input)).toBe(\n expectedOutput,\n );\n });\n });\n\n describe('removeSentryFromBundleShellScript', () => {\n it('removes sentry cli from rn bundle build phase', () => {\n const input = `export SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\\"\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh\"\n`;\n const expectedOutput = `export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`;\n\n expect(removeSentryFromBundleShellScript(input)).toBe(expectedOutput);\n });\n\n it('removes sentry bundled scripts from rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\\\"\"`;\n const expectedOutput = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"`;\n\n expect(removeSentryFromBundleShellScript(input)).toBe(expectedOutput);\n });\n });\n\n describe('findBundlePhase', () => {\n it('returns build phase with react native xcode shell script', () => {\n const inputMap = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: 'bar',\n },\n 3: {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n },\n 4: {\n shellScript: 'qux',\n },\n };\n\n const expected = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n };\n\n expect(findBundlePhase(inputMap)).toEqual(expected);\n });\n\n it('returns undefined if bundle phase not present', () => {\n const inputMap = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: 'bar',\n },\n 3: {\n // note different path to the script\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/unknown/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n },\n 4: {\n shellScript: 'qux',\n },\n };\n\n expect(findBundlePhase(inputMap)).toBeUndefined();\n });\n });\n\n describe('doesBundlePhaseIncludeSentry', () => {\n it('returns true for script containing sentry cli calling react native xcode command', () => {\n const input = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\nSENTRY_CLI=\"sentry-cli react-native xcode\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$SENTRY_CLI $REACT_NATIVE_XCODE\\\"\"\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeTruthy();\n });\n\n it('returns true for script containing sentry bundled script', () => {\n const input = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\nSENTRY_CLI=\"sentry-cli react-native xcode\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\"\\\\\"\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeTruthy();\n });\n\n it('returns false', () => {\n const input = {\n // note sentry-cli can be part of the script but doesn't call react native xcode script\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\nsentry-cli --version\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeFalsy();\n });\n });\n\n describe('findDebugFilesUploadPhase', () => {\n it('returns debug files build phase using debug files command', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\nsentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\nsentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase with sentry-cli absolute path', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\n/path/to/bin/sentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\n/path/to/bin/sentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase using dsym command', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\nsentry-cli upload-dsym path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\nsentry-cli upload-dsym path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase using bundled scripts', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns undefined if build phase not present', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n // sentry-cli present but with different command\n shellScript: 'sentry-cli sourcempas upload',\n },\n };\n\n expect(findDebugFilesUploadPhase(input)).toBeUndefined();\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"xcode.test.js","sourceRoot":"","sources":["../../../test/react-native/xcode.test.ts"],"names":[],"mappings":";;AAAA,sCAAsC;AACtC,sDAOsC;AAEtC,QAAQ,CAAC,oBAAoB,EAAE;IAC7B,QAAQ,CAAC,qCAAqC,EAAE;QAC9C,EAAE,CAAC,0CAA0C,EAAE;YAC7C,IAAM,KAAK,GAAG,0OAK+B,CAAC;YAC9C,uCAAuC;YACvC,yDAAyD;YACzD,sDAAsD;YACtD,IAAM,cAAc,GAAG,uhBAS5B,CAAC;YAEI,MAAM,CAAC,IAAA,2CAAmC,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4CAA4C,EAAE;QACrD,EAAE,CAAC,0CAA0C,EAAE;YAC7C,IAAM,KAAK,GAAG,0OAK+B,CAAC;YAC9C,uCAAuC;YACvC,yDAAyD;YACzD,sDAAsD;YACtD,IAAM,cAAc,GAAG,uTAKiG,CAAC;YAEzH,MAAM,CAAC,IAAA,sDAA8C,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAChE,cAAc,CACf,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE;YAC/C,IAAM,KAAK,GAAG,o6CAwCnB,CAAC;YAEI,IAAM,cAAc,GAAG,sjDAwC5B,CAAC;YAEI,MAAM,CAAC,IAAA,sDAA8C,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAChE,cAAc,CACf,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE;QAC5C,EAAE,CAAC,+CAA+C,EAAE;YAClD,IAAM,KAAK,GAAG,qhBAUnB,CAAC;YACI,IAAM,cAAc,GAAG,yUAQ5B,CAAC;YAEI,MAAM,CAAC,IAAA,yCAAiC,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE;YAC9D,IAAM,KAAK,GAAG,mTAKwG,CAAC;YACvH,IAAM,cAAc,GAAG,8OAK0B,CAAC;YAElD,MAAM,CAAC,IAAA,yCAAiC,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE;QAC1B,EAAE,CAAC,0DAA0D,EAAE;YAC7D,IAAM,QAAQ,GAAG;gBACf,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,gPAMtB;iBACQ;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;aACF,CAAC;YAEF,IAAM,QAAQ,GAAG;gBACf,WAAW,EAAE,gPAMpB;aACM,CAAC;YAEF,MAAM,CAAC,IAAA,uBAAe,EAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE;YAClD,IAAM,QAAQ,GAAG;gBACf,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,oCAAoC;oBACpC,WAAW,EAAE,gPAMtB;iBACQ;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;aACF,CAAC;YAEF,MAAM,CAAC,IAAA,uBAAe,EAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE;QACvC,EAAE,CAAC,kFAAkF,EAAE;YACrF,IAAM,KAAK,GAAG;gBACZ,WAAW,EAAE,wSAMpB;aACM,CAAC;YACF,MAAM,CAAC,IAAA,oCAA4B,EAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE;YAC7D,IAAM,KAAK,GAAG;gBACZ,WAAW,EAAE,qWAMpB;aACM,CAAC;YACF,MAAM,CAAC,IAAA,oCAA4B,EAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,eAAe,EAAE;YAClB,IAAM,KAAK,GAAG;gBACZ,uFAAuF;gBACvF,WAAW,EAAE,sQAOpB;aACM,CAAC;YACF,MAAM,CAAC,IAAA,oCAA4B,EAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE;QACpC,EAAE,CAAC,2DAA2D,EAAE;YAC9D,IAAM,KAAK,GAAG;gBACZ,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,wEAEtB;iBACQ;aACF,CAAC;YACF,IAAM,QAAQ,GAAG;gBACf,GAAG;gBACH;oBACE,WAAW,EAAE,wEAEtB;iBACQ;aACF,CAAC;YACF,MAAM,CAAC,IAAA,iCAAyB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE;YAClE,IAAM,KAAK,GAAG;gBACZ,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,qFAEtB;iBACQ;aACF,CAAC;YACF,IAAM,QAAQ,GAAG;gBACf,GAAG;gBACH;oBACE,WAAW,EAAE,qFAEtB;iBACQ;aACF,CAAC;YACF,MAAM,CAAC,IAAA,iCAAyB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE;YACvD,IAAM,KAAK,GAAG;gBACZ,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,iEAEtB;iBACQ;aACF,CAAC;YACF,IAAM,QAAQ,GAAG;gBACf,GAAG;gBACH;oBACE,WAAW,EAAE,iEAEtB;iBACQ;aACF,CAAC;YACF,MAAM,CAAC,IAAA,iCAAyB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE;YAC1D,IAAM,KAAK,GAAG;gBACZ,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,WAAW,EAAE,kFAAkF;iBAChG;aACF,CAAC;YACF,IAAM,QAAQ,GAAG;gBACf,GAAG;gBACH;oBACE,WAAW,EAAE,kFAAkF;iBAChG;aACF,CAAC;YACF,MAAM,CAAC,IAAA,iCAAyB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE;YACjD,IAAM,KAAK,GAAG;gBACZ,CAAC,EAAE;oBACD,WAAW,EAAE,KAAK;iBACnB;gBACD,CAAC,EAAE;oBACD,gDAAgD;oBAChD,WAAW,EAAE,8BAA8B;iBAC5C;aACF,CAAC;YAEF,MAAM,CAAC,IAAA,iCAAyB,EAAC,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/* eslint-disable no-useless-escape */\nimport {\n addSentryWithBundledScriptsToBundleShellScript,\n addSentryWithCliToBundleShellScript,\n doesBundlePhaseIncludeSentry,\n findBundlePhase,\n findDebugFilesUploadPhase,\n removeSentryFromBundleShellScript,\n} from '../../src/react-native/xcode';\n\ndescribe('react-native xcode', () => {\n describe('addSentryWithCliToBundleShellScript', () => {\n it('adds sentry cli to rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"`;\n // actual shell script looks like this:\n // /bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n // but during parsing xcode library removes the quotes\n const expectedOutput = `export SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\\\\"\"\n/bin/sh -c \"$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh\"\n`;\n\n expect(addSentryWithCliToBundleShellScript(input)).toBe(expectedOutput);\n });\n });\n\n describe('addSentryBundledScriptsToBundleShellScript', () => {\n it('adds sentry cli to rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"`;\n // actual shell script looks like this:\n // /bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n // but during parsing xcode library removes the quotes\n const expectedOutput = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\\\\\"\"`;\n\n expect(addSentryWithBundledScriptsToBundleShellScript(input)).toBe(\n expectedOutput,\n );\n });\n\n it('adds sentry cli to expo bundle build phase', () => {\n const input = `\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n\\`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"\\`\n`;\n\n const expectedOutput = `\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n/bin/sh \\`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"\\` \\`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"\\`\n`;\n\n expect(addSentryWithBundledScriptsToBundleShellScript(input)).toBe(\n expectedOutput,\n );\n });\n });\n\n describe('removeSentryFromBundleShellScript', () => {\n it('removes sentry cli from rn bundle build phase', () => {\n const input = `export SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\\"\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh\"\n`;\n const expectedOutput = `export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`;\n\n expect(removeSentryFromBundleShellScript(input)).toBe(expectedOutput);\n });\n\n it('removes sentry bundled scripts from rn bundle build phase', () => {\n const input = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\\\"\"`;\n const expectedOutput = `set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"`;\n\n expect(removeSentryFromBundleShellScript(input)).toBe(expectedOutput);\n });\n });\n\n describe('findBundlePhase', () => {\n it('returns build phase with react native xcode shell script', () => {\n const inputMap = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: 'bar',\n },\n 3: {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n },\n 4: {\n shellScript: 'qux',\n },\n };\n\n const expected = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n };\n\n expect(findBundlePhase(inputMap)).toEqual(expected);\n });\n\n it('returns undefined if bundle phase not present', () => {\n const inputMap = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: 'bar',\n },\n 3: {\n // note different path to the script\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/unknown/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\n`,\n },\n 4: {\n shellScript: 'qux',\n },\n };\n\n expect(findBundlePhase(inputMap)).toBeUndefined();\n });\n });\n\n describe('doesBundlePhaseIncludeSentry', () => {\n it('returns true for script containing sentry cli calling react native xcode command', () => {\n const input = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\nSENTRY_CLI=\"sentry-cli react-native xcode\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$SENTRY_CLI $REACT_NATIVE_XCODE\\\"\"\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeTruthy();\n });\n\n it('returns true for script containing sentry bundled script', () => {\n const input = {\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\nSENTRY_CLI=\"sentry-cli react-native xcode\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\\\"/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode.sh $REACT_NATIVE_XCODE\"\\\\\"\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeTruthy();\n });\n\n it('returns false', () => {\n const input = {\n // note sentry-cli can be part of the script but doesn't call react native xcode script\n shellScript: `set -e\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"$REACT_NATIVE_XCODE\\\"\"\n\nsentry-cli --version\n`,\n };\n expect(doesBundlePhaseIncludeSentry(input)).toBeFalsy();\n });\n });\n\n describe('findDebugFilesUploadPhase', () => {\n it('returns debug files build phase using debug files command', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\nsentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\nsentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase with sentry-cli absolute path', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\n/path/to/bin/sentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\n/path/to/bin/sentry-cli debug-files upload path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase using dsym command', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `set -e\nsentry-cli upload-dsym path/to/dsym --include-sources\n`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `set -e\nsentry-cli upload-dsym path/to/dsym --include-sources\n`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns debug files build phase using bundled scripts', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n shellScript: `/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n },\n };\n const expected = [\n '2',\n {\n shellScript: `/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`,\n },\n ];\n expect(findDebugFilesUploadPhase(input)).toEqual(expected);\n });\n\n it('returns undefined if build phase not present', () => {\n const input = {\n 1: {\n shellScript: 'foo',\n },\n 2: {\n // sentry-cli present but with different command\n shellScript: 'sentry-cli sourcempas upload',\n },\n };\n\n expect(findDebugFilesUploadPhase(input)).toBeUndefined();\n });\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"homepage": "https://github.com/getsentry/sentry-wizard",
|
|
5
5
|
"repository": "https://github.com/getsentry/sentry-wizard",
|
|
6
6
|
"description": "Sentry wizard helping you to configure your project",
|
package/src/nextjs/templates.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function getWithSentryConfigOptionsTemplate({
|
|
|
22
22
|
|
|
23
23
|
org: "${orgSlug}",
|
|
24
24
|
project: "${projectSlug}",${
|
|
25
|
-
selfHosted ? `\n sentryUrl: "${sentryUrl}"
|
|
25
|
+
selfHosted ? `\n sentryUrl: "${sentryUrl}",` : ''
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Only print logs for uploading source maps in CI
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
2
|
+
import * as clack from '@clack/prompts';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import * as Sentry from '@sentry/node';
|
|
6
|
+
import { RNCliSetupConfigContent } from './react-native-wizard';
|
|
7
|
+
import { addToGitignore } from './git';
|
|
8
|
+
|
|
9
|
+
const EXPO_ENV_LOCAL_FILE = '.env.local';
|
|
10
|
+
|
|
11
|
+
export async function addExpoEnvLocal(
|
|
12
|
+
options: RNCliSetupConfigContent,
|
|
13
|
+
): Promise<boolean> {
|
|
14
|
+
const newContent = `#DO NOT COMMIT THIS\nSENTRY_AUTH_TOKEN=${options.authToken}\n`;
|
|
15
|
+
|
|
16
|
+
const added = await addToGitignore(EXPO_ENV_LOCAL_FILE);
|
|
17
|
+
if (added) {
|
|
18
|
+
clack.log.success(
|
|
19
|
+
`Added ${chalk.cyan(EXPO_ENV_LOCAL_FILE)} to .gitignore.`,
|
|
20
|
+
);
|
|
21
|
+
} else {
|
|
22
|
+
clack.log.error(
|
|
23
|
+
`Could not add ${chalk.cyan(
|
|
24
|
+
EXPO_ENV_LOCAL_FILE,
|
|
25
|
+
)} to .gitignore, please add it to not commit your auth key.`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!fs.existsSync(EXPO_ENV_LOCAL_FILE)) {
|
|
30
|
+
try {
|
|
31
|
+
await fs.promises.writeFile(EXPO_ENV_LOCAL_FILE, newContent);
|
|
32
|
+
Sentry.setTag('expo-env-local', 'written');
|
|
33
|
+
clack.log.success(`Written ${chalk.cyan(EXPO_ENV_LOCAL_FILE)}.`);
|
|
34
|
+
return true;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
Sentry.setTag('expo-env-local', 'write-error');
|
|
37
|
+
clack.log.error(`Unable to write ${chalk.cyan(EXPO_ENV_LOCAL_FILE)}.`);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Sentry.setTag('expo-env-local', 'exists');
|
|
43
|
+
clack.log.info(`Updating existing ${chalk.cyan(EXPO_ENV_LOCAL_FILE)}.`);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
await fs.promises.appendFile(EXPO_ENV_LOCAL_FILE, newContent);
|
|
47
|
+
Sentry.setTag('expo-env-local', 'updated');
|
|
48
|
+
clack.log.success(`Updated ${chalk.cyan(EXPO_ENV_LOCAL_FILE)}.`);
|
|
49
|
+
return true;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
Sentry.setTag('expo-env-local', 'update-error');
|
|
52
|
+
clack.log.error(`Unable to update ${chalk.cyan(EXPO_ENV_LOCAL_FILE)}.`);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
3
|
+
import * as clack from '@clack/prompts';
|
|
4
|
+
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
5
|
+
import { ProxifiedModule } from 'magicast';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import * as Sentry from '@sentry/node';
|
|
8
|
+
|
|
9
|
+
import { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';
|
|
10
|
+
import {
|
|
11
|
+
makeCodeSnippet,
|
|
12
|
+
showCopyPasteInstructions,
|
|
13
|
+
} from '../utils/clack-utils';
|
|
14
|
+
|
|
15
|
+
import { metroConfigPath, parseMetroConfig, writeMetroConfig } from './metro';
|
|
16
|
+
|
|
17
|
+
import * as recast from 'recast';
|
|
18
|
+
import x = recast.types;
|
|
19
|
+
import t = x.namedTypes;
|
|
20
|
+
|
|
21
|
+
const b = recast.types.builders;
|
|
22
|
+
|
|
23
|
+
export async function addSentryToExpoMetroConfig() {
|
|
24
|
+
if (!fs.existsSync(metroConfigPath)) {
|
|
25
|
+
const success = await createSentryExpoMetroConfig();
|
|
26
|
+
if (!success) {
|
|
27
|
+
Sentry.setTag('expo-metro-config', 'create-new-error');
|
|
28
|
+
return await showInstructions();
|
|
29
|
+
}
|
|
30
|
+
Sentry.setTag('expo-metro-config', 'created-new');
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const mod = await parseMetroConfig();
|
|
35
|
+
|
|
36
|
+
let didPatch = false;
|
|
37
|
+
try {
|
|
38
|
+
didPatch = patchMetroInMemory(mod);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// noop
|
|
41
|
+
}
|
|
42
|
+
if (!didPatch) {
|
|
43
|
+
Sentry.setTag('expo-metro-config', 'patch-error');
|
|
44
|
+
clack.log.error(
|
|
45
|
+
`Could not patch ${chalk.cyan(
|
|
46
|
+
metroConfigPath,
|
|
47
|
+
)} with Sentry configuration.`,
|
|
48
|
+
);
|
|
49
|
+
return await showInstructions();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const saved = await writeMetroConfig(mod);
|
|
53
|
+
if (saved) {
|
|
54
|
+
Sentry.setTag('expo-metro-config', 'patch-saved');
|
|
55
|
+
clack.log.success(
|
|
56
|
+
chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),
|
|
57
|
+
);
|
|
58
|
+
} else {
|
|
59
|
+
Sentry.setTag('expo-metro-config', 'patch-save-error');
|
|
60
|
+
clack.log.warn(
|
|
61
|
+
`Could not save changes to ${chalk.cyan(
|
|
62
|
+
metroConfigPath,
|
|
63
|
+
)}, please follow the manual steps.`,
|
|
64
|
+
);
|
|
65
|
+
return await showInstructions();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function patchMetroInMemory(mod: ProxifiedModule): boolean {
|
|
70
|
+
const ast = mod.$ast as t.Program;
|
|
71
|
+
|
|
72
|
+
if (hasSentryContent(ast)) {
|
|
73
|
+
clack.log.warn(
|
|
74
|
+
`The ${chalk.cyan(
|
|
75
|
+
metroConfigPath,
|
|
76
|
+
)} file already has Sentry configuration.`,
|
|
77
|
+
);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let didReplaceDefaultConfigCall = false;
|
|
82
|
+
|
|
83
|
+
recast.visit(ast, {
|
|
84
|
+
visitVariableDeclaration(path) {
|
|
85
|
+
const { node } = path;
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
// path is require("expo/metro-config")
|
|
89
|
+
// and only getDefaultConfig is being destructured
|
|
90
|
+
// then remove the entire declaration
|
|
91
|
+
node.declarations.length > 0 &&
|
|
92
|
+
node.declarations[0].type === 'VariableDeclarator' &&
|
|
93
|
+
node.declarations[0].init &&
|
|
94
|
+
node.declarations[0].init.type === 'CallExpression' &&
|
|
95
|
+
node.declarations[0].init.callee &&
|
|
96
|
+
node.declarations[0].init.callee.type === 'Identifier' &&
|
|
97
|
+
node.declarations[0].init.callee.name === 'require' &&
|
|
98
|
+
node.declarations[0].init.arguments[0].type === 'StringLiteral' &&
|
|
99
|
+
node.declarations[0].init.arguments[0].value === 'expo/metro-config' &&
|
|
100
|
+
node.declarations[0].id.type === 'ObjectPattern' &&
|
|
101
|
+
node.declarations[0].id.properties.length === 1 &&
|
|
102
|
+
node.declarations[0].id.properties[0].type === 'ObjectProperty' &&
|
|
103
|
+
node.declarations[0].id.properties[0].key.type === 'Identifier' &&
|
|
104
|
+
node.declarations[0].id.properties[0].key.name === 'getDefaultConfig'
|
|
105
|
+
) {
|
|
106
|
+
path.prune();
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.traverse(path);
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
visitCallExpression(path) {
|
|
114
|
+
const { node } = path;
|
|
115
|
+
if (
|
|
116
|
+
// path is getDefaultConfig
|
|
117
|
+
// then rename it to getSentryExpoConfig
|
|
118
|
+
node.callee.type === 'Identifier' &&
|
|
119
|
+
node.callee.name === 'getDefaultConfig'
|
|
120
|
+
) {
|
|
121
|
+
node.callee.name = 'getSentryExpoConfig';
|
|
122
|
+
didReplaceDefaultConfigCall = true;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.traverse(path);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (!didReplaceDefaultConfigCall) {
|
|
131
|
+
clack.log.warn(
|
|
132
|
+
`Could not find \`getDefaultConfig\` in ${chalk.cyan(metroConfigPath)}.`,
|
|
133
|
+
);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
addSentryExpoConfigRequire(ast);
|
|
138
|
+
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function addSentryExpoConfigRequire(program: t.Program) {
|
|
143
|
+
const lastRequireIndex = getLastRequireIndex(program);
|
|
144
|
+
const sentryExpoConfigRequire = createSentryExpoConfigRequire();
|
|
145
|
+
program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Creates const { getSentryExpoConfig } = require("@sentry/react-native/metro");
|
|
150
|
+
*/
|
|
151
|
+
function createSentryExpoConfigRequire() {
|
|
152
|
+
return b.variableDeclaration('const', [
|
|
153
|
+
b.variableDeclarator(
|
|
154
|
+
b.objectPattern([
|
|
155
|
+
b.objectProperty.from({
|
|
156
|
+
key: b.identifier('getSentryExpoConfig'),
|
|
157
|
+
value: b.identifier('getSentryExpoConfig'),
|
|
158
|
+
shorthand: true,
|
|
159
|
+
}),
|
|
160
|
+
]),
|
|
161
|
+
b.callExpression(b.identifier('require'), [
|
|
162
|
+
b.literal('@sentry/react-native/metro'),
|
|
163
|
+
]),
|
|
164
|
+
),
|
|
165
|
+
]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function createSentryExpoMetroConfig(): Promise<boolean> {
|
|
169
|
+
const snippet = `const { getSentryExpoConfig } = require("@sentry/react-native/metro");
|
|
170
|
+
|
|
171
|
+
const config = getSentryExpoConfig(__dirname);
|
|
172
|
+
|
|
173
|
+
module.exports = config;
|
|
174
|
+
`;
|
|
175
|
+
try {
|
|
176
|
+
await fs.promises.writeFile(metroConfigPath, snippet);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
clack.log.error(
|
|
179
|
+
`Could not create ${chalk.cyan(
|
|
180
|
+
metroConfigPath,
|
|
181
|
+
)} with Sentry configuration.`,
|
|
182
|
+
);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
clack.log.success(
|
|
186
|
+
`Created ${chalk.cyan(metroConfigPath)} with Sentry configuration.`,
|
|
187
|
+
);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function showInstructions() {
|
|
192
|
+
return showCopyPasteInstructions(
|
|
193
|
+
metroConfigPath,
|
|
194
|
+
getMetroWithSentryExpoConfigSnippet(true),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function getMetroWithSentryExpoConfigSnippet(colors: boolean): string {
|
|
199
|
+
return makeCodeSnippet(colors, (unchanged, plus, minus) =>
|
|
200
|
+
unchanged(`${minus(
|
|
201
|
+
`// const { getDefaultConfig } = require("expo/metro-config");`,
|
|
202
|
+
)}
|
|
203
|
+
${plus(
|
|
204
|
+
`const { getSentryExpoConfig } = require("@sentry/react-native/metro");`,
|
|
205
|
+
)}
|
|
206
|
+
|
|
207
|
+
${minus(`// const config = getDefaultConfig(__dirname);`)}
|
|
208
|
+
${plus(`const config = getSentryExpoConfig(__dirname);`)}
|
|
209
|
+
|
|
210
|
+
module.exports = config;`),
|
|
211
|
+
);
|
|
212
|
+
}
|