@sentry/wizard 6.1.2 → 6.2.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 +20 -0
- package/dist/e2e-tests/tests/flutter.test.js +16 -2
- package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
- package/dist/e2e-tests/tests/remix.test.js +3 -2
- package/dist/e2e-tests/tests/remix.test.js.map +1 -1
- package/dist/lib/Steps/Integrations/Electron.js +4 -0
- package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
- package/dist/src/apple/apple-wizard.js +10 -0
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/code-tools.d.ts +1 -1
- package/dist/src/apple/code-tools.js +3 -3
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/inject-code-snippet.d.ts +2 -1
- package/dist/src/apple/inject-code-snippet.js +2 -2
- package/dist/src/apple/inject-code-snippet.js.map +1 -1
- package/dist/src/apple/templates.d.ts +2 -2
- package/dist/src/apple/templates.js +22 -6
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/flutter/code-tools.d.ts +1 -0
- package/dist/src/flutter/code-tools.js +6 -0
- package/dist/src/flutter/code-tools.js.map +1 -1
- package/dist/src/flutter/templates.d.ts +1 -0
- package/dist/src/flutter/templates.js +5 -0
- package/dist/src/flutter/templates.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +11 -7
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/utils.d.ts +8 -0
- package/dist/src/nextjs/utils.js +36 -1
- package/dist/src/nextjs/utils.js.map +1 -1
- package/dist/src/react-native/expo-metro.d.ts +2 -2
- package/dist/src/react-native/expo-metro.js +32 -27
- package/dist/src/react-native/expo-metro.js.map +1 -1
- package/dist/src/react-native/metro.d.ts +4 -4
- package/dist/src/react-native/metro.js +39 -17
- package/dist/src/react-native/metro.js.map +1 -1
- package/dist/src/remix/codemods/root.d.ts +1 -0
- package/dist/src/remix/codemods/root.js +30 -2
- package/dist/src/remix/codemods/root.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/test/apple/code-tools.test.js +62 -14
- package/dist/test/apple/code-tools.test.js.map +1 -1
- package/dist/test/apple/templates.test.js +68 -2
- package/dist/test/apple/templates.test.js.map +1 -1
- package/dist/test/flutter/code-tools.test.js +1 -0
- package/dist/test/flutter/code-tools.test.js.map +1 -1
- package/dist/test/flutter/templates.test.js +28 -1
- package/dist/test/flutter/templates.test.js.map +1 -1
- package/dist/test/nextjs/wizard-double-wrap-prevention.test.d.ts +1 -0
- package/dist/test/nextjs/wizard-double-wrap-prevention.test.js +266 -0
- package/dist/test/nextjs/wizard-double-wrap-prevention.test.js.map +1 -0
- package/dist/test/react-native/expo-metro.test.js +3 -3
- package/dist/test/react-native/expo-metro.test.js.map +1 -1
- package/dist/test/react-native/metro.test.js +73 -15
- package/dist/test/react-native/metro.test.js.map +1 -1
- package/dist/test/remix/root.test.js +226 -0
- package/dist/test/remix/root.test.js.map +1 -1
- package/package.json +1 -9
|
@@ -38,49 +38,54 @@ const metro_1 = require("./metro");
|
|
|
38
38
|
const recast = __importStar(require("recast"));
|
|
39
39
|
const b = recast.types.builders;
|
|
40
40
|
async function addSentryToExpoMetroConfig() {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
let metroConfigPath = (0, metro_1.findMetroConfigPath)();
|
|
42
|
+
if (!metroConfigPath) {
|
|
43
|
+
// No existing metro config found, create metro.config.js (Expo default)
|
|
44
|
+
metroConfigPath = 'metro.config.js';
|
|
45
|
+
}
|
|
46
|
+
if (!fs.existsSync(metroConfigPath)) {
|
|
47
|
+
const success = await createSentryExpoMetroConfig(metroConfigPath);
|
|
43
48
|
if (!success) {
|
|
44
49
|
Sentry.setTag('expo-metro-config', 'create-new-error');
|
|
45
|
-
return await showInstructions();
|
|
50
|
+
return await showInstructions(metroConfigPath);
|
|
46
51
|
}
|
|
47
52
|
Sentry.setTag('expo-metro-config', 'created-new');
|
|
48
53
|
return undefined;
|
|
49
54
|
}
|
|
50
55
|
Sentry.setTag('expo-metro-config', 'exists');
|
|
51
|
-
clack.log.info(`Updating existing ${
|
|
52
|
-
const mod = await (0, metro_1.parseMetroConfig)();
|
|
56
|
+
clack.log.info(`Updating existing ${metroConfigPath}.`);
|
|
57
|
+
const mod = await (0, metro_1.parseMetroConfig)(metroConfigPath);
|
|
53
58
|
if (!mod) {
|
|
54
|
-
return await showInstructions();
|
|
59
|
+
return await showInstructions(metroConfigPath);
|
|
55
60
|
}
|
|
56
61
|
let didPatch = false;
|
|
57
62
|
try {
|
|
58
|
-
didPatch = patchMetroInMemory(mod);
|
|
63
|
+
didPatch = patchMetroInMemory(mod, metroConfigPath);
|
|
59
64
|
}
|
|
60
65
|
catch (e) {
|
|
61
66
|
Sentry.captureException('Unable to patch expo metro config');
|
|
62
67
|
}
|
|
63
68
|
if (!didPatch) {
|
|
64
69
|
Sentry.setTag('expo-metro-config', 'patch-error');
|
|
65
|
-
clack.log.error(`Could not patch ${chalk_1.default.cyan(
|
|
66
|
-
return await showInstructions();
|
|
70
|
+
clack.log.error(`Could not patch ${chalk_1.default.cyan(metroConfigPath)} with Sentry configuration.`);
|
|
71
|
+
return await showInstructions(metroConfigPath);
|
|
67
72
|
}
|
|
68
|
-
const saved = await (0, metro_1.writeMetroConfig)(mod);
|
|
73
|
+
const saved = await (0, metro_1.writeMetroConfig)(mod, metroConfigPath);
|
|
69
74
|
if (saved) {
|
|
70
75
|
Sentry.setTag('expo-metro-config', 'patch-saved');
|
|
71
|
-
clack.log.success(chalk_1.default.green(`${chalk_1.default.cyan(
|
|
76
|
+
clack.log.success(chalk_1.default.green(`${chalk_1.default.cyan(metroConfigPath)} changes saved.`));
|
|
72
77
|
}
|
|
73
78
|
else {
|
|
74
79
|
Sentry.setTag('expo-metro-config', 'patch-save-error');
|
|
75
|
-
clack.log.error(`Could not save changes to ${chalk_1.default.cyan(
|
|
76
|
-
return await showInstructions();
|
|
80
|
+
clack.log.error(`Could not save changes to ${chalk_1.default.cyan(metroConfigPath)}, please follow the manual steps.`);
|
|
81
|
+
return await showInstructions(metroConfigPath);
|
|
77
82
|
}
|
|
78
83
|
}
|
|
79
84
|
exports.addSentryToExpoMetroConfig = addSentryToExpoMetroConfig;
|
|
80
|
-
function patchMetroInMemory(mod) {
|
|
85
|
+
function patchMetroInMemory(mod, metroConfigPath) {
|
|
81
86
|
const ast = mod.$ast;
|
|
82
87
|
if ((0, ast_utils_1.hasSentryContent)(ast)) {
|
|
83
|
-
clack.log.warn(`The ${chalk_1.default.cyan(
|
|
88
|
+
clack.log.warn(`The ${chalk_1.default.cyan(metroConfigPath)} file already has Sentry configuration.`);
|
|
84
89
|
return false;
|
|
85
90
|
}
|
|
86
91
|
let didReplaceDefaultConfigCall = false;
|
|
@@ -125,14 +130,14 @@ function patchMetroInMemory(mod) {
|
|
|
125
130
|
},
|
|
126
131
|
});
|
|
127
132
|
if (!didReplaceDefaultConfigCall) {
|
|
128
|
-
clack.log.warn(`Could not find \`getDefaultConfig\` in ${chalk_1.default.cyan(
|
|
133
|
+
clack.log.warn(`Could not find \`getDefaultConfig\` in ${chalk_1.default.cyan(metroConfigPath)}.`);
|
|
129
134
|
return false;
|
|
130
135
|
}
|
|
131
|
-
addSentryExpoConfigRequire(ast);
|
|
136
|
+
addSentryExpoConfigRequire(ast, metroConfigPath);
|
|
132
137
|
return true;
|
|
133
138
|
}
|
|
134
139
|
exports.patchMetroInMemory = patchMetroInMemory;
|
|
135
|
-
function addSentryExpoConfigRequire(program) {
|
|
140
|
+
function addSentryExpoConfigRequire(program, metroConfigPath) {
|
|
136
141
|
try {
|
|
137
142
|
const lastRequireIndex = (0, ast_utils_1.getLastRequireIndex)(program);
|
|
138
143
|
const sentryExpoConfigRequire = createSentryExpoConfigRequire();
|
|
@@ -140,8 +145,8 @@ function addSentryExpoConfigRequire(program) {
|
|
|
140
145
|
program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);
|
|
141
146
|
}
|
|
142
147
|
catch (error) {
|
|
143
|
-
clack.log.error(`Could not add Sentry Expo config require statement to ${chalk_1.default.cyan(
|
|
144
|
-
Sentry.captureException(`Could not add Sentry Expo config require statement to ${
|
|
148
|
+
clack.log.error(`Could not add Sentry Expo config require statement to ${chalk_1.default.cyan(metroConfigPath)}.`);
|
|
149
|
+
Sentry.captureException(`Could not add Sentry Expo config require statement to ${metroConfigPath}.`);
|
|
145
150
|
}
|
|
146
151
|
}
|
|
147
152
|
exports.addSentryExpoConfigRequire = addSentryExpoConfigRequire;
|
|
@@ -161,7 +166,7 @@ function createSentryExpoConfigRequire() {
|
|
|
161
166
|
])),
|
|
162
167
|
]);
|
|
163
168
|
}
|
|
164
|
-
async function createSentryExpoMetroConfig() {
|
|
169
|
+
async function createSentryExpoMetroConfig(metroConfigPath) {
|
|
165
170
|
const snippet = `const { getSentryExpoConfig } = require("@sentry/react-native/metro");
|
|
166
171
|
|
|
167
172
|
const config = getSentryExpoConfig(__dirname);
|
|
@@ -169,19 +174,19 @@ const config = getSentryExpoConfig(__dirname);
|
|
|
169
174
|
module.exports = config;
|
|
170
175
|
`;
|
|
171
176
|
try {
|
|
172
|
-
await fs.promises.writeFile(
|
|
177
|
+
await fs.promises.writeFile(metroConfigPath, snippet);
|
|
173
178
|
}
|
|
174
179
|
catch (e) {
|
|
175
|
-
clack.log.error(`Could not create ${chalk_1.default.cyan(
|
|
176
|
-
Sentry.captureException(`Could not create ${
|
|
180
|
+
clack.log.error(`Could not create ${chalk_1.default.cyan(metroConfigPath)} with Sentry configuration.`);
|
|
181
|
+
Sentry.captureException(`Could not create ${metroConfigPath} with Sentry configuration.`);
|
|
177
182
|
return false;
|
|
178
183
|
}
|
|
179
|
-
clack.log.success(`Created ${chalk_1.default.cyan(
|
|
184
|
+
clack.log.success(`Created ${chalk_1.default.cyan(metroConfigPath)} with Sentry configuration.`);
|
|
180
185
|
return true;
|
|
181
186
|
}
|
|
182
|
-
function showInstructions() {
|
|
187
|
+
function showInstructions(metroConfigPath) {
|
|
183
188
|
return (0, clack_1.showCopyPasteInstructions)({
|
|
184
|
-
filename:
|
|
189
|
+
filename: metroConfigPath,
|
|
185
190
|
codeSnippet: getMetroWithSentryExpoConfigSnippet(true),
|
|
186
191
|
});
|
|
187
192
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo-metro.js","sourceRoot":"","sources":["../../../src/react-native/expo-metro.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,+EAA+E;AAC/E,sDAAwC;AAGxC,kDAA0B;AAC1B,qDAAuC;AAEvC,kDAA2E;AAC3E,0CAA4E;AAE5E,mCAA8E;AAE9E,+CAAiC;AAIjC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;AAEzB,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,uBAAe,CAAC,EAAE;QACnC,MAAM,OAAO,GAAG,MAAM,2BAA2B,EAAE,CAAC;QACpD,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;YACvD,OAAO,MAAM,gBAAgB,EAAE,CAAC;SACjC;QACD,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC;KAClB;IAED,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC7C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,uBAAe,GAAG,CAAC,CAAC;IAExD,MAAM,GAAG,GAAG,MAAM,IAAA,wBAAgB,GAAE,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE;QACR,OAAO,MAAM,gBAAgB,EAAE,CAAC;KACjC;IAED,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI;QACF,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;KACpC;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,CAAC,gBAAgB,CAAC,mCAAmC,CAAC,CAAC;KAC9D;IACD,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,mBAAmB,eAAK,CAAC,IAAI,CAC3B,uBAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,OAAO,MAAM,gBAAgB,EAAE,CAAC;KACjC;IAED,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAgB,EAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,EAAE;QACT,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,eAAK,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,iBAAiB,CAAC,CAC7D,CAAC;KACH;SAAM;QACL,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;QACvD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,6BAA6B,eAAK,CAAC,IAAI,CACrC,uBAAe,CAChB,mCAAmC,CACrC,CAAC;QACF,OAAO,MAAM,gBAAgB,EAAE,CAAC;KACjC;AACH,CAAC;AAlDD,gEAkDC;AAED,SAAgB,kBAAkB,CAAC,GAAoB;IACrD,MAAM,GAAG,GAAG,GAAG,CAAC,IAAiB,CAAC;IAElC,IAAI,IAAA,4BAAgB,EAAC,GAAG,CAAC,EAAE;QACzB,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,OAAO,eAAK,CAAC,IAAI,CACf,uBAAe,CAChB,yCAAyC,CAC3C,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,IAAI,2BAA2B,GAAG,KAAK,CAAC;IAExC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,wBAAwB,CAAC,IAAI;YAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YAEtB;YACE,uCAAuC;YACvC,kDAAkD;YAClD,qCAAqC;YACrC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;gBAC5B,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB;gBAClD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;gBACzB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;gBAChC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACtD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB;gBACpE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe;gBAChD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBAC/C,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,kBAAkB,EACrE;gBACA,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,mBAAmB,CAAC,IAAI;YACtB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YACtB;YACE,2BAA2B;YAC3B,wCAAwC;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACjC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EACvC;gBACA,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,qBAAqB,CAAC;gBACzC,2BAA2B,GAAG,IAAI,CAAC;gBACnC,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,2BAA2B,EAAE;QAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,0CAA0C,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,GAAG,CACzE,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,0BAA0B,CAAC,GAAG,CAAC,CAAC;IAEhC,OAAO,IAAI,CAAC;AACd,CAAC;AAvED,gDAuEC;AAED,SAAgB,0BAA0B,CAAC,OAAkB;IAC3D,IAAI;QACF,MAAM,gBAAgB,GAAG,IAAA,+BAAmB,EAAC,OAAO,CAAC,CAAC;QACtD,MAAM,uBAAuB,GAAG,6BAA6B,EAAE,CAAC;QAEhE,uEAAuE;QACvE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC;KACvE;IAAC,OAAO,KAAK,EAAE;QACd,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,yDAAyD,eAAK,CAAC,IAAI,CACjE,uBAAe,CAChB,GAAG,CACL,CAAC;QACF,MAAM,CAAC,gBAAgB,CACrB,yDAAyD,uBAAe,GAAG,CAC5E,CAAC;KACH;AACH,CAAC;AAjBD,gEAiBC;AAED;;GAEG;AACH,SAAS,6BAA6B;IACpC,OAAO,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE;QACpC,CAAC,CAAC,kBAAkB,CAClB,CAAC,CAAC,aAAa,CAAC;YACd,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC;gBACpB,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBACxC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBAC1C,SAAS,EAAE,IAAI;aAChB,CAAC;SACH,CAAC,EACF,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACxC,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC;SACxC,CAAC,CACH;KACF,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,2BAA2B;IACxC,MAAM,OAAO,GAAG;;;;;CAKjB,CAAC;IACA,IAAI;QACF,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,uBAAe,EAAE,OAAO,CAAC,CAAC;KACvD;IAAC,OAAO,CAAC,EAAE;QACV,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,oBAAoB,eAAK,CAAC,IAAI,CAC5B,uBAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,MAAM,CAAC,gBAAgB,CACrB,oBAAoB,uBAAe,6BAA6B,CACjE,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IACD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,WAAW,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,6BAA6B,CACpE,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAA,iCAAyB,EAAC;QAC/B,QAAQ,EAAE,uBAAe;QACzB,WAAW,EAAE,mCAAmC,CAAC,IAAI,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mCAAmC,CAAC,MAAe;IAC1D,OAAO,IAAA,uBAAe,EAAC,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CACxD,SAAS,CAAC,GAAG,KAAK,CAChB,+DAA+D,CAChE;EACH,IAAI,CACJ,wEAAwE,CACzE;;EAEC,KAAK,CAAC,gDAAgD,CAAC;EACvD,IAAI,CAAC,gDAAgD,CAAC;;yBAE/B,CAAC,CACvB,CAAC;AACJ,CAAC","sourcesContent":["import * as fs from 'node:fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\nimport chalk from 'chalk';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\n\nimport { metroConfigPath, parseMetroConfig, writeMetroConfig } from './metro';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nconst b = recast.types.builders;\n\nexport async function addSentryToExpoMetroConfig() {\n if (!fs.existsSync(metroConfigPath)) {\n const success = await createSentryExpoMetroConfig();\n if (!success) {\n Sentry.setTag('expo-metro-config', 'create-new-error');\n return await showInstructions();\n }\n Sentry.setTag('expo-metro-config', 'created-new');\n return undefined;\n }\n\n Sentry.setTag('expo-metro-config', 'exists');\n clack.log.info(`Updating existing ${metroConfigPath}.`);\n\n const mod = await parseMetroConfig();\n if (!mod) {\n return await showInstructions();\n }\n\n let didPatch = false;\n try {\n didPatch = patchMetroInMemory(mod);\n } catch (e) {\n Sentry.captureException('Unable to patch expo metro config');\n }\n if (!didPatch) {\n Sentry.setTag('expo-metro-config', 'patch-error');\n clack.log.error(\n `Could not patch ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return await showInstructions();\n }\n\n const saved = await writeMetroConfig(mod);\n if (saved) {\n Sentry.setTag('expo-metro-config', 'patch-saved');\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n Sentry.setTag('expo-metro-config', 'patch-save-error');\n clack.log.error(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n}\n\nexport function patchMetroInMemory(mod: ProxifiedModule): boolean {\n const ast = mod.$ast as t.Program;\n\n if (hasSentryContent(ast)) {\n clack.log.warn(\n `The ${chalk.cyan(\n metroConfigPath,\n )} file already has Sentry configuration.`,\n );\n return false;\n }\n\n let didReplaceDefaultConfigCall = false;\n\n recast.visit(ast, {\n visitVariableDeclaration(path) {\n const { node } = path;\n\n if (\n // path is require(\"expo/metro-config\")\n // and only getDefaultConfig is being destructured\n // then remove the entire declaration\n node.declarations.length > 0 &&\n node.declarations[0].type === 'VariableDeclarator' &&\n node.declarations[0].init &&\n node.declarations[0].init.type === 'CallExpression' &&\n node.declarations[0].init.callee &&\n node.declarations[0].init.callee.type === 'Identifier' &&\n node.declarations[0].init.callee.name === 'require' &&\n node.declarations[0].init.arguments[0].type === 'StringLiteral' &&\n node.declarations[0].init.arguments[0].value === 'expo/metro-config' &&\n node.declarations[0].id.type === 'ObjectPattern' &&\n node.declarations[0].id.properties.length === 1 &&\n node.declarations[0].id.properties[0].type === 'ObjectProperty' &&\n node.declarations[0].id.properties[0].key.type === 'Identifier' &&\n node.declarations[0].id.properties[0].key.name === 'getDefaultConfig'\n ) {\n path.prune();\n return false;\n }\n\n this.traverse(path);\n },\n\n visitCallExpression(path) {\n const { node } = path;\n if (\n // path is getDefaultConfig\n // then rename it to getSentryExpoConfig\n node.callee.type === 'Identifier' &&\n node.callee.name === 'getDefaultConfig'\n ) {\n node.callee.name = 'getSentryExpoConfig';\n didReplaceDefaultConfigCall = true;\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n if (!didReplaceDefaultConfigCall) {\n clack.log.warn(\n `Could not find \\`getDefaultConfig\\` in ${chalk.cyan(metroConfigPath)}.`,\n );\n return false;\n }\n\n addSentryExpoConfigRequire(ast);\n\n return true;\n}\n\nexport function addSentryExpoConfigRequire(program: t.Program) {\n try {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryExpoConfigRequire = createSentryExpoConfigRequire();\n\n // Add the require statement after the last require or at the beginning\n program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);\n } catch (error) {\n clack.log.error(\n `Could not add Sentry Expo config require statement to ${chalk.cyan(\n metroConfigPath,\n )}.`,\n );\n Sentry.captureException(\n `Could not add Sentry Expo config require statement to ${metroConfigPath}.`,\n );\n }\n}\n\n/**\n * Creates const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n */\nfunction createSentryExpoConfigRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('getSentryExpoConfig'),\n value: b.identifier('getSentryExpoConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function createSentryExpoMetroConfig(): Promise<boolean> {\n const snippet = `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`;\n try {\n await fs.promises.writeFile(metroConfigPath, snippet);\n } catch (e) {\n clack.log.error(\n `Could not create ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n Sentry.captureException(\n `Could not create ${metroConfigPath} with Sentry configuration.`,\n );\n return false;\n }\n clack.log.success(\n `Created ${chalk.cyan(metroConfigPath)} with Sentry configuration.`,\n );\n return true;\n}\n\nfunction showInstructions() {\n return showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryExpoConfigSnippet(true),\n });\n}\n\nfunction getMetroWithSentryExpoConfigSnippet(colors: boolean): string {\n return makeCodeSnippet(colors, (unchanged, plus, minus) =>\n unchanged(`${minus(\n `// const { getDefaultConfig } = require(\"expo/metro-config\");`,\n )}\n${plus(\n `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");`,\n)}\n\n${minus(`// const config = getDefaultConfig(__dirname);`)}\n${plus(`const config = getSentryExpoConfig(__dirname);`)}\n\nmodule.exports = config;`),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"expo-metro.js","sourceRoot":"","sources":["../../../src/react-native/expo-metro.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,+EAA+E;AAC/E,sDAAwC;AAGxC,kDAA0B;AAC1B,qDAAuC;AAEvC,kDAA2E;AAC3E,0CAA4E;AAE5E,mCAIiB;AAEjB,+CAAiC;AAIjC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;AAEzB,KAAK,UAAU,0BAA0B;IAC9C,IAAI,eAAe,GAAG,IAAA,2BAAmB,GAAE,CAAC;IAE5C,IAAI,CAAC,eAAe,EAAE;QACpB,wEAAwE;QACxE,eAAe,GAAG,iBAAiB,CAAC;KACrC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;QACnC,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,eAAe,CAAC,CAAC;QACnE,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;YACvD,OAAO,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;SAChD;QACD,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC;KAClB;IAED,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC7C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,eAAe,GAAG,CAAC,CAAC;IAExD,MAAM,GAAG,GAAG,MAAM,IAAA,wBAAgB,EAAC,eAAe,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE;QACR,OAAO,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;KAChD;IAED,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI;QACF,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;KACrD;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,CAAC,gBAAgB,CAAC,mCAAmC,CAAC,CAAC;KAC9D;IACD,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,mBAAmB,eAAK,CAAC,IAAI,CAC3B,eAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,OAAO,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;KAChD;IAED,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAgB,EAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,KAAK,EAAE;QACT,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,eAAK,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAC7D,CAAC;KACH;SAAM;QACL,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;QACvD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,6BAA6B,eAAK,CAAC,IAAI,CACrC,eAAe,CAChB,mCAAmC,CACrC,CAAC;QACF,OAAO,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;KAChD;AACH,CAAC;AAzDD,gEAyDC;AAED,SAAgB,kBAAkB,CAChC,GAAoB,EACpB,eAAuB;IAEvB,MAAM,GAAG,GAAG,GAAG,CAAC,IAAiB,CAAC;IAElC,IAAI,IAAA,4BAAgB,EAAC,GAAG,CAAC,EAAE;QACzB,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,OAAO,eAAK,CAAC,IAAI,CACf,eAAe,CAChB,yCAAyC,CAC3C,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,IAAI,2BAA2B,GAAG,KAAK,CAAC;IAExC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,wBAAwB,CAAC,IAAI;YAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YAEtB;YACE,uCAAuC;YACvC,kDAAkD;YAClD,qCAAqC;YACrC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;gBAC5B,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB;gBAClD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;gBACzB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;gBAChC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACtD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB;gBACpE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe;gBAChD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBAC/C,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,kBAAkB,EACrE;gBACA,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,mBAAmB,CAAC,IAAI;YACtB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YACtB;YACE,2BAA2B;YAC3B,wCAAwC;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACjC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EACvC;gBACA,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,qBAAqB,CAAC;gBACzC,2BAA2B,GAAG,IAAI,CAAC;gBACnC,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,2BAA2B,EAAE;QAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,0CAA0C,eAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CACzE,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,0BAA0B,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAEjD,OAAO,IAAI,CAAC;AACd,CAAC;AA1ED,gDA0EC;AAED,SAAgB,0BAA0B,CACxC,OAAkB,EAClB,eAAuB;IAEvB,IAAI;QACF,MAAM,gBAAgB,GAAG,IAAA,+BAAmB,EAAC,OAAO,CAAC,CAAC;QACtD,MAAM,uBAAuB,GAAG,6BAA6B,EAAE,CAAC;QAEhE,uEAAuE;QACvE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC;KACvE;IAAC,OAAO,KAAK,EAAE;QACd,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,yDAAyD,eAAK,CAAC,IAAI,CACjE,eAAe,CAChB,GAAG,CACL,CAAC;QACF,MAAM,CAAC,gBAAgB,CACrB,yDAAyD,eAAe,GAAG,CAC5E,CAAC;KACH;AACH,CAAC;AApBD,gEAoBC;AAED;;GAEG;AACH,SAAS,6BAA6B;IACpC,OAAO,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE;QACpC,CAAC,CAAC,kBAAkB,CAClB,CAAC,CAAC,aAAa,CAAC;YACd,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC;gBACpB,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBACxC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBAC1C,SAAS,EAAE,IAAI;aAChB,CAAC;SACH,CAAC,EACF,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACxC,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC;SACxC,CAAC,CACH;KACF,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,eAAuB;IAEvB,MAAM,OAAO,GAAG;;;;;CAKjB,CAAC;IACA,IAAI;QACF,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;KACvD;IAAC,OAAO,CAAC,EAAE;QACV,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,oBAAoB,eAAK,CAAC,IAAI,CAC5B,eAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,MAAM,CAAC,gBAAgB,CACrB,oBAAoB,eAAe,6BAA6B,CACjE,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IACD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,WAAW,eAAK,CAAC,IAAI,CAAC,eAAe,CAAC,6BAA6B,CACpE,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,eAAuB;IAC/C,OAAO,IAAA,iCAAyB,EAAC;QAC/B,QAAQ,EAAE,eAAe;QACzB,WAAW,EAAE,mCAAmC,CAAC,IAAI,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mCAAmC,CAAC,MAAe;IAC1D,OAAO,IAAA,uBAAe,EAAC,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CACxD,SAAS,CAAC,GAAG,KAAK,CAChB,+DAA+D,CAChE;EACH,IAAI,CACJ,wEAAwE,CACzE;;EAEC,KAAK,CAAC,gDAAgD,CAAC;EACvD,IAAI,CAAC,gDAAgD,CAAC;;yBAE/B,CAAC,CACvB,CAAC;AACJ,CAAC","sourcesContent":["import * as fs from 'node:fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\nimport chalk from 'chalk';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\n\nimport {\n findMetroConfigPath,\n parseMetroConfig,\n writeMetroConfig,\n} from './metro';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nconst b = recast.types.builders;\n\nexport async function addSentryToExpoMetroConfig() {\n let metroConfigPath = findMetroConfigPath();\n\n if (!metroConfigPath) {\n // No existing metro config found, create metro.config.js (Expo default)\n metroConfigPath = 'metro.config.js';\n }\n\n if (!fs.existsSync(metroConfigPath)) {\n const success = await createSentryExpoMetroConfig(metroConfigPath);\n if (!success) {\n Sentry.setTag('expo-metro-config', 'create-new-error');\n return await showInstructions(metroConfigPath);\n }\n Sentry.setTag('expo-metro-config', 'created-new');\n return undefined;\n }\n\n Sentry.setTag('expo-metro-config', 'exists');\n clack.log.info(`Updating existing ${metroConfigPath}.`);\n\n const mod = await parseMetroConfig(metroConfigPath);\n if (!mod) {\n return await showInstructions(metroConfigPath);\n }\n\n let didPatch = false;\n try {\n didPatch = patchMetroInMemory(mod, metroConfigPath);\n } catch (e) {\n Sentry.captureException('Unable to patch expo metro config');\n }\n if (!didPatch) {\n Sentry.setTag('expo-metro-config', 'patch-error');\n clack.log.error(\n `Could not patch ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return await showInstructions(metroConfigPath);\n }\n\n const saved = await writeMetroConfig(mod, metroConfigPath);\n if (saved) {\n Sentry.setTag('expo-metro-config', 'patch-saved');\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n Sentry.setTag('expo-metro-config', 'patch-save-error');\n clack.log.error(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions(metroConfigPath);\n }\n}\n\nexport function patchMetroInMemory(\n mod: ProxifiedModule,\n metroConfigPath: string,\n): boolean {\n const ast = mod.$ast as t.Program;\n\n if (hasSentryContent(ast)) {\n clack.log.warn(\n `The ${chalk.cyan(\n metroConfigPath,\n )} file already has Sentry configuration.`,\n );\n return false;\n }\n\n let didReplaceDefaultConfigCall = false;\n\n recast.visit(ast, {\n visitVariableDeclaration(path) {\n const { node } = path;\n\n if (\n // path is require(\"expo/metro-config\")\n // and only getDefaultConfig is being destructured\n // then remove the entire declaration\n node.declarations.length > 0 &&\n node.declarations[0].type === 'VariableDeclarator' &&\n node.declarations[0].init &&\n node.declarations[0].init.type === 'CallExpression' &&\n node.declarations[0].init.callee &&\n node.declarations[0].init.callee.type === 'Identifier' &&\n node.declarations[0].init.callee.name === 'require' &&\n node.declarations[0].init.arguments[0].type === 'StringLiteral' &&\n node.declarations[0].init.arguments[0].value === 'expo/metro-config' &&\n node.declarations[0].id.type === 'ObjectPattern' &&\n node.declarations[0].id.properties.length === 1 &&\n node.declarations[0].id.properties[0].type === 'ObjectProperty' &&\n node.declarations[0].id.properties[0].key.type === 'Identifier' &&\n node.declarations[0].id.properties[0].key.name === 'getDefaultConfig'\n ) {\n path.prune();\n return false;\n }\n\n this.traverse(path);\n },\n\n visitCallExpression(path) {\n const { node } = path;\n if (\n // path is getDefaultConfig\n // then rename it to getSentryExpoConfig\n node.callee.type === 'Identifier' &&\n node.callee.name === 'getDefaultConfig'\n ) {\n node.callee.name = 'getSentryExpoConfig';\n didReplaceDefaultConfigCall = true;\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n if (!didReplaceDefaultConfigCall) {\n clack.log.warn(\n `Could not find \\`getDefaultConfig\\` in ${chalk.cyan(metroConfigPath)}.`,\n );\n return false;\n }\n\n addSentryExpoConfigRequire(ast, metroConfigPath);\n\n return true;\n}\n\nexport function addSentryExpoConfigRequire(\n program: t.Program,\n metroConfigPath: string,\n) {\n try {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryExpoConfigRequire = createSentryExpoConfigRequire();\n\n // Add the require statement after the last require or at the beginning\n program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);\n } catch (error) {\n clack.log.error(\n `Could not add Sentry Expo config require statement to ${chalk.cyan(\n metroConfigPath,\n )}.`,\n );\n Sentry.captureException(\n `Could not add Sentry Expo config require statement to ${metroConfigPath}.`,\n );\n }\n}\n\n/**\n * Creates const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n */\nfunction createSentryExpoConfigRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('getSentryExpoConfig'),\n value: b.identifier('getSentryExpoConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function createSentryExpoMetroConfig(\n metroConfigPath: string,\n): Promise<boolean> {\n const snippet = `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`;\n try {\n await fs.promises.writeFile(metroConfigPath, snippet);\n } catch (e) {\n clack.log.error(\n `Could not create ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n Sentry.captureException(\n `Could not create ${metroConfigPath} with Sentry configuration.`,\n );\n return false;\n }\n clack.log.success(\n `Created ${chalk.cyan(metroConfigPath)} with Sentry configuration.`,\n );\n return true;\n}\n\nfunction showInstructions(metroConfigPath: string) {\n return showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryExpoConfigSnippet(true),\n });\n}\n\nfunction getMetroWithSentryExpoConfigSnippet(colors: boolean): string {\n return makeCodeSnippet(colors, (unchanged, plus, minus) =>\n unchanged(`${minus(\n `// const { getDefaultConfig } = require(\"expo/metro-config\");`,\n )}\n${plus(\n `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");`,\n)}\n\n${minus(`// const config = getDefaultConfig(__dirname);`)}\n${plus(`const config = getSentryExpoConfig(__dirname);`)}\n\nmodule.exports = config;`),\n );\n}\n"]}
|
|
@@ -2,11 +2,11 @@ import { ProxifiedModule } from 'magicast';
|
|
|
2
2
|
import * as recast from 'recast';
|
|
3
3
|
import x = recast.types;
|
|
4
4
|
import t = x.namedTypes;
|
|
5
|
-
export declare
|
|
5
|
+
export declare function findMetroConfigPath(): string | undefined;
|
|
6
6
|
export declare function patchMetroWithSentryConfig(): Promise<void>;
|
|
7
|
-
export declare function patchMetroWithSentryConfigInMemory(mod: ProxifiedModule,
|
|
8
|
-
export declare function parseMetroConfig(): Promise<ProxifiedModule | undefined>;
|
|
9
|
-
export declare function writeMetroConfig(mod: ProxifiedModule): Promise<boolean>;
|
|
7
|
+
export declare function patchMetroWithSentryConfigInMemory(mod: ProxifiedModule, metroConfigPath: string, skipInstructions?: boolean): Promise<boolean>;
|
|
8
|
+
export declare function parseMetroConfig(configPath: string): Promise<ProxifiedModule | undefined>;
|
|
9
|
+
export declare function writeMetroConfig(mod: ProxifiedModule, configPath: string): Promise<boolean>;
|
|
10
10
|
export declare function addSentrySerializerToMetroConfig(configObj: t.ObjectExpression): boolean;
|
|
11
11
|
export declare function addSentrySerializerRequireToMetroConfig(program: t.Program): boolean;
|
|
12
12
|
export declare function addSentryMetroRequireToMetroConfig(program: t.Program): boolean;
|
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.getModuleExportsAssignmentRight = exports.getMetroConfigObject = exports.addSentryMetroRequireToMetroConfig = exports.addSentrySerializerRequireToMetroConfig = exports.addSentrySerializerToMetroConfig = exports.writeMetroConfig = exports.parseMetroConfig = exports.patchMetroWithSentryConfigInMemory = exports.patchMetroWithSentryConfig = exports.
|
|
29
|
+
exports.getModuleExportsAssignmentRight = exports.getMetroConfigObject = exports.addSentryMetroRequireToMetroConfig = exports.addSentrySerializerRequireToMetroConfig = exports.addSentrySerializerToMetroConfig = exports.writeMetroConfig = exports.parseMetroConfig = exports.patchMetroWithSentryConfigInMemory = exports.patchMetroWithSentryConfig = exports.findMetroConfigPath = void 0;
|
|
30
30
|
// @ts-expect-error - clack is ESM and TS complains about that. It works though
|
|
31
31
|
const clack = __importStar(require("@clack/prompts"));
|
|
32
32
|
// @ts-expect-error - magicast is ESM and TS complains about that. It works though
|
|
@@ -38,32 +38,54 @@ const clack_1 = require("../utils/clack");
|
|
|
38
38
|
const recast = __importStar(require("recast"));
|
|
39
39
|
const chalk_1 = __importDefault(require("chalk"));
|
|
40
40
|
const b = recast.types.builders;
|
|
41
|
-
|
|
41
|
+
const METRO_CONFIG_FILENAMES = ['metro.config.js', 'metro.config.cjs'];
|
|
42
|
+
function findMetroConfigPath() {
|
|
43
|
+
return METRO_CONFIG_FILENAMES.find((filename) => fs.existsSync(filename));
|
|
44
|
+
}
|
|
45
|
+
exports.findMetroConfigPath = findMetroConfigPath;
|
|
42
46
|
async function patchMetroWithSentryConfig() {
|
|
47
|
+
const metroConfigPath = findMetroConfigPath();
|
|
48
|
+
if (!metroConfigPath) {
|
|
49
|
+
clack.log.error(`No Metro config file found. Expected: ${METRO_CONFIG_FILENAMES.join(' or ')}`);
|
|
50
|
+
// Fallback to .js for manual instructions
|
|
51
|
+
return await (0, clack_1.showCopyPasteInstructions)({
|
|
52
|
+
filename: 'metro.config.js',
|
|
53
|
+
codeSnippet: getMetroWithSentryConfigSnippet(true),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
43
56
|
const showInstructions = () => (0, clack_1.showCopyPasteInstructions)({
|
|
44
|
-
filename:
|
|
57
|
+
filename: metroConfigPath,
|
|
45
58
|
codeSnippet: getMetroWithSentryConfigSnippet(true),
|
|
46
59
|
});
|
|
47
|
-
const mod = await parseMetroConfig();
|
|
60
|
+
const mod = await parseMetroConfig(metroConfigPath);
|
|
48
61
|
if (!mod) {
|
|
49
|
-
clack.log.error(`Could read from file ${chalk_1.default.cyan(
|
|
62
|
+
clack.log.error(`Could not read from file ${chalk_1.default.cyan(metroConfigPath)}, please follow the manual steps.`);
|
|
50
63
|
return await showInstructions();
|
|
51
64
|
}
|
|
52
|
-
const success = await patchMetroWithSentryConfigInMemory(mod,
|
|
65
|
+
const success = await patchMetroWithSentryConfigInMemory(mod, metroConfigPath);
|
|
53
66
|
if (!success) {
|
|
54
67
|
return;
|
|
55
68
|
}
|
|
56
|
-
const saved = await writeMetroConfig(mod);
|
|
69
|
+
const saved = await writeMetroConfig(mod, metroConfigPath);
|
|
57
70
|
if (saved) {
|
|
58
|
-
clack.log.success(chalk_1.default.green(`${chalk_1.default.cyan(
|
|
71
|
+
clack.log.success(chalk_1.default.green(`${chalk_1.default.cyan(metroConfigPath)} changes saved.`));
|
|
59
72
|
}
|
|
60
73
|
else {
|
|
61
|
-
clack.log.warn(`Could not save changes to ${chalk_1.default.cyan(
|
|
74
|
+
clack.log.warn(`Could not save changes to ${chalk_1.default.cyan(metroConfigPath)}, please follow the manual steps.`);
|
|
62
75
|
return await showInstructions();
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
78
|
exports.patchMetroWithSentryConfig = patchMetroWithSentryConfig;
|
|
66
|
-
async function patchMetroWithSentryConfigInMemory(mod,
|
|
79
|
+
async function patchMetroWithSentryConfigInMemory(mod, metroConfigPath, skipInstructions = false) {
|
|
80
|
+
const showInstructions = () => {
|
|
81
|
+
if (skipInstructions) {
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
return (0, clack_1.showCopyPasteInstructions)({
|
|
85
|
+
filename: metroConfigPath,
|
|
86
|
+
codeSnippet: getMetroWithSentryConfigSnippet(true),
|
|
87
|
+
});
|
|
88
|
+
};
|
|
67
89
|
if ((0, ast_utils_1.hasSentryContent)(mod.$ast)) {
|
|
68
90
|
const shouldContinue = await confirmPathMetroConfig();
|
|
69
91
|
if (!shouldContinue) {
|
|
@@ -93,28 +115,28 @@ async function patchMetroWithSentryConfigInMemory(mod, showInstructions) {
|
|
|
93
115
|
await showInstructions();
|
|
94
116
|
return false;
|
|
95
117
|
}
|
|
96
|
-
clack.log.success(`Added Sentry Metro plugin to ${chalk_1.default.cyan(
|
|
118
|
+
clack.log.success(`Added Sentry Metro plugin to ${chalk_1.default.cyan(metroConfigPath)}.`);
|
|
97
119
|
return true;
|
|
98
120
|
}
|
|
99
121
|
exports.patchMetroWithSentryConfigInMemory = patchMetroWithSentryConfigInMemory;
|
|
100
|
-
async function parseMetroConfig() {
|
|
122
|
+
async function parseMetroConfig(configPath) {
|
|
101
123
|
try {
|
|
102
|
-
const metroConfigContent = (await fs.promises.readFile(
|
|
124
|
+
const metroConfigContent = (await fs.promises.readFile(configPath)).toString();
|
|
103
125
|
return (0, magicast_1.parseModule)(metroConfigContent);
|
|
104
126
|
}
|
|
105
127
|
catch (error) {
|
|
106
|
-
clack.log.error(`Could not read Metro config file ${chalk_1.default.cyan(
|
|
128
|
+
clack.log.error(`Could not read Metro config file ${chalk_1.default.cyan(configPath)}`);
|
|
107
129
|
Sentry.captureException('Could not read Metro config file');
|
|
108
130
|
return undefined;
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
133
|
exports.parseMetroConfig = parseMetroConfig;
|
|
112
|
-
async function writeMetroConfig(mod) {
|
|
134
|
+
async function writeMetroConfig(mod, configPath) {
|
|
113
135
|
try {
|
|
114
|
-
await (0, magicast_1.writeFile)(mod.$ast,
|
|
136
|
+
await (0, magicast_1.writeFile)(mod.$ast, configPath);
|
|
115
137
|
}
|
|
116
138
|
catch (e) {
|
|
117
|
-
clack.log.error(`Failed to write to ${chalk_1.default.cyan(
|
|
139
|
+
clack.log.error(`Failed to write to ${chalk_1.default.cyan(configPath)}: ${JSON.stringify(e)}`);
|
|
118
140
|
Sentry.captureException('Failed to write to Metro config file');
|
|
119
141
|
return false;
|
|
120
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metro.js","sourceRoot":"","sources":["../../../src/react-native/metro.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { ProxifiedModule, parseModule, writeFile } from 'magicast';\nimport * as fs from 'fs';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport {\n abortIfCancelled,\n makeCodeSnippet,\n showCopyPasteInstructions,\n} from '../utils/clack';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\nimport chalk from 'chalk';\n\nconst b = recast.types.builders;\n\nexport const metroConfigPath = 'metro.config.js';\n\nexport async function patchMetroWithSentryConfig() {\n const showInstructions = () =>\n showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryConfigSnippet(true),\n });\n\n const mod = await parseMetroConfig();\n if (!mod) {\n clack.log.error(\n `Could read from file ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n\n const success = await patchMetroWithSentryConfigInMemory(\n mod,\n showInstructions,\n );\n if (!success) {\n return;\n }\n\n const saved = await writeMetroConfig(mod);\n if (saved) {\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n clack.log.warn(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n}\n\nexport async function patchMetroWithSentryConfigInMemory(\n mod: ProxifiedModule,\n showInstructions: () => Promise<void>,\n): Promise<boolean> {\n if (hasSentryContent(mod.$ast as t.Program)) {\n const shouldContinue = await confirmPathMetroConfig();\n if (!shouldContinue) {\n await showInstructions();\n return false;\n }\n }\n\n const configExpression = getModuleExportsAssignmentRight(\n mod.$ast as t.Program,\n );\n if (!configExpression) {\n clack.log.warn(\n 'Could not find Metro config, please follow the manual steps.',\n );\n Sentry.captureException('Could not find Metro config.');\n await showInstructions();\n return false;\n }\n\n const wrappedConfig = wrapWithSentryConfig(configExpression);\n\n const replacedModuleExportsRight = replaceModuleExportsRight(\n mod.$ast as t.Program,\n wrappedConfig,\n );\n if (!replacedModuleExportsRight) {\n clack.log.warn(\n 'Could not automatically wrap the config export, please follow the manual steps.',\n );\n Sentry.captureException('Could not automatically wrap the config export.');\n await showInstructions();\n return false;\n }\n\n const addedSentryMetroImport = addSentryMetroRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n if (!addedSentryMetroImport) {\n clack.log.warn(\n 'Could not add `@sentry/react-native/metro` import to Metro config, please follow the manual steps.',\n );\n Sentry.captureException(\n 'Could not add `@sentry/react-native/metro` import to Metro config.',\n );\n await showInstructions();\n return false;\n }\n\n clack.log.success(\n `Added Sentry Metro plugin to ${chalk.cyan(metroConfigPath)}.`,\n );\n return true;\n}\n\nexport async function parseMetroConfig(): Promise<ProxifiedModule | undefined> {\n try {\n const metroConfigContent = (\n await fs.promises.readFile(metroConfigPath)\n ).toString();\n\n return parseModule(metroConfigContent);\n } catch (error) {\n clack.log.error(\n `Could not read Metro config file ${chalk.cyan(metroConfigPath)}`,\n );\n Sentry.captureException('Could not read Metro config file');\n return undefined;\n }\n}\n\nexport async function writeMetroConfig(mod: ProxifiedModule): Promise<boolean> {\n try {\n await writeFile(mod.$ast, metroConfigPath);\n } catch (e) {\n clack.log.error(\n `Failed to write to ${chalk.cyan(metroConfigPath)}: ${JSON.stringify(e)}`,\n );\n Sentry.captureException('Failed to write to Metro config file');\n return false;\n }\n return true;\n}\n\nexport function addSentrySerializerToMetroConfig(\n configObj: t.ObjectExpression,\n): boolean {\n const serializerProp = getSerializerProp(configObj);\n if ('invalid' === serializerProp) {\n return false;\n }\n\n // case 1: serializer property doesn't exist yet, so we can just add it\n if ('undefined' === serializerProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('serializer'),\n b.objectExpression([\n b.objectProperty(\n b.identifier('customSerializer'),\n b.callExpression(b.identifier('createSentryMetroSerializer'), []),\n ),\n ]),\n ),\n );\n return true;\n }\n\n const customSerializerProp = getCustomSerializerProp(serializerProp);\n // case 2: serializer.customSerializer property doesn't exist yet, so we just add it\n if (\n 'undefined' === customSerializerProp &&\n serializerProp.value.type === 'ObjectExpression'\n ) {\n serializerProp.value.properties.push(\n b.objectProperty(\n b.identifier('customSerializer'),\n b.callExpression(b.identifier('createSentryMetroSerializer'), []),\n ),\n );\n return true;\n }\n\n return false;\n}\n\nfunction getCustomSerializerProp(\n prop: t.ObjectProperty,\n): t.ObjectProperty | 'undefined' | 'invalid' {\n const customSerializerProp =\n prop.value.type === 'ObjectExpression' &&\n prop.value.properties.find(\n (p: t.ObjectProperty) =>\n p.key.type === 'Identifier' && p.key.name === 'customSerializer',\n );\n\n if (!customSerializerProp) {\n return 'undefined';\n }\n\n if (customSerializerProp.type === 'ObjectProperty') {\n return customSerializerProp;\n }\n\n return 'invalid';\n}\n\nfunction getSerializerProp(\n obj: t.ObjectExpression,\n): t.ObjectProperty | 'undefined' | 'invalid' {\n const serializerProp = obj.properties.find(\n (p: t.ObjectProperty) =>\n p.key.type === 'Identifier' && p.key.name === 'serializer',\n );\n\n if (!serializerProp) {\n return 'undefined';\n }\n\n if (serializerProp.type === 'ObjectProperty') {\n return serializerProp;\n }\n\n return 'invalid';\n}\n\nexport function addSentrySerializerRequireToMetroConfig(\n program: t.Program,\n): boolean {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentrySerializerRequire = createSentrySerializerRequire();\n const sentryImportIndex = lastRequireIndex + 1;\n if (sentryImportIndex < program.body.length) {\n // insert after last require\n program.body.splice(lastRequireIndex + 1, 0, sentrySerializerRequire);\n } else {\n // insert at the beginning\n program.body.unshift(sentrySerializerRequire);\n }\n return true;\n}\n\nexport function addSentryMetroRequireToMetroConfig(\n program: t.Program,\n): boolean {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryMetroRequire = createSentryMetroRequire();\n const sentryImportIndex = lastRequireIndex + 1;\n if (sentryImportIndex < program.body.length) {\n // insert after last require\n program.body.splice(lastRequireIndex + 1, 0, sentryMetroRequire);\n } else {\n // insert at the beginning\n program.body.unshift(sentryMetroRequire);\n }\n return true;\n}\n\nfunction wrapWithSentryConfig(\n configObj: t.Identifier | t.CallExpression | t.ObjectExpression,\n): t.CallExpression {\n return b.callExpression(b.identifier('withSentryConfig'), [configObj]);\n}\n\nfunction replaceModuleExportsRight(\n program: t.Program,\n wrappedConfig: t.CallExpression,\n): boolean {\n const moduleExports = getModuleExports(program);\n if (!moduleExports) {\n return false;\n }\n\n if (moduleExports.expression.type === 'AssignmentExpression') {\n moduleExports.expression.right = wrappedConfig;\n return true;\n }\n\n return false;\n}\n\n/**\n * Creates const {createSentryMetroSerializer} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\n */\nfunction createSentrySerializerRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('createSentryMetroSerializer'),\n value: b.identifier('createSentryMetroSerializer'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/dist/js/tools/sentryMetroSerializer'),\n ]),\n ),\n ]);\n}\n\n/**\n * Creates const {withSentryConfig} = require('@sentry/react-native/metro');\n */\nfunction createSentryMetroRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('withSentryConfig'),\n value: b.identifier('withSentryConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function confirmPathMetroConfig() {\n const shouldContinue = await abortIfCancelled(\n clack.select({\n message: `Metro Config already contains Sentry-related code. Should the wizard modify it anyway?`,\n options: [\n {\n label: 'Yes, add the Sentry Metro plugin',\n value: true,\n },\n {\n label: 'No, show me instructions to manually add the plugin',\n value: false,\n },\n ],\n initialValue: true,\n }),\n );\n\n if (!shouldContinue) {\n Sentry.setTag('ast-mod-fail-reason', 'has-sentry-content');\n }\n\n return shouldContinue;\n}\n\n/**\n * Returns value from `module.exports = value` or `const config = value`\n */\nexport function getMetroConfigObject(\n program: t.Program,\n): t.ObjectExpression | undefined {\n // check config variable\n const configVariable = program.body.find((s) => {\n if (\n s.type === 'VariableDeclaration' &&\n s.declarations.length === 1 &&\n s.declarations[0].type === 'VariableDeclarator' &&\n s.declarations[0].id.type === 'Identifier' &&\n s.declarations[0].id.name === 'config'\n ) {\n return true;\n }\n return false;\n }) as t.VariableDeclaration | undefined;\n\n if (\n configVariable?.declarations[0].type === 'VariableDeclarator' &&\n configVariable?.declarations[0].init?.type === 'ObjectExpression'\n ) {\n Sentry.setTag('metro-config', 'config-variable');\n return configVariable.declarations[0].init;\n }\n\n return getModuleExportsObject(program);\n}\n\nfunction getModuleExportsObject(\n program: t.Program,\n): t.ObjectExpression | undefined {\n // check module.exports\n const moduleExports = getModuleExportsAssignmentRight(program);\n\n if (moduleExports?.type === 'ObjectExpression') {\n return moduleExports;\n }\n\n Sentry.setTag('metro-config', 'not-found');\n return undefined;\n}\n\nexport function getModuleExportsAssignmentRight(\n program: t.Program,\n): t.Identifier | t.CallExpression | t.ObjectExpression | undefined {\n // check module.exports\n const moduleExports = getModuleExports(program);\n\n if (\n moduleExports?.expression.type === 'AssignmentExpression' &&\n (moduleExports.expression.right.type === 'ObjectExpression' ||\n moduleExports.expression.right.type === 'CallExpression' ||\n moduleExports.expression.right.type === 'Identifier')\n ) {\n Sentry.setTag('metro-config', 'module-exports');\n return moduleExports?.expression.right;\n }\n\n Sentry.setTag('metro-config', 'not-found');\n return undefined;\n}\n\nfunction getModuleExports(\n program: t.Program,\n): t.ExpressionStatement | undefined {\n // find module.exports\n return program.body.find((s) => {\n if (\n s.type === 'ExpressionStatement' &&\n s.expression.type === 'AssignmentExpression' &&\n s.expression.left.type === 'MemberExpression' &&\n s.expression.left.object.type === 'Identifier' &&\n s.expression.left.object.name === 'module' &&\n s.expression.left.property.type === 'Identifier' &&\n s.expression.left.property.name === 'exports'\n ) {\n return true;\n }\n return false;\n }) as t.ExpressionStatement | undefined;\n}\n\nfunction getMetroWithSentryConfigSnippet(colors: boolean) {\n return makeCodeSnippet(colors, (unchanged, plus, _) =>\n unchanged(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\";\n${plus(\"const {withSentryConfig} = require('@sentry/react-native/metro');\")}\n\nconst config = {};\n\nmodule.exports = ${plus(\n 'withSentryConfig(',\n )}mergeConfig(getDefaultConfig(__dirname), config)${plus(')')};\n`),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metro.js","sourceRoot":"","sources":["../../../src/react-native/metro.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { ProxifiedModule, parseModule, writeFile } from 'magicast';\nimport * as fs from 'fs';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport {\n abortIfCancelled,\n makeCodeSnippet,\n showCopyPasteInstructions,\n} from '../utils/clack';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\nimport chalk from 'chalk';\n\nconst b = recast.types.builders;\n\nconst METRO_CONFIG_FILENAMES = ['metro.config.js', 'metro.config.cjs'];\n\nexport function findMetroConfigPath(): string | undefined {\n return METRO_CONFIG_FILENAMES.find((filename) => fs.existsSync(filename));\n}\n\nexport async function patchMetroWithSentryConfig() {\n const metroConfigPath = findMetroConfigPath();\n\n if (!metroConfigPath) {\n clack.log.error(\n `No Metro config file found. Expected: ${METRO_CONFIG_FILENAMES.join(\n ' or ',\n )}`,\n );\n // Fallback to .js for manual instructions\n return await showCopyPasteInstructions({\n filename: 'metro.config.js',\n codeSnippet: getMetroWithSentryConfigSnippet(true),\n });\n }\n\n const showInstructions = () =>\n showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryConfigSnippet(true),\n });\n\n const mod = await parseMetroConfig(metroConfigPath);\n if (!mod) {\n clack.log.error(\n `Could not read from file ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n\n const success = await patchMetroWithSentryConfigInMemory(\n mod,\n metroConfigPath,\n );\n if (!success) {\n return;\n }\n\n const saved = await writeMetroConfig(mod, metroConfigPath);\n if (saved) {\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n clack.log.warn(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n}\n\nexport async function patchMetroWithSentryConfigInMemory(\n mod: ProxifiedModule,\n metroConfigPath: string,\n skipInstructions = false,\n): Promise<boolean> {\n const showInstructions = () => {\n if (skipInstructions) {\n return Promise.resolve();\n }\n return showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryConfigSnippet(true),\n });\n };\n\n if (hasSentryContent(mod.$ast as t.Program)) {\n const shouldContinue = await confirmPathMetroConfig();\n if (!shouldContinue) {\n await showInstructions();\n return false;\n }\n }\n\n const configExpression = getModuleExportsAssignmentRight(\n mod.$ast as t.Program,\n );\n if (!configExpression) {\n clack.log.warn(\n 'Could not find Metro config, please follow the manual steps.',\n );\n Sentry.captureException('Could not find Metro config.');\n await showInstructions();\n return false;\n }\n\n const wrappedConfig = wrapWithSentryConfig(configExpression);\n\n const replacedModuleExportsRight = replaceModuleExportsRight(\n mod.$ast as t.Program,\n wrappedConfig,\n );\n if (!replacedModuleExportsRight) {\n clack.log.warn(\n 'Could not automatically wrap the config export, please follow the manual steps.',\n );\n Sentry.captureException('Could not automatically wrap the config export.');\n await showInstructions();\n return false;\n }\n\n const addedSentryMetroImport = addSentryMetroRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n if (!addedSentryMetroImport) {\n clack.log.warn(\n 'Could not add `@sentry/react-native/metro` import to Metro config, please follow the manual steps.',\n );\n Sentry.captureException(\n 'Could not add `@sentry/react-native/metro` import to Metro config.',\n );\n await showInstructions();\n return false;\n }\n\n clack.log.success(\n `Added Sentry Metro plugin to ${chalk.cyan(metroConfigPath)}.`,\n );\n return true;\n}\n\nexport async function parseMetroConfig(\n configPath: string,\n): Promise<ProxifiedModule | undefined> {\n try {\n const metroConfigContent = (\n await fs.promises.readFile(configPath)\n ).toString();\n\n return parseModule(metroConfigContent);\n } catch (error) {\n clack.log.error(\n `Could not read Metro config file ${chalk.cyan(configPath)}`,\n );\n Sentry.captureException('Could not read Metro config file');\n return undefined;\n }\n}\n\nexport async function writeMetroConfig(\n mod: ProxifiedModule,\n configPath: string,\n): Promise<boolean> {\n try {\n await writeFile(mod.$ast, configPath);\n } catch (e) {\n clack.log.error(\n `Failed to write to ${chalk.cyan(configPath)}: ${JSON.stringify(e)}`,\n );\n Sentry.captureException('Failed to write to Metro config file');\n return false;\n }\n return true;\n}\n\nexport function addSentrySerializerToMetroConfig(\n configObj: t.ObjectExpression,\n): boolean {\n const serializerProp = getSerializerProp(configObj);\n if ('invalid' === serializerProp) {\n return false;\n }\n\n // case 1: serializer property doesn't exist yet, so we can just add it\n if ('undefined' === serializerProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('serializer'),\n b.objectExpression([\n b.objectProperty(\n b.identifier('customSerializer'),\n b.callExpression(b.identifier('createSentryMetroSerializer'), []),\n ),\n ]),\n ),\n );\n return true;\n }\n\n const customSerializerProp = getCustomSerializerProp(serializerProp);\n // case 2: serializer.customSerializer property doesn't exist yet, so we just add it\n if (\n 'undefined' === customSerializerProp &&\n serializerProp.value.type === 'ObjectExpression'\n ) {\n serializerProp.value.properties.push(\n b.objectProperty(\n b.identifier('customSerializer'),\n b.callExpression(b.identifier('createSentryMetroSerializer'), []),\n ),\n );\n return true;\n }\n\n return false;\n}\n\nfunction getCustomSerializerProp(\n prop: t.ObjectProperty,\n): t.ObjectProperty | 'undefined' | 'invalid' {\n const customSerializerProp =\n prop.value.type === 'ObjectExpression' &&\n prop.value.properties.find(\n (p: t.ObjectProperty) =>\n p.key.type === 'Identifier' && p.key.name === 'customSerializer',\n );\n\n if (!customSerializerProp) {\n return 'undefined';\n }\n\n if (customSerializerProp.type === 'ObjectProperty') {\n return customSerializerProp;\n }\n\n return 'invalid';\n}\n\nfunction getSerializerProp(\n obj: t.ObjectExpression,\n): t.ObjectProperty | 'undefined' | 'invalid' {\n const serializerProp = obj.properties.find(\n (p: t.ObjectProperty) =>\n p.key.type === 'Identifier' && p.key.name === 'serializer',\n );\n\n if (!serializerProp) {\n return 'undefined';\n }\n\n if (serializerProp.type === 'ObjectProperty') {\n return serializerProp;\n }\n\n return 'invalid';\n}\n\nexport function addSentrySerializerRequireToMetroConfig(\n program: t.Program,\n): boolean {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentrySerializerRequire = createSentrySerializerRequire();\n const sentryImportIndex = lastRequireIndex + 1;\n if (sentryImportIndex < program.body.length) {\n // insert after last require\n program.body.splice(lastRequireIndex + 1, 0, sentrySerializerRequire);\n } else {\n // insert at the beginning\n program.body.unshift(sentrySerializerRequire);\n }\n return true;\n}\n\nexport function addSentryMetroRequireToMetroConfig(\n program: t.Program,\n): boolean {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryMetroRequire = createSentryMetroRequire();\n const sentryImportIndex = lastRequireIndex + 1;\n if (sentryImportIndex < program.body.length) {\n // insert after last require\n program.body.splice(lastRequireIndex + 1, 0, sentryMetroRequire);\n } else {\n // insert at the beginning\n program.body.unshift(sentryMetroRequire);\n }\n return true;\n}\n\nfunction wrapWithSentryConfig(\n configObj: t.Identifier | t.CallExpression | t.ObjectExpression,\n): t.CallExpression {\n return b.callExpression(b.identifier('withSentryConfig'), [configObj]);\n}\n\nfunction replaceModuleExportsRight(\n program: t.Program,\n wrappedConfig: t.CallExpression,\n): boolean {\n const moduleExports = getModuleExports(program);\n if (!moduleExports) {\n return false;\n }\n\n if (moduleExports.expression.type === 'AssignmentExpression') {\n moduleExports.expression.right = wrappedConfig;\n return true;\n }\n\n return false;\n}\n\n/**\n * Creates const {createSentryMetroSerializer} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\n */\nfunction createSentrySerializerRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('createSentryMetroSerializer'),\n value: b.identifier('createSentryMetroSerializer'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/dist/js/tools/sentryMetroSerializer'),\n ]),\n ),\n ]);\n}\n\n/**\n * Creates const {withSentryConfig} = require('@sentry/react-native/metro');\n */\nfunction createSentryMetroRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('withSentryConfig'),\n value: b.identifier('withSentryConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function confirmPathMetroConfig() {\n const shouldContinue = await abortIfCancelled(\n clack.select({\n message: `Metro Config already contains Sentry-related code. Should the wizard modify it anyway?`,\n options: [\n {\n label: 'Yes, add the Sentry Metro plugin',\n value: true,\n },\n {\n label: 'No, show me instructions to manually add the plugin',\n value: false,\n },\n ],\n initialValue: true,\n }),\n );\n\n if (!shouldContinue) {\n Sentry.setTag('ast-mod-fail-reason', 'has-sentry-content');\n }\n\n return shouldContinue;\n}\n\n/**\n * Returns value from `module.exports = value` or `const config = value`\n */\nexport function getMetroConfigObject(\n program: t.Program,\n): t.ObjectExpression | undefined {\n // check config variable\n const configVariable = program.body.find((s) => {\n if (\n s.type === 'VariableDeclaration' &&\n s.declarations.length === 1 &&\n s.declarations[0].type === 'VariableDeclarator' &&\n s.declarations[0].id.type === 'Identifier' &&\n s.declarations[0].id.name === 'config'\n ) {\n return true;\n }\n return false;\n }) as t.VariableDeclaration | undefined;\n\n if (\n configVariable?.declarations[0].type === 'VariableDeclarator' &&\n configVariable?.declarations[0].init?.type === 'ObjectExpression'\n ) {\n Sentry.setTag('metro-config', 'config-variable');\n return configVariable.declarations[0].init;\n }\n\n return getModuleExportsObject(program);\n}\n\nfunction getModuleExportsObject(\n program: t.Program,\n): t.ObjectExpression | undefined {\n // check module.exports\n const moduleExports = getModuleExportsAssignmentRight(program);\n\n if (moduleExports?.type === 'ObjectExpression') {\n return moduleExports;\n }\n\n Sentry.setTag('metro-config', 'not-found');\n return undefined;\n}\n\nexport function getModuleExportsAssignmentRight(\n program: t.Program,\n): t.Identifier | t.CallExpression | t.ObjectExpression | undefined {\n // check module.exports\n const moduleExports = getModuleExports(program);\n\n if (\n moduleExports?.expression.type === 'AssignmentExpression' &&\n (moduleExports.expression.right.type === 'ObjectExpression' ||\n moduleExports.expression.right.type === 'CallExpression' ||\n moduleExports.expression.right.type === 'Identifier')\n ) {\n Sentry.setTag('metro-config', 'module-exports');\n return moduleExports?.expression.right;\n }\n\n Sentry.setTag('metro-config', 'not-found');\n return undefined;\n}\n\nfunction getModuleExports(\n program: t.Program,\n): t.ExpressionStatement | undefined {\n // find module.exports\n return program.body.find((s) => {\n if (\n s.type === 'ExpressionStatement' &&\n s.expression.type === 'AssignmentExpression' &&\n s.expression.left.type === 'MemberExpression' &&\n s.expression.left.object.type === 'Identifier' &&\n s.expression.left.object.name === 'module' &&\n s.expression.left.property.type === 'Identifier' &&\n s.expression.left.property.name === 'exports'\n ) {\n return true;\n }\n return false;\n }) as t.ExpressionStatement | undefined;\n}\n\nfunction getMetroWithSentryConfigSnippet(colors: boolean) {\n return makeCodeSnippet(colors, (unchanged, plus, _) =>\n unchanged(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\";\n${plus(\"const {withSentryConfig} = require('@sentry/react-native/metro');\")}\n\nconst config = {};\n\nmodule.exports = ${plus(\n 'withSentryConfig(',\n )}mergeConfig(getDefaultConfig(__dirname), config)${plus(')')};\n`),\n );\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ProxifiedModule } from 'magicast';
|
|
2
2
|
export declare function wrapAppWithSentry(rootRouteAst: ProxifiedModule, rootFileName: string): void;
|
|
3
|
+
export declare function isWithSentryAlreadyUsed(rootRouteAst: ProxifiedModule): boolean;
|
|
3
4
|
export declare function instrumentRoot(rootFileName: string): Promise<void>;
|
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.instrumentRoot = exports.wrapAppWithSentry = void 0;
|
|
29
|
+
exports.instrumentRoot = exports.isWithSentryAlreadyUsed = exports.wrapAppWithSentry = void 0;
|
|
30
30
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
31
31
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
32
32
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
@@ -70,11 +70,28 @@ function wrapAppWithSentry(rootRouteAst, rootFileName) {
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
exports.wrapAppWithSentry = wrapAppWithSentry;
|
|
73
|
+
function isWithSentryAlreadyUsed(rootRouteAst) {
|
|
74
|
+
// Check if withSentry is called anywhere in the code
|
|
75
|
+
let isUsed = false;
|
|
76
|
+
recast.visit(rootRouteAst.$ast, {
|
|
77
|
+
visitCallExpression(path) {
|
|
78
|
+
if (path.value.callee.type === 'Identifier' &&
|
|
79
|
+
path.value.callee.name === 'withSentry') {
|
|
80
|
+
isUsed = true;
|
|
81
|
+
return false; // Stop traversal
|
|
82
|
+
}
|
|
83
|
+
this.traverse(path);
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
return isUsed;
|
|
87
|
+
}
|
|
88
|
+
exports.isWithSentryAlreadyUsed = isWithSentryAlreadyUsed;
|
|
73
89
|
async function instrumentRoot(rootFileName) {
|
|
74
90
|
const rootRouteAst = await (0, magicast_1.loadFile)(path.join(process.cwd(), 'app', rootFileName));
|
|
75
91
|
const exportsAst = rootRouteAst.exports.$ast;
|
|
76
92
|
const namedExports = exportsAst.body.filter((node) => node.type === 'ExportNamedDeclaration');
|
|
77
93
|
let foundErrorBoundary = false;
|
|
94
|
+
const withSentryAlreadyUsed = isWithSentryAlreadyUsed(rootRouteAst);
|
|
78
95
|
namedExports.forEach((namedExport) => {
|
|
79
96
|
const declaration = namedExport.declaration;
|
|
80
97
|
if (!declaration) {
|
|
@@ -106,6 +123,10 @@ async function instrumentRoot(rootFileName) {
|
|
|
106
123
|
imported: 'useRouteError',
|
|
107
124
|
local: 'useRouteError',
|
|
108
125
|
});
|
|
126
|
+
// Call wrapAppWithSentry if withSentry is not already used
|
|
127
|
+
if (!withSentryAlreadyUsed) {
|
|
128
|
+
wrapAppWithSentry(rootRouteAst, rootFileName);
|
|
129
|
+
}
|
|
109
130
|
recast.visit(rootRouteAst.$ast, {
|
|
110
131
|
visitExportDefaultDeclaration(path) {
|
|
111
132
|
const implementation = recast.parse(templates_1.ERROR_BOUNDARY_TEMPLATE).program
|
|
@@ -122,7 +143,10 @@ async function instrumentRoot(rootFileName) {
|
|
|
122
143
|
imported: 'captureRemixErrorBoundaryError',
|
|
123
144
|
local: 'captureRemixErrorBoundaryError',
|
|
124
145
|
});
|
|
125
|
-
wrapAppWithSentry
|
|
146
|
+
// Call wrapAppWithSentry if withSentry is not already used
|
|
147
|
+
if (!withSentryAlreadyUsed) {
|
|
148
|
+
wrapAppWithSentry(rootRouteAst, rootFileName);
|
|
149
|
+
}
|
|
126
150
|
recast.visit(rootRouteAst.$ast, {
|
|
127
151
|
visitExportNamedDeclaration(path) {
|
|
128
152
|
// Find ErrorBoundary export
|
|
@@ -161,6 +185,10 @@ async function instrumentRoot(rootFileName) {
|
|
|
161
185
|
},
|
|
162
186
|
});
|
|
163
187
|
}
|
|
188
|
+
else if (!withSentryAlreadyUsed) {
|
|
189
|
+
// Even if we have Sentry content but withSentry is not used, we should still wrap the app
|
|
190
|
+
wrapAppWithSentry(rootRouteAst, rootFileName);
|
|
191
|
+
}
|
|
164
192
|
await (0, magicast_1.writeFile)(rootRouteAst.$ast, path.join(process.cwd(), 'app', rootFileName));
|
|
165
193
|
}
|
|
166
194
|
exports.instrumentRoot = instrumentRoot;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.js","sourceRoot":"","sources":["../../../../src/remix/codemods/root.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\nimport * as recast from 'recast';\nimport * as path from 'path';\n\nimport type { ExportNamedDeclaration, Program } from '@babel/types';\n\nimport {\n builders,\n generateCode,\n loadFile,\n ProxifiedModule,\n writeFile,\n // @ts-expect-error - magicast is ESM and TS complains about that. It works though\n} from 'magicast';\n\nimport { ERROR_BOUNDARY_TEMPLATE } from '../templates';\nimport { hasSentryContent } from '../utils';\nimport chalk from 'chalk';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n\nexport function wrapAppWithSentry(\n rootRouteAst: ProxifiedModule,\n rootFileName: string,\n) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'withSentry',\n local: 'withSentry',\n });\n\n recast.visit(rootRouteAst.$ast, {\n visitExportDefaultDeclaration(path) {\n if (path.value.declaration.type === 'FunctionDeclaration') {\n // Move the function declaration just before the default export\n path.insertBefore(path.value.declaration);\n\n // Get the name of the function to be wrapped\n const functionName: string = path.value.declaration.id.name as string;\n\n // Create the wrapped function call\n const functionCall = recast.types.builders.callExpression(\n recast.types.builders.identifier('withSentry'),\n [recast.types.builders.identifier(functionName)],\n );\n\n // Replace the default export with the wrapped function call\n path.value.declaration = functionCall;\n } else if (path.value.declaration.type === 'Identifier') {\n const rootRouteExport = rootRouteAst.exports.default;\n\n const expressionToWrap = generateCode(rootRouteExport.$ast).code;\n\n rootRouteAst.exports.default = builders.raw(\n `withSentry(${expressionToWrap})`,\n );\n } else {\n clack.log.warn(\n chalk.yellow(\n `Couldn't instrument ${chalk.bold(\n rootFileName,\n )} automatically. Wrap your default export with: ${chalk.dim(\n 'withSentry()',\n )}\\n`,\n ),\n );\n }\n\n this.traverse(path);\n },\n });\n}\n\nexport async function instrumentRoot(rootFileName: string): Promise<void> {\n const rootRouteAst = await loadFile(\n path.join(process.cwd(), 'app', rootFileName),\n );\n\n const exportsAst = rootRouteAst.exports.$ast as Program;\n\n const namedExports = exportsAst.body.filter(\n (node) => node.type === 'ExportNamedDeclaration',\n ) as ExportNamedDeclaration[];\n\n let foundErrorBoundary = false;\n\n namedExports.forEach((namedExport) => {\n const declaration = namedExport.declaration;\n\n if (!declaration) {\n return;\n }\n\n if (declaration.type === 'FunctionDeclaration') {\n if (declaration.id?.name === 'ErrorBoundary') {\n foundErrorBoundary = true;\n }\n } else if (declaration.type === 'VariableDeclaration') {\n const declarations = declaration.declarations;\n\n declarations.forEach((declaration) => {\n // @ts-expect-error - id should always have a name in this case\n if (declaration.id?.name === 'ErrorBoundary') {\n foundErrorBoundary = true;\n }\n });\n }\n });\n\n if (!foundErrorBoundary) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'captureRemixErrorBoundaryError',\n local: 'captureRemixErrorBoundaryError',\n });\n\n rootRouteAst.imports.$add({\n from: '@remix-run/react',\n imported: 'useRouteError',\n local: 'useRouteError',\n });\n\n recast.visit(rootRouteAst.$ast, {\n visitExportDefaultDeclaration(path) {\n const implementation = recast.parse(ERROR_BOUNDARY_TEMPLATE).program\n .body[0];\n\n path.insertBefore(\n recast.types.builders.exportDeclaration(false, implementation),\n );\n\n this.traverse(path);\n },\n });\n // If there is already a ErrorBoundary export, and it doesn't have Sentry content\n } else if (!hasSentryContent(rootFileName, rootRouteAst.$code)) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'captureRemixErrorBoundaryError',\n local: 'captureRemixErrorBoundaryError',\n });\n\n wrapAppWithSentry(rootRouteAst, rootFileName);\n\n recast.visit(rootRouteAst.$ast, {\n visitExportNamedDeclaration(path) {\n // Find ErrorBoundary export\n if (path.value.declaration?.id?.name === 'ErrorBoundary') {\n const errorBoundaryExport = path.value.declaration;\n\n let errorIdentifier;\n\n // check if useRouteError is called\n recast.visit(errorBoundaryExport, {\n visitVariableDeclaration(path) {\n const variableDeclaration = path.value.declarations[0];\n const initializer = variableDeclaration.init;\n\n if (\n initializer.type === 'CallExpression' &&\n initializer.callee.name === 'useRouteError'\n ) {\n errorIdentifier = variableDeclaration.id.name;\n }\n\n this.traverse(path);\n },\n });\n\n // We don't have an errorIdentifier, which means useRouteError is not called / imported\n // We need to add it and capture the error\n if (!errorIdentifier) {\n rootRouteAst.imports.$add({\n from: '@remix-run/react',\n imported: 'useRouteError',\n local: 'useRouteError',\n });\n\n const useRouteErrorCall = recast.parse(\n `const error = useRouteError();`,\n ).program.body[0];\n\n // Insert at the top of ErrorBoundary body\n errorBoundaryExport.body.body.splice(0, 0, useRouteErrorCall);\n }\n\n const captureErrorCall = recast.parse(\n `captureRemixErrorBoundaryError(error);`,\n ).program.body[0];\n\n // Insert just before the the fallback page is returned\n errorBoundaryExport.body.body.splice(\n errorBoundaryExport.body.body.length - 1,\n 0,\n captureErrorCall,\n );\n }\n this.traverse(path);\n },\n });\n }\n\n await writeFile(\n rootRouteAst.$ast,\n path.join(process.cwd(), 'app', rootFileName),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"root.js","sourceRoot":"","sources":["../../../../src/remix/codemods/root.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\nimport * as recast from 'recast';\nimport * as path from 'path';\n\nimport type { ExportNamedDeclaration, Program } from '@babel/types';\n\nimport {\n builders,\n generateCode,\n loadFile,\n ProxifiedModule,\n writeFile,\n // @ts-expect-error - magicast is ESM and TS complains about that. It works though\n} from 'magicast';\n\nimport { ERROR_BOUNDARY_TEMPLATE } from '../templates';\nimport { hasSentryContent } from '../utils';\nimport chalk from 'chalk';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n\nexport function wrapAppWithSentry(\n rootRouteAst: ProxifiedModule,\n rootFileName: string,\n) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'withSentry',\n local: 'withSentry',\n });\n\n recast.visit(rootRouteAst.$ast, {\n visitExportDefaultDeclaration(path) {\n if (path.value.declaration.type === 'FunctionDeclaration') {\n // Move the function declaration just before the default export\n path.insertBefore(path.value.declaration);\n\n // Get the name of the function to be wrapped\n const functionName: string = path.value.declaration.id.name as string;\n\n // Create the wrapped function call\n const functionCall = recast.types.builders.callExpression(\n recast.types.builders.identifier('withSentry'),\n [recast.types.builders.identifier(functionName)],\n );\n\n // Replace the default export with the wrapped function call\n path.value.declaration = functionCall;\n } else if (path.value.declaration.type === 'Identifier') {\n const rootRouteExport = rootRouteAst.exports.default;\n\n const expressionToWrap = generateCode(rootRouteExport.$ast).code;\n\n rootRouteAst.exports.default = builders.raw(\n `withSentry(${expressionToWrap})`,\n );\n } else {\n clack.log.warn(\n chalk.yellow(\n `Couldn't instrument ${chalk.bold(\n rootFileName,\n )} automatically. Wrap your default export with: ${chalk.dim(\n 'withSentry()',\n )}\\n`,\n ),\n );\n }\n\n this.traverse(path);\n },\n });\n}\n\nexport function isWithSentryAlreadyUsed(\n rootRouteAst: ProxifiedModule,\n): boolean {\n // Check if withSentry is called anywhere in the code\n let isUsed = false;\n recast.visit(rootRouteAst.$ast, {\n visitCallExpression(path) {\n if (\n path.value.callee.type === 'Identifier' &&\n path.value.callee.name === 'withSentry'\n ) {\n isUsed = true;\n return false; // Stop traversal\n }\n this.traverse(path);\n },\n });\n return isUsed;\n}\n\nexport async function instrumentRoot(rootFileName: string): Promise<void> {\n const rootRouteAst = await loadFile(\n path.join(process.cwd(), 'app', rootFileName),\n );\n\n const exportsAst = rootRouteAst.exports.$ast as Program;\n\n const namedExports = exportsAst.body.filter(\n (node) => node.type === 'ExportNamedDeclaration',\n ) as ExportNamedDeclaration[];\n\n let foundErrorBoundary = false;\n const withSentryAlreadyUsed = isWithSentryAlreadyUsed(rootRouteAst);\n\n namedExports.forEach((namedExport) => {\n const declaration = namedExport.declaration;\n\n if (!declaration) {\n return;\n }\n\n if (declaration.type === 'FunctionDeclaration') {\n if (declaration.id?.name === 'ErrorBoundary') {\n foundErrorBoundary = true;\n }\n } else if (declaration.type === 'VariableDeclaration') {\n const declarations = declaration.declarations;\n\n declarations.forEach((declaration) => {\n // @ts-expect-error - id should always have a name in this case\n if (declaration.id?.name === 'ErrorBoundary') {\n foundErrorBoundary = true;\n }\n });\n }\n });\n\n if (!foundErrorBoundary) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'captureRemixErrorBoundaryError',\n local: 'captureRemixErrorBoundaryError',\n });\n\n rootRouteAst.imports.$add({\n from: '@remix-run/react',\n imported: 'useRouteError',\n local: 'useRouteError',\n });\n\n // Call wrapAppWithSentry if withSentry is not already used\n if (!withSentryAlreadyUsed) {\n wrapAppWithSentry(rootRouteAst, rootFileName);\n }\n\n recast.visit(rootRouteAst.$ast, {\n visitExportDefaultDeclaration(path) {\n const implementation = recast.parse(ERROR_BOUNDARY_TEMPLATE).program\n .body[0];\n\n path.insertBefore(\n recast.types.builders.exportDeclaration(false, implementation),\n );\n\n this.traverse(path);\n },\n });\n // If there is already a ErrorBoundary export, and it doesn't have Sentry content\n } else if (!hasSentryContent(rootFileName, rootRouteAst.$code)) {\n rootRouteAst.imports.$add({\n from: '@sentry/remix',\n imported: 'captureRemixErrorBoundaryError',\n local: 'captureRemixErrorBoundaryError',\n });\n\n // Call wrapAppWithSentry if withSentry is not already used\n if (!withSentryAlreadyUsed) {\n wrapAppWithSentry(rootRouteAst, rootFileName);\n }\n\n recast.visit(rootRouteAst.$ast, {\n visitExportNamedDeclaration(path) {\n // Find ErrorBoundary export\n if (path.value.declaration?.id?.name === 'ErrorBoundary') {\n const errorBoundaryExport = path.value.declaration;\n\n let errorIdentifier;\n\n // check if useRouteError is called\n recast.visit(errorBoundaryExport, {\n visitVariableDeclaration(path) {\n const variableDeclaration = path.value.declarations[0];\n const initializer = variableDeclaration.init;\n\n if (\n initializer.type === 'CallExpression' &&\n initializer.callee.name === 'useRouteError'\n ) {\n errorIdentifier = variableDeclaration.id.name;\n }\n\n this.traverse(path);\n },\n });\n\n // We don't have an errorIdentifier, which means useRouteError is not called / imported\n // We need to add it and capture the error\n if (!errorIdentifier) {\n rootRouteAst.imports.$add({\n from: '@remix-run/react',\n imported: 'useRouteError',\n local: 'useRouteError',\n });\n\n const useRouteErrorCall = recast.parse(\n `const error = useRouteError();`,\n ).program.body[0];\n\n // Insert at the top of ErrorBoundary body\n errorBoundaryExport.body.body.splice(0, 0, useRouteErrorCall);\n }\n\n const captureErrorCall = recast.parse(\n `captureRemixErrorBoundaryError(error);`,\n ).program.body[0];\n\n // Insert just before the the fallback page is returned\n errorBoundaryExport.body.body.splice(\n errorBoundaryExport.body.body.length - 1,\n 0,\n captureErrorCall,\n );\n }\n this.traverse(path);\n },\n });\n } else if (!withSentryAlreadyUsed) {\n // Even if we have Sentry content but withSentry is not used, we should still wrap the app\n wrapAppWithSentry(rootRouteAst, rootFileName);\n }\n\n await writeFile(\n rootRouteAst.$ast,\n path.join(process.cwd(), 'app', rootFileName),\n );\n}\n"]}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const WIZARD_VERSION = "6.
|
|
1
|
+
export declare const WIZARD_VERSION = "6.2.0";
|
package/dist/src/version.js
CHANGED
package/dist/src/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";AAAA,oCAAoC;AACpC,2CAA2C;;;AAE9B,QAAA,cAAc,GAAG,OAAO,CAAC","sourcesContent":["// DO NOT modify this file manually!\n// This is file is updated at release time.\n\nexport const WIZARD_VERSION = '6.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";AAAA,oCAAoC;AACpC,2CAA2C;;;AAE9B,QAAA,cAAc,GAAG,OAAO,CAAC","sourcesContent":["// DO NOT modify this file manually!\n// This is file is updated at release time.\n\nexport const WIZARD_VERSION = '6.2.0';\n"]}
|