@sentry/wizard 3.22.2 → 3.23.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 +12 -0
- package/dist/package.json +1 -1
- package/dist/src/nextjs/templates.js +2 -2
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/react-native/javascript.js +1 -1
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/metro.d.ts +6 -1
- package/dist/src/react-native/metro.js +166 -17
- package/dist/src/react-native/metro.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.d.ts +1 -0
- package/dist/src/react-native/react-native-wizard.js +19 -20
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +1 -1
- package/dist/src/utils/ast-utils.js +2 -2
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.js +1 -1
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/test/react-native/javascript.test.js +1 -1
- package/dist/test/react-native/javascript.test.js.map +1 -1
- package/dist/test/react-native/metro.test.js +115 -0
- package/dist/test/react-native/metro.test.js.map +1 -1
- package/package.json +1 -1
- package/src/nextjs/templates.ts +2 -5
- package/src/react-native/javascript.ts +3 -0
- package/src/react-native/metro.ts +208 -18
- package/src/react-native/react-native-wizard.ts +24 -7
- package/src/utils/ast-utils.ts +2 -2
- package/src/utils/clack-utils.ts +1 -1
- package/test/react-native/javascript.test.ts +3 -0
- package/test/react-native/metro.test.ts +113 -0
|
@@ -5,7 +5,7 @@ describe('react-native javascript', function () {
|
|
|
5
5
|
describe('addSentryInitWithSdkImport', function () {
|
|
6
6
|
it('adds sdk import and sentry init under last import in the file', function () {
|
|
7
7
|
var input = "import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;";
|
|
8
|
-
var expectedOutput = "import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'dsn',\n});\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;";
|
|
8
|
+
var expectedOutput = "import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'dsn',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // enableSpotlight: __DEV__,\n});\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;";
|
|
9
9
|
expect((0, javascript_1.addSentryInitWithSdkImport)(input, { dsn: 'dsn' })).toBe(expectedOutput);
|
|
10
10
|
});
|
|
11
11
|
it('does not add sdk import and sentry init in the file without imports', function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"javascript.test.js","sourceRoot":"","sources":["../../../test/react-native/javascript.test.ts"],"names":[],"mappings":";;AAAA,gEAG2C;AAE3C,QAAQ,CAAC,yBAAyB,EAAE;IAClC,QAAQ,CAAC,4BAA4B,EAAE;QACrC,EAAE,CAAC,+DAA+D,EAAE;YAClE,IAAM,KAAK,GAAG,8MAcA,CAAC;YAEf,IAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"javascript.test.js","sourceRoot":"","sources":["../../../test/react-native/javascript.test.ts"],"names":[],"mappings":";;AAAA,gEAG2C;AAE3C,QAAQ,CAAC,yBAAyB,EAAE;IAClC,QAAQ,CAAC,4BAA4B,EAAE;QACrC,EAAE,CAAC,+DAA+D,EAAE;YAClE,IAAM,KAAK,GAAG,8MAcA,CAAC;YAEf,IAAM,cAAc,GAAG,mZAsBT,CAAC;YAEf,MAAM,CAAC,IAAA,uCAA0B,EAAC,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAC5D,cAAc,CACf,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qEAAqE,EAAE;YACxE,IAAM,KAAK,GAAG,6BAA6B,CAAC;YAC5C,MAAM,CAAC,IAAA,uCAA0B,EAAC,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE;YAC9D,IAAM,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,CAAC,IAAA,uCAA0B,EAAC,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE;QAC3C,EAAE,CAAC,qCAAqC,EAAE;YACxC,IAAM,KAAK,GAAG,+PAeA,CAAC;YAEf,MAAM,CACJ,IAAA,6CAAgC,EAAC,KAAK,EAAE;gBACtC,cAAc,EAAE,sBAAsB;aACvC,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE;YACzC,IAAM,KAAK,GAAG,+PAeA,CAAC;YAEf,MAAM,CACJ,IAAA,6CAAgC,EAAC,KAAK,EAAE;gBACtC,cAAc,EAAE,sBAAsB;aACvC,CAAC,CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE;YACnD,IAAM,KAAK,GAAG,6BAA6B,CAAC;YAC5C,MAAM,CACJ,IAAA,6CAAgC,EAAC,KAAK,EAAE;gBACtC,cAAc,EAAE,sBAAsB;aACvC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE;YACjC,IAAM,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,CACJ,IAAA,6CAAgC,EAAC,KAAK,EAAE;gBACtC,cAAc,EAAE,sBAAsB;aACvC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import {\n addSentryInitWithSdkImport,\n doesJsCodeIncludeSdkSentryImport,\n} from '../../src/react-native/javascript';\n\ndescribe('react-native javascript', () => {\n describe('addSentryInitWithSdkImport', () => {\n it('adds sdk import and sentry init under last import in the file', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n const expectedOutput = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'dsn',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // enableSpotlight: __DEV__,\n});\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(\n expectedOutput,\n );\n });\n\n it('does not add sdk import and sentry init in the file without imports', () => {\n const input = `export const test = 'test';`;\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n\n it('does not add sdk import and sentry init in the empty file', () => {\n const input = '';\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n });\n\n describe('doesJsCodeIncludeSdkSentryImport', () => {\n it('returns true if code has sdk import', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns true if code has sdk require', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nconst Sentry = require('@sentry/react-native');\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns false if code does not have sdk import', () => {\n const input = `export const test = 'test';`;\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n\n it('returns false for empty file', () => {\n const input = '';\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n });\n});\n"]}
|
|
@@ -1,9 +1,124 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
4
40
|
var magicast_1 = require("magicast");
|
|
5
41
|
var metro_1 = require("../../src/react-native/metro");
|
|
6
42
|
describe('patch metro config - sentry serializer', function () {
|
|
43
|
+
describe('patchMetroWithSentryConfigInMemory', function () {
|
|
44
|
+
it('patches react native 0.72 default metro config', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
45
|
+
var mod, result;
|
|
46
|
+
return __generator(this, function (_a) {
|
|
47
|
+
switch (_a.label) {
|
|
48
|
+
case 0:
|
|
49
|
+
mod = (0, magicast_1.parseModule)("const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = mergeConfig(getDefaultConfig(__dirname), config);");
|
|
50
|
+
return [4 /*yield*/, (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
51
|
+
return __generator(this, function (_a) {
|
|
52
|
+
return [2 /*return*/];
|
|
53
|
+
});
|
|
54
|
+
}); })];
|
|
55
|
+
case 1:
|
|
56
|
+
result = _a.sent();
|
|
57
|
+
expect(result).toBe(true);
|
|
58
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code)
|
|
59
|
+
.toBe("const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\nconst {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));");
|
|
60
|
+
return [2 /*return*/];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}); });
|
|
64
|
+
it('patches react native 0.65 default metro config', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
65
|
+
var mod, result;
|
|
66
|
+
return __generator(this, function (_a) {
|
|
67
|
+
switch (_a.label) {
|
|
68
|
+
case 0:
|
|
69
|
+
mod = (0, magicast_1.parseModule)("/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = {\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n};");
|
|
70
|
+
return [4 /*yield*/, (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
71
|
+
return __generator(this, function (_a) {
|
|
72
|
+
return [2 /*return*/];
|
|
73
|
+
});
|
|
74
|
+
}); })];
|
|
75
|
+
case 1:
|
|
76
|
+
result = _a.sent();
|
|
77
|
+
expect(result).toBe(true);
|
|
78
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = withSentryConfig({\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n});");
|
|
79
|
+
return [2 /*return*/];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}); });
|
|
83
|
+
it('patches react native metro config exported variable', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
84
|
+
var mod, result;
|
|
85
|
+
return __generator(this, function (_a) {
|
|
86
|
+
switch (_a.label) {
|
|
87
|
+
case 0:
|
|
88
|
+
mod = (0, magicast_1.parseModule)("const testConfig = {};\n\nmodule.exports = testConfig;");
|
|
89
|
+
return [4 /*yield*/, (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
90
|
+
return __generator(this, function (_a) {
|
|
91
|
+
return [2 /*return*/];
|
|
92
|
+
});
|
|
93
|
+
}); })];
|
|
94
|
+
case 1:
|
|
95
|
+
result = _a.sent();
|
|
96
|
+
expect(result).toBe(true);
|
|
97
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst testConfig = {};\n\nmodule.exports = withSentryConfig(testConfig);");
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}); });
|
|
102
|
+
it('does not patch react native metro config exported as factory function', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
103
|
+
var mod, result;
|
|
104
|
+
return __generator(this, function (_a) {
|
|
105
|
+
switch (_a.label) {
|
|
106
|
+
case 0:
|
|
107
|
+
mod = (0, magicast_1.parseModule)("module.exports = () => ({});");
|
|
108
|
+
return [4 /*yield*/, (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
109
|
+
return __generator(this, function (_a) {
|
|
110
|
+
return [2 /*return*/];
|
|
111
|
+
});
|
|
112
|
+
}); })];
|
|
113
|
+
case 1:
|
|
114
|
+
result = _a.sent();
|
|
115
|
+
expect(result).toBe(false);
|
|
116
|
+
expect((0, magicast_1.generateCode)(mod.$ast).code).toBe("module.exports = () => ({});");
|
|
117
|
+
return [2 /*return*/];
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}); });
|
|
121
|
+
});
|
|
7
122
|
describe('addSentrySerializerToMetroConfig', function () {
|
|
8
123
|
it('add to empty config', function () {
|
|
9
124
|
var mod = (0, magicast_1.parseModule)("module.exports = {\n other: 'config'\n }");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metro.test.js","sourceRoot":"","sources":["../../../test/react-native/metro.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { generateCode, type ProxifiedModule, parseModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nimport {\n addSentrySerializerRequireToMetroConfig,\n addSentrySerializerToMetroConfig,\n getMetroConfigObject,\n removeSentryRequire,\n removeSentrySerializerFromMetroConfig,\n} from '../../src/react-native/metro';\n\ndescribe('patch metro config - sentry serializer', () => {\n describe('addSentrySerializerToMetroConfig', () => {\n it('add to empty config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config'\n }`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n\n serializer: {\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('add to existing serializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('not add to existing customSerializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n });\n });\n\n describe('addSentrySerializerImportToMetroConfig', () => {\n it('add import', () => {\n const mod =\n parseModule(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nmodule.exports = {\n other: 'config'\n}`);\n const result = addSentrySerializerRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nconst {\n createSentryMetroSerializer\n} = require(\"@sentry/react-native/dist/js/tools/sentryMetroSerializer\");\n\nmodule.exports = {\n other: 'config'\n}`);\n });\n });\n\n describe('getMetroConfigObject', () => {\n it('get config object from variable called config', () => {\n const mod = parseModule(`var config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from const called config', () => {\n const mod = parseModule(`const config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config oject from let called config', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from module.exports', () => {\n const mod = parseModule(`module.exports = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n });\n\n describe('remove @sentry require', () => {\n it('nothing to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove metro serializer import', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove all sentry imports', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nvar Sentry = require('@sentry/react-native');\nlet SentryIntegrations = require('@sentry/integrations');\n\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n });\n\n describe('remove sentryMetroSerializer', () => {\n it('no custom serializer to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('no Sentry custom serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n other: 'config'\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove with wrapped serializer', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(wrappedSerializer()),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: wrappedSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n });\n });\n});\n\nfunction getModuleExportsObject(\n mod: ProxifiedModule,\n index = 0,\n): t.ObjectExpression {\n return (\n ((mod.$ast as t.Program).body[index] as t.ExpressionStatement)\n .expression as t.AssignmentExpression\n ).right as t.ObjectExpression;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metro.test.js","sourceRoot":"","sources":["../../../test/react-native/metro.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { generateCode, type ProxifiedModule, parseModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nimport {\n addSentrySerializerRequireToMetroConfig,\n addSentrySerializerToMetroConfig,\n getMetroConfigObject,\n patchMetroWithSentryConfigInMemory,\n removeSentryRequire,\n removeSentrySerializerFromMetroConfig,\n} from '../../src/react-native/metro';\n\ndescribe('patch metro config - sentry serializer', () => {\n describe('patchMetroWithSentryConfigInMemory', () => {\n it('patches react native 0.72 default metro config', async () => {\n const mod =\n parseModule(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = mergeConfig(getDefaultConfig(__dirname), config);`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\nconst {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);\n });\n\n it('patches react native 0.65 default metro config', async () => {\n const mod = parseModule(`/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = {\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n};`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = withSentryConfig({\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n});`);\n });\n\n it('patches react native metro config exported variable', async () => {\n const mod = parseModule(`const testConfig = {};\n\nmodule.exports = testConfig;`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst testConfig = {};\n\nmodule.exports = withSentryConfig(testConfig);`);\n });\n\n it('does not patch react native metro config exported as factory function', async () => {\n const mod = parseModule(`module.exports = () => ({});`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = () => ({});`);\n });\n });\n\n describe('addSentrySerializerToMetroConfig', () => {\n it('add to empty config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config'\n }`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n\n serializer: {\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('add to existing serializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('not add to existing customSerializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n });\n });\n\n describe('addSentrySerializerImportToMetroConfig', () => {\n it('add import', () => {\n const mod =\n parseModule(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nmodule.exports = {\n other: 'config'\n}`);\n const result = addSentrySerializerRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nconst {\n createSentryMetroSerializer\n} = require(\"@sentry/react-native/dist/js/tools/sentryMetroSerializer\");\n\nmodule.exports = {\n other: 'config'\n}`);\n });\n });\n\n describe('getMetroConfigObject', () => {\n it('get config object from variable called config', () => {\n const mod = parseModule(`var config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from const called config', () => {\n const mod = parseModule(`const config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config oject from let called config', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from module.exports', () => {\n const mod = parseModule(`module.exports = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n });\n\n describe('remove @sentry require', () => {\n it('nothing to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove metro serializer import', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove all sentry imports', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nvar Sentry = require('@sentry/react-native');\nlet SentryIntegrations = require('@sentry/integrations');\n\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n });\n\n describe('remove sentryMetroSerializer', () => {\n it('no custom serializer to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('no Sentry custom serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n other: 'config'\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove with wrapped serializer', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(wrappedSerializer()),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: wrappedSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n });\n });\n});\n\nfunction getModuleExportsObject(\n mod: ProxifiedModule,\n index = 0,\n): t.ObjectExpression {\n return (\n ((mod.$ast as t.Program).body[index] as t.ExpressionStatement)\n .expression as t.AssignmentExpression\n ).right as t.ObjectExpression;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.23.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
|
@@ -32,9 +32,6 @@ export function getWithSentryConfigOptionsTemplate({
|
|
|
32
32
|
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
33
33
|
widenClientFileUpload: true,
|
|
34
34
|
|
|
35
|
-
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
|
36
|
-
transpileClientSDK: true,
|
|
37
|
-
|
|
38
35
|
// ${
|
|
39
36
|
tunnelRoute ? 'Route' : 'Uncomment to route'
|
|
40
37
|
} browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
|
@@ -230,8 +227,8 @@ export default function Page() {
|
|
|
230
227
|
fontSize: "14px",
|
|
231
228
|
margin: "18px",
|
|
232
229
|
}}
|
|
233
|
-
onClick={() => {
|
|
234
|
-
Sentry.startSpan({
|
|
230
|
+
onClick={async () => {
|
|
231
|
+
await Sentry.startSpan({
|
|
235
232
|
name: 'Example Frontend Span',
|
|
236
233
|
op: 'test'
|
|
237
234
|
}, async () => {
|
|
@@ -25,11 +25,100 @@ const b = recast.types.builders;
|
|
|
25
25
|
|
|
26
26
|
const metroConfigPath = 'metro.config.js';
|
|
27
27
|
|
|
28
|
-
export async function
|
|
28
|
+
export async function patchMetroWithSentryConfig() {
|
|
29
29
|
const mod = await parseMetroConfig();
|
|
30
30
|
|
|
31
31
|
const showInstructions = () =>
|
|
32
|
-
showCopyPasteInstructions(
|
|
32
|
+
showCopyPasteInstructions(
|
|
33
|
+
metroConfigPath,
|
|
34
|
+
getMetroWithSentryConfigSnippet(true),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const success = await patchMetroWithSentryConfigInMemory(
|
|
38
|
+
mod,
|
|
39
|
+
showInstructions,
|
|
40
|
+
);
|
|
41
|
+
if (!success) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const saved = await writeMetroConfig(mod);
|
|
46
|
+
if (saved) {
|
|
47
|
+
clack.log.success(
|
|
48
|
+
chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),
|
|
49
|
+
);
|
|
50
|
+
} else {
|
|
51
|
+
clack.log.warn(
|
|
52
|
+
`Could not save changes to ${chalk.cyan(
|
|
53
|
+
metroConfigPath,
|
|
54
|
+
)}, please follow the manual steps.`,
|
|
55
|
+
);
|
|
56
|
+
return await showInstructions();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function patchMetroWithSentryConfigInMemory(
|
|
61
|
+
mod: ProxifiedModule,
|
|
62
|
+
showInstructions: () => Promise<void>,
|
|
63
|
+
): Promise<boolean> {
|
|
64
|
+
if (hasSentryContent(mod.$ast as t.Program)) {
|
|
65
|
+
const shouldContinue = await confirmPathMetroConfig();
|
|
66
|
+
if (!shouldContinue) {
|
|
67
|
+
await showInstructions();
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const configExpression = getModuleExportsAssignmentRight(
|
|
73
|
+
mod.$ast as t.Program,
|
|
74
|
+
);
|
|
75
|
+
if (!configExpression) {
|
|
76
|
+
clack.log.warn(
|
|
77
|
+
'Could not find Metro config, please follow the manual steps.',
|
|
78
|
+
);
|
|
79
|
+
await showInstructions();
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const wrappedConfig = wrapWithSentryConfig(configExpression);
|
|
84
|
+
|
|
85
|
+
const replacedModuleExportsRight = replaceModuleExportsRight(
|
|
86
|
+
mod.$ast as t.Program,
|
|
87
|
+
wrappedConfig,
|
|
88
|
+
);
|
|
89
|
+
if (!replacedModuleExportsRight) {
|
|
90
|
+
clack.log.warn(
|
|
91
|
+
'Could not automatically wrap the config export, please follow the manual steps.',
|
|
92
|
+
);
|
|
93
|
+
await showInstructions();
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const addedSentryMetroImport = addSentryMetroRequireToMetroConfig(
|
|
98
|
+
mod.$ast as t.Program,
|
|
99
|
+
);
|
|
100
|
+
if (!addedSentryMetroImport) {
|
|
101
|
+
clack.log.warn(
|
|
102
|
+
'Could not add `@sentry/react-native/metro` import to Metro config, please follow the manual steps.',
|
|
103
|
+
);
|
|
104
|
+
await showInstructions();
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
clack.log.success(
|
|
109
|
+
`Added Sentry Metro plugin to ${chalk.cyan(metroConfigPath)}.`,
|
|
110
|
+
);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function patchMetroConfigWithSentrySerializer() {
|
|
115
|
+
const mod = await parseMetroConfig();
|
|
116
|
+
|
|
117
|
+
const showInstructions = () =>
|
|
118
|
+
showCopyPasteInstructions(
|
|
119
|
+
metroConfigPath,
|
|
120
|
+
getMetroSentrySerializerSnippet(true),
|
|
121
|
+
);
|
|
33
122
|
|
|
34
123
|
if (hasSentryContent(mod.$ast as t.Program)) {
|
|
35
124
|
const shouldContinue = await confirmPathMetroConfig();
|
|
@@ -282,12 +371,51 @@ export function addSentrySerializerRequireToMetroConfig(
|
|
|
282
371
|
// insert after last require
|
|
283
372
|
program.body.splice(lastRequireIndex + 1, 0, sentrySerializerRequire);
|
|
284
373
|
} else {
|
|
285
|
-
// insert at the
|
|
286
|
-
program.body.
|
|
374
|
+
// insert at the beginning
|
|
375
|
+
program.body.unshift(sentrySerializerRequire);
|
|
376
|
+
}
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function addSentryMetroRequireToMetroConfig(
|
|
381
|
+
program: t.Program,
|
|
382
|
+
): boolean {
|
|
383
|
+
const lastRequireIndex = getLastRequireIndex(program);
|
|
384
|
+
const sentryMetroRequire = createSentryMetroRequire();
|
|
385
|
+
const sentryImportIndex = lastRequireIndex + 1;
|
|
386
|
+
if (sentryImportIndex < program.body.length) {
|
|
387
|
+
// insert after last require
|
|
388
|
+
program.body.splice(lastRequireIndex + 1, 0, sentryMetroRequire);
|
|
389
|
+
} else {
|
|
390
|
+
// insert at the beginning
|
|
391
|
+
program.body.unshift(sentryMetroRequire);
|
|
287
392
|
}
|
|
288
393
|
return true;
|
|
289
394
|
}
|
|
290
395
|
|
|
396
|
+
function wrapWithSentryConfig(
|
|
397
|
+
configObj: t.Identifier | t.CallExpression | t.ObjectExpression,
|
|
398
|
+
): t.CallExpression {
|
|
399
|
+
return b.callExpression(b.identifier('withSentryConfig'), [configObj]);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function replaceModuleExportsRight(
|
|
403
|
+
program: t.Program,
|
|
404
|
+
wrappedConfig: t.CallExpression,
|
|
405
|
+
): boolean {
|
|
406
|
+
const moduleExports = getModuleExports(program);
|
|
407
|
+
if (!moduleExports) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (moduleExports.expression.type === 'AssignmentExpression') {
|
|
412
|
+
moduleExports.expression.right = wrappedConfig;
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
291
419
|
/**
|
|
292
420
|
* Creates const {createSentryMetroSerializer} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');
|
|
293
421
|
*/
|
|
@@ -308,6 +436,26 @@ function createSentrySerializerRequire() {
|
|
|
308
436
|
]);
|
|
309
437
|
}
|
|
310
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Creates const {withSentryConfig} = require('@sentry/react-native/metro');
|
|
441
|
+
*/
|
|
442
|
+
function createSentryMetroRequire() {
|
|
443
|
+
return b.variableDeclaration('const', [
|
|
444
|
+
b.variableDeclarator(
|
|
445
|
+
b.objectPattern([
|
|
446
|
+
b.objectProperty.from({
|
|
447
|
+
key: b.identifier('withSentryConfig'),
|
|
448
|
+
value: b.identifier('withSentryConfig'),
|
|
449
|
+
shorthand: true,
|
|
450
|
+
}),
|
|
451
|
+
]),
|
|
452
|
+
b.callExpression(b.identifier('require'), [
|
|
453
|
+
b.literal('@sentry/react-native/metro'),
|
|
454
|
+
]),
|
|
455
|
+
),
|
|
456
|
+
]);
|
|
457
|
+
}
|
|
458
|
+
|
|
311
459
|
async function confirmPathMetroConfig() {
|
|
312
460
|
const shouldContinue = await abortIfCancelled(
|
|
313
461
|
clack.select({
|
|
@@ -361,8 +509,48 @@ export function getMetroConfigObject(
|
|
|
361
509
|
return configVariable.declarations[0].init;
|
|
362
510
|
}
|
|
363
511
|
|
|
512
|
+
return getModuleExportsObject(program);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function getModuleExportsObject(
|
|
516
|
+
program: t.Program,
|
|
517
|
+
): t.ObjectExpression | undefined {
|
|
518
|
+
// check module.exports
|
|
519
|
+
const moduleExports = getModuleExportsAssignmentRight(program);
|
|
520
|
+
|
|
521
|
+
if (moduleExports?.type === 'ObjectExpression') {
|
|
522
|
+
return moduleExports;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
Sentry.setTag('metro-config', 'not-found');
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export function getModuleExportsAssignmentRight(
|
|
530
|
+
program: t.Program,
|
|
531
|
+
): t.Identifier | t.CallExpression | t.ObjectExpression | undefined {
|
|
364
532
|
// check module.exports
|
|
365
|
-
const moduleExports = program
|
|
533
|
+
const moduleExports = getModuleExports(program);
|
|
534
|
+
|
|
535
|
+
if (
|
|
536
|
+
moduleExports?.expression.type === 'AssignmentExpression' &&
|
|
537
|
+
(moduleExports.expression.right.type === 'ObjectExpression' ||
|
|
538
|
+
moduleExports.expression.right.type === 'CallExpression' ||
|
|
539
|
+
moduleExports.expression.right.type === 'Identifier')
|
|
540
|
+
) {
|
|
541
|
+
Sentry.setTag('metro-config', 'module-exports');
|
|
542
|
+
return moduleExports?.expression.right;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
Sentry.setTag('metro-config', 'not-found');
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function getModuleExports(
|
|
550
|
+
program: t.Program,
|
|
551
|
+
): t.ExpressionStatement | undefined {
|
|
552
|
+
// find module.exports
|
|
553
|
+
return program.body.find((s) => {
|
|
366
554
|
if (
|
|
367
555
|
s.type === 'ExpressionStatement' &&
|
|
368
556
|
s.expression.type === 'AssignmentExpression' &&
|
|
@@ -376,21 +564,9 @@ export function getMetroConfigObject(
|
|
|
376
564
|
}
|
|
377
565
|
return false;
|
|
378
566
|
}) as t.ExpressionStatement | undefined;
|
|
379
|
-
|
|
380
|
-
if (
|
|
381
|
-
(moduleExports?.expression as t.AssignmentExpression).right.type ===
|
|
382
|
-
'ObjectExpression'
|
|
383
|
-
) {
|
|
384
|
-
Sentry.setTag('metro-config', 'module-exports');
|
|
385
|
-
return (moduleExports?.expression as t.AssignmentExpression)
|
|
386
|
-
.right as t.ObjectExpression;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
Sentry.setTag('metro-config', 'not-found');
|
|
390
|
-
return undefined;
|
|
391
567
|
}
|
|
392
568
|
|
|
393
|
-
function
|
|
569
|
+
function getMetroSentrySerializerSnippet(colors: boolean) {
|
|
394
570
|
return makeCodeSnippet(colors, (unchanged, plus, _) =>
|
|
395
571
|
unchanged(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');";
|
|
396
572
|
${plus(
|
|
@@ -407,3 +583,17 @@ module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
|
|
407
583
|
`),
|
|
408
584
|
);
|
|
409
585
|
}
|
|
586
|
+
|
|
587
|
+
function getMetroWithSentryConfigSnippet(colors: boolean) {
|
|
588
|
+
return makeCodeSnippet(colors, (unchanged, plus, _) =>
|
|
589
|
+
unchanged(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');";
|
|
590
|
+
${plus("const {withSentryConfig} = require('@sentry/react-native/metro');")}
|
|
591
|
+
|
|
592
|
+
const config = {};
|
|
593
|
+
|
|
594
|
+
module.exports = ${plus(
|
|
595
|
+
'withSentryConfig(',
|
|
596
|
+
)}mergeConfig(getDefaultConfig(__dirname), config)${plus(')')};
|
|
597
|
+
`),
|
|
598
|
+
);
|
|
599
|
+
}
|
|
@@ -50,7 +50,10 @@ import { traceStep, withTelemetry } from '../telemetry';
|
|
|
50
50
|
import * as Sentry from '@sentry/node';
|
|
51
51
|
import { fulfillsVersionRange } from '../utils/semver';
|
|
52
52
|
import { getIssueStreamUrl } from '../utils/url';
|
|
53
|
-
import {
|
|
53
|
+
import {
|
|
54
|
+
patchMetroConfigWithSentrySerializer,
|
|
55
|
+
patchMetroWithSentryConfig,
|
|
56
|
+
} from './metro';
|
|
54
57
|
|
|
55
58
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
56
59
|
const xcode = require('xcode');
|
|
@@ -69,6 +72,10 @@ export const SDK_XCODE_SCRIPTS_SUPPORTED_SDK_RANGE = '>=5.11.0';
|
|
|
69
72
|
// The following SDK version ship with Sentry Metro plugin
|
|
70
73
|
export const SDK_SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE = '>=5.11.0';
|
|
71
74
|
|
|
75
|
+
// The following SDK version shipped `withSentryConfig`
|
|
76
|
+
export const SDK_SENTRY_METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE =
|
|
77
|
+
'>=5.17.0';
|
|
78
|
+
|
|
72
79
|
export type RNCliSetupConfigContent = Pick<
|
|
73
80
|
Required<CliSetupConfigContent>,
|
|
74
81
|
'authToken' | 'org' | 'project' | 'url'
|
|
@@ -181,23 +188,33 @@ export async function runReactNativeWizardWithTelemetry(
|
|
|
181
188
|
}
|
|
182
189
|
}
|
|
183
190
|
|
|
184
|
-
|
|
191
|
+
function addSentryToMetroConfig({
|
|
185
192
|
sdkVersion,
|
|
186
193
|
}: {
|
|
187
194
|
sdkVersion: string | undefined;
|
|
188
195
|
}) {
|
|
189
196
|
if (
|
|
190
|
-
|
|
191
|
-
|
|
197
|
+
sdkVersion &&
|
|
198
|
+
fulfillsVersionRange({
|
|
192
199
|
version: sdkVersion,
|
|
193
|
-
acceptableVersions:
|
|
200
|
+
acceptableVersions:
|
|
201
|
+
SDK_SENTRY_METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE,
|
|
194
202
|
canBeLatest: true,
|
|
195
203
|
})
|
|
196
204
|
) {
|
|
197
|
-
return;
|
|
205
|
+
return patchMetroWithSentryConfig();
|
|
198
206
|
}
|
|
199
207
|
|
|
200
|
-
|
|
208
|
+
if (
|
|
209
|
+
sdkVersion &&
|
|
210
|
+
fulfillsVersionRange({
|
|
211
|
+
version: sdkVersion,
|
|
212
|
+
acceptableVersions: SDK_SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE,
|
|
213
|
+
canBeLatest: true,
|
|
214
|
+
})
|
|
215
|
+
) {
|
|
216
|
+
return patchMetroConfigWithSentrySerializer();
|
|
217
|
+
}
|
|
201
218
|
}
|
|
202
219
|
|
|
203
220
|
async function addSentryInit({ dsn }: { dsn: string }) {
|
package/src/utils/ast-utils.ts
CHANGED
|
@@ -221,10 +221,10 @@ export function printJsonC(ast: t.Program): string {
|
|
|
221
221
|
* Walks the program body and returns index of the last variable assignment initialized by require statement.
|
|
222
222
|
* Only counts top level require statements.
|
|
223
223
|
*
|
|
224
|
-
* @returns index of the last `const foo = require('bar');` statement
|
|
224
|
+
* @returns index of the last `const foo = require('bar');` statement or -1 if none was found.
|
|
225
225
|
*/
|
|
226
226
|
export function getLastRequireIndex(program: t.Program): number {
|
|
227
|
-
let lastRequireIdex =
|
|
227
|
+
let lastRequireIdex = -1;
|
|
228
228
|
program.body.forEach((s, i) => {
|
|
229
229
|
if (
|
|
230
230
|
s.type === 'VariableDeclaration' &&
|
package/src/utils/clack-utils.ts
CHANGED
|
@@ -550,7 +550,7 @@ export async function addDotEnvSentryBuildPluginFile(
|
|
|
550
550
|
# The SENTRY_AUTH_TOKEN variable is picked up by the Sentry Build Plugin.
|
|
551
551
|
# It's used for authentication when uploading source maps.
|
|
552
552
|
# You can also set this env variable in your own \`.env\` files and remove this file.
|
|
553
|
-
SENTRY_AUTH_TOKEN
|
|
553
|
+
SENTRY_AUTH_TOKEN=${authToken}
|
|
554
554
|
`;
|
|
555
555
|
|
|
556
556
|
const dotEnvFilePath = path.join(process.cwd(), SENTRY_DOT_ENV_FILE);
|