@sentry/wizard 6.1.1 → 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 +24 -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/angular/angular-wizard.js +1 -1
- package/dist/src/angular/angular-wizard.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 +12 -8
- 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/nuxt/nuxt-wizard.js +1 -1
- package/dist/src/nuxt/nuxt-wizard.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/remix/remix-wizard.js +1 -1
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.test.js","sourceRoot":"","sources":["../../../test/flutter/templates.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,2DAIqC;AAErC,IAAA,iBAAQ,EAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAA,iBAAQ,EAAC,SAAS,EAAE,GAAG,EAAE;QACvB,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,QAAQ,GAAG,IAAA,0BAAc,EAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;YAClE,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;aAOhC,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAA,iBAAQ,EAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,QAAQ,GAAG,IAAA,4BAAgB,EAAC,eAAe,CAAC,CAAC;YACnD,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,4BAA4B,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAA,iBAAQ,EAAC,MAAM,EAAE,GAAG,EAAE;QACpB,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAC1B,QAAQ,EACR;gBACE,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;
|
|
1
|
+
{"version":3,"file":"templates.test.js","sourceRoot":"","sources":["../../../test/flutter/templates.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,2DAIqC;AAErC,IAAA,iBAAQ,EAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAA,iBAAQ,EAAC,SAAS,EAAE,GAAG,EAAE;QACvB,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,QAAQ,GAAG,IAAA,0BAAc,EAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;YAClE,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;aAOhC,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAA,iBAAQ,EAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,QAAQ,GAAG,IAAA,4BAAgB,EAAC,eAAe,CAAC,CAAC;YACnD,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,4BAA4B,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAA,iBAAQ,EAAC,MAAM,EAAE,GAAG,EAAE;QACpB,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAC1B,QAAQ,EACR;gBACE,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,IAAI;aACX,EACD,eAAe,CAChB,CAAC;YACF,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;OAsBtC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAC1B,QAAQ,EACR;gBACE,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,IAAI;aACX,EACD,eAAe,CAChB,CAAC;YACF,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;OAgBtC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,2EAA2E,EAAE,GAAG,EAAE;YACnF,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAC1B,QAAQ,EACR;gBACE,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,KAAK;aACZ,EACD,eAAe,CAChB,CAAC;YACF,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;OAYtC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAC1B,QAAQ,EACR;gBACE,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,IAAI;aACX,EACD,eAAe,CAChB,CAAC;YACF,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;OAatC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from 'vitest';\nimport {\n pubspecOptions,\n sentryProperties,\n initSnippet,\n} from '../../src/flutter/templates';\n\ndescribe('Flutter code templates', () => {\n describe('pubspec', () => {\n it('generates pubspec with project and org', () => {\n const template = pubspecOptions('fixture-project', 'fixture-org');\n expect(template).toMatchInlineSnapshot(`\n \"sentry:\n upload_debug_symbols: true\n upload_source_maps: true\n project: fixture-project\n org: fixture-org\n \"\n `);\n });\n });\n describe('sentry.properties', () => {\n it('generates sentry.properties with token', () => {\n const template = sentryProperties('fixture-token');\n expect(template).toMatchInlineSnapshot(`\"auth_token=fixture-token\"`);\n });\n });\n describe('init', () => {\n it('generates Sentry config with all features enabled', () => {\n const template = initSnippet(\n 'my-dsn',\n {\n tracing: true,\n profiling: true,\n replay: true,\n logs: true,\n },\n 'const MyApp()',\n );\n expect(template).toMatchInlineSnapshot(`\n \"await SentryFlutter.init(\n (options) {\n options.dsn = 'my-dsn';\n // Adds request headers and IP for users, for more info visit:\n // https://docs.sentry.io/platforms/dart/guides/flutter/data-management/data-collected/\n options.sendDefaultPii = true;\n options.enableLogs = true;\n // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.\n // We recommend adjusting this value in production.\n options.tracesSampleRate = 1.0;\n // The sampling rate for profiling is relative to tracesSampleRate\n // Setting to 1.0 will profile 100% of sampled transactions:\n options.profilesSampleRate = 1.0;\n // Configure Session Replay\n options.replay.sessionSampleRate = 0.1;\n options.replay.onErrorSampleRate = 1.0;\n },\n appRunner: () => runApp(SentryWidget(child: const MyApp())),\n );\n // TODO: Remove this line after sending the first sample event to sentry.\n await Sentry.captureException(StateError('This is a sample exception.'));\"\n `);\n });\n\n it('generates Sentry config with profiling & replay disabled', () => {\n const template = initSnippet(\n 'my-dsn',\n {\n tracing: true,\n profiling: false,\n replay: false,\n logs: true,\n },\n 'const MyApp()',\n );\n expect(template).toMatchInlineSnapshot(`\n \"await SentryFlutter.init(\n (options) {\n options.dsn = 'my-dsn';\n // Adds request headers and IP for users, for more info visit:\n // https://docs.sentry.io/platforms/dart/guides/flutter/data-management/data-collected/\n options.sendDefaultPii = true;\n options.enableLogs = true;\n // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.\n // We recommend adjusting this value in production.\n options.tracesSampleRate = 1.0;\n },\n appRunner: () => runApp(SentryWidget(child: const MyApp())),\n );\n // TODO: Remove this line after sending the first sample event to sentry.\n await Sentry.captureException(StateError('This is a sample exception.'));\"\n `);\n });\n\n it('generates Sentry config with tracing, profiling, replay and logs disabled', () => {\n const template = initSnippet(\n 'my-dsn',\n {\n tracing: false,\n profiling: false,\n replay: false,\n logs: false,\n },\n 'const MyApp()',\n );\n expect(template).toMatchInlineSnapshot(`\n \"await SentryFlutter.init(\n (options) {\n options.dsn = 'my-dsn';\n // Adds request headers and IP for users, for more info visit:\n // https://docs.sentry.io/platforms/dart/guides/flutter/data-management/data-collected/\n options.sendDefaultPii = true;\n },\n appRunner: () => runApp(SentryWidget(child: const MyApp())),\n );\n // TODO: Remove this line after sending the first sample event to sentry.\n await Sentry.captureException(StateError('This is a sample exception.'));\"\n `);\n });\n\n it('generates Sentry config with only structured logs enabled', () => {\n const template = initSnippet(\n 'my-dsn',\n {\n tracing: false,\n profiling: false,\n replay: false,\n logs: true,\n },\n 'const MyApp()',\n );\n expect(template).toMatchInlineSnapshot(`\n \"await SentryFlutter.init(\n (options) {\n options.dsn = 'my-dsn';\n // Adds request headers and IP for users, for more info visit:\n // https://docs.sentry.io/platforms/dart/guides/flutter/data-management/data-collected/\n options.sendDefaultPii = true;\n options.enableLogs = true;\n },\n appRunner: () => runApp(SentryWidget(child: const MyApp())),\n );\n // TODO: Remove this line after sending the first sample event to sentry.\n await Sentry.captureException(StateError('This is a sample exception.'));\"\n `);\n });\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
// @ts-expect-error - magicast is ESM and TS complains about that. It works though
|
|
5
|
+
const magicast_1 = require("magicast");
|
|
6
|
+
const templates_1 = require("../../src/nextjs/templates");
|
|
7
|
+
const utils_1 = require("../../src/nextjs/utils");
|
|
8
|
+
(0, vitest_1.describe)('Next.js wizard double wrap prevention', () => {
|
|
9
|
+
const mockWithSentryConfigOptionsTemplate = (0, templates_1.getWithSentryConfigOptionsTemplate)({
|
|
10
|
+
orgSlug: 'test-org',
|
|
11
|
+
projectSlug: 'test-project',
|
|
12
|
+
selfHosted: false,
|
|
13
|
+
sentryUrl: 'https://sentry.io',
|
|
14
|
+
tunnelRoute: false,
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.describe)('unwrapSentryConfigAst utility function', () => {
|
|
17
|
+
(0, vitest_1.describe)('AST-based expression unwrapping', () => {
|
|
18
|
+
(0, vitest_1.it)('keeps code without withSentryConfig', () => {
|
|
19
|
+
const mod = (0, magicast_1.parseModule)('export default nextConfig');
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
21
|
+
const originalAST = mod.exports.default.$ast;
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
23
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
24
|
+
(0, vitest_1.expect)(resultAST).toBe(originalAST);
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
26
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
27
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"nextConfig"`);
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)('should handle plain object literal exports', () => {
|
|
30
|
+
const mod = (0, magicast_1.parseModule)(`export default { nextConfig: { randomValue: true } }`);
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
32
|
+
const originalAST = mod.exports.default.$ast;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
34
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
35
|
+
(0, vitest_1.expect)(resultAST).toBe(originalAST);
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
37
|
+
(0, vitest_1.expect)(resultAST.type).toBe('ObjectExpression');
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
39
|
+
(0, vitest_1.expect)(resultAST.properties).toHaveLength(1);
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)('should unwrap withSentryConfig with options', () => {
|
|
42
|
+
const mod = (0, magicast_1.parseModule)('export default withSentryConfig(nextConfig, { org: "test" })');
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
44
|
+
const wrappedAst = mod.exports.default.$ast;
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(wrappedAst);
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
48
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
49
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"nextConfig"`);
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.it)('should unwrap withSentryConfig without options', () => {
|
|
52
|
+
const mod = (0, magicast_1.parseModule)('export default withSentryConfig(nextConfig)');
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
54
|
+
const wrappedAst = mod.exports.default.$ast;
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
56
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(wrappedAst);
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
58
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
59
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"nextConfig"`);
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)('should handle nested withSentryConfig calls', () => {
|
|
62
|
+
const mod = (0, magicast_1.parseModule)('export default withSentryConfig(withSentryConfig(nextConfig, { org: "inner" }), { org: "outer" })');
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
64
|
+
const wrappedAst = mod.exports.default.$ast;
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
66
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(wrappedAst);
|
|
67
|
+
// Should unwrap one level and return the inner withSentryConfig call
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
69
|
+
(0, vitest_1.expect)(resultAST.type).toBe('CallExpression');
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
71
|
+
(0, vitest_1.expect)(resultAST.callee.name).toBe('withSentryConfig');
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
73
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
74
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"withSentryConfig(nextConfig, { org: "inner" })"`);
|
|
75
|
+
});
|
|
76
|
+
(0, vitest_1.it)('should handle complex expressions', () => {
|
|
77
|
+
const mod = (0, magicast_1.parseModule)('export default withSentryConfig(someComplexExpression.withMethods())');
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
79
|
+
const wrappedAst = mod.exports.default.$ast;
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
81
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(wrappedAst);
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
83
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
84
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"someComplexExpression.withMethods()"`);
|
|
85
|
+
});
|
|
86
|
+
(0, vitest_1.it)('should handle object literals', () => {
|
|
87
|
+
const mod = (0, magicast_1.parseModule)('export default withSentryConfig({ next: "config", obj: { next: "nested" } }, { org: "test" })');
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
89
|
+
const wrappedAst = mod.exports.default.$ast;
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
91
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(wrappedAst);
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
93
|
+
const { code: exportDefaultCode } = (0, magicast_1.generateCode)({ $ast: resultAST });
|
|
94
|
+
(0, vitest_1.expect)(exportDefaultCode).toMatchInlineSnapshot(`"{ next: "config", obj: { next: "nested" } }"`);
|
|
95
|
+
});
|
|
96
|
+
(0, vitest_1.it)('should return unchanged if not a withSentryConfig call', () => {
|
|
97
|
+
const mod = (0, magicast_1.parseModule)('export default someOtherFunction(nextConfig)');
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
99
|
+
const originalAST = mod.exports.default.$ast;
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
101
|
+
const resultAST = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
102
|
+
(0, vitest_1.expect)(resultAST).toBe(originalAST);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
(0, vitest_1.describe)('MJS/TS files', () => {
|
|
107
|
+
(0, vitest_1.it)('should unwrap existing withSentryConfig and re-wrap with new config using AST', () => {
|
|
108
|
+
const existingMjsContent = `import { withSentryConfig } from "@sentry/nextjs";
|
|
109
|
+
|
|
110
|
+
const nextConfig = {};
|
|
111
|
+
|
|
112
|
+
export default withSentryConfig(nextConfig, {
|
|
113
|
+
org: "old-org",
|
|
114
|
+
project: "old-project",
|
|
115
|
+
});`;
|
|
116
|
+
const mod = (0, magicast_1.parseModule)(existingMjsContent);
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
118
|
+
const originalAST = mod.exports.default.$ast;
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
120
|
+
const unwrappedAst = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
121
|
+
// Verify it returns the first argument (nextConfig identifier)
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
123
|
+
(0, vitest_1.expect)(unwrappedAst.type).toBe('Identifier');
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
125
|
+
(0, vitest_1.expect)(unwrappedAst.name).toBe('nextConfig');
|
|
126
|
+
// Create a fresh module to simulate the re-wrapping process
|
|
127
|
+
const freshMod = (0, magicast_1.parseModule)(`import { withSentryConfig } from "@sentry/nextjs";
|
|
128
|
+
|
|
129
|
+
const nextConfig = {};
|
|
130
|
+
|
|
131
|
+
export default nextConfig;`);
|
|
132
|
+
// Apply wrapping
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
134
|
+
freshMod.exports.default = (0, utils_1.wrapWithSentryConfig)(freshMod.exports.default, mockWithSentryConfigOptionsTemplate);
|
|
135
|
+
const newCode = freshMod.generate().code;
|
|
136
|
+
// Verify only one withSentryConfig call exists
|
|
137
|
+
const withSentryConfigMatches = newCode.match(/withSentryConfig\s*\(/g);
|
|
138
|
+
(0, vitest_1.expect)(withSentryConfigMatches).toHaveLength(1);
|
|
139
|
+
(0, vitest_1.expect)(newCode).toContain('test-org');
|
|
140
|
+
(0, vitest_1.expect)(newCode).toContain('test-project');
|
|
141
|
+
(0, vitest_1.expect)(newCode).not.toContain('old-org');
|
|
142
|
+
(0, vitest_1.expect)(newCode).not.toContain('old-project');
|
|
143
|
+
});
|
|
144
|
+
(0, vitest_1.it)('should handle complex nested configurations using AST', () => {
|
|
145
|
+
const existingMjsContent = `import { withSentryConfig } from "@sentry/nextjs";
|
|
146
|
+
|
|
147
|
+
const nextConfig = { experimental: { appDir: true } };
|
|
148
|
+
|
|
149
|
+
export default withSentryConfig(
|
|
150
|
+
withSentryConfig(nextConfig, { org: "nested-org" }),
|
|
151
|
+
{ org: "outer-org" }
|
|
152
|
+
);`;
|
|
153
|
+
const mod = (0, magicast_1.parseModule)(existingMjsContent);
|
|
154
|
+
// First unwrap ----
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
156
|
+
const firstUnwrapAST = (0, utils_1.unwrapSentryConfigAst)(mod.exports.default.$ast);
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
158
|
+
(0, vitest_1.expect)(firstUnwrapAST.type).toBe('CallExpression');
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
160
|
+
(0, vitest_1.expect)(firstUnwrapAST.callee.name).toBe('withSentryConfig');
|
|
161
|
+
const { code: exportDefaultCode1 } = (0, magicast_1.generateCode)({
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
163
|
+
$ast: firstUnwrapAST,
|
|
164
|
+
});
|
|
165
|
+
(0, vitest_1.expect)(exportDefaultCode1).toMatchInlineSnapshot(`"withSentryConfig(nextConfig, { org: "nested-org" })"`);
|
|
166
|
+
// Second unwrap ----
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
168
|
+
const secondUnwrapAST = (0, utils_1.unwrapSentryConfigAst)(firstUnwrapAST);
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
170
|
+
(0, vitest_1.expect)(secondUnwrapAST.type).toBe('Identifier');
|
|
171
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
172
|
+
(0, vitest_1.expect)(secondUnwrapAST.name).toBe('nextConfig');
|
|
173
|
+
const { code: exportDefaultCode2 } = (0, magicast_1.generateCode)({
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
175
|
+
$ast: secondUnwrapAST,
|
|
176
|
+
});
|
|
177
|
+
(0, vitest_1.expect)(exportDefaultCode2).toMatchInlineSnapshot(`"nextConfig"`);
|
|
178
|
+
});
|
|
179
|
+
(0, vitest_1.it)('should handle simple export without existing withSentryConfig using AST', () => {
|
|
180
|
+
const simpleMjsContent = `const nextConfig = {};
|
|
181
|
+
|
|
182
|
+
export default nextConfig;`;
|
|
183
|
+
const mod = (0, magicast_1.parseModule)(simpleMjsContent);
|
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
185
|
+
const originalAST = mod.exports.default.$ast;
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
187
|
+
const unwrappedAst = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
188
|
+
(0, vitest_1.expect)(unwrappedAst).toBe(originalAST);
|
|
189
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
190
|
+
mod.exports.default = (0, utils_1.wrapWithSentryConfig)(mod.exports.default, mockWithSentryConfigOptionsTemplate);
|
|
191
|
+
const newCode = mod.generate().code;
|
|
192
|
+
// Should have exactly one withSentryConfig call
|
|
193
|
+
const withSentryConfigMatches = newCode.match(/withSentryConfig\s*\(/g);
|
|
194
|
+
(0, vitest_1.expect)(withSentryConfigMatches).toHaveLength(1);
|
|
195
|
+
(0, vitest_1.expect)(newCode).toMatchInlineSnapshot(`
|
|
196
|
+
"const nextConfig = {};
|
|
197
|
+
|
|
198
|
+
export default withSentryConfig(nextConfig, ${sentryOptionsSnapshot});"
|
|
199
|
+
`);
|
|
200
|
+
});
|
|
201
|
+
(0, vitest_1.it)('should handle withSentryConfig(nextConfig) without options using AST', () => {
|
|
202
|
+
const existingMjsContent = `import { withSentryConfig } from "@sentry/nextjs";
|
|
203
|
+
|
|
204
|
+
const nextConfig = {};
|
|
205
|
+
|
|
206
|
+
export default withSentryConfig(nextConfig);`;
|
|
207
|
+
const mod = (0, magicast_1.parseModule)(existingMjsContent);
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
209
|
+
const originalAST = mod.exports.default.$ast;
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
211
|
+
const unwrappedAst = (0, utils_1.unwrapSentryConfigAst)(originalAST);
|
|
212
|
+
// Verify it returns the first argument (nextConfig identifier)
|
|
213
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
214
|
+
(0, vitest_1.expect)(unwrappedAst.type).toBe('Identifier');
|
|
215
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
216
|
+
(0, vitest_1.expect)(unwrappedAst.name).toBe('nextConfig');
|
|
217
|
+
// Simulate the re-wrapping process
|
|
218
|
+
const freshMod = (0, magicast_1.parseModule)(`import { withSentryConfig } from "@sentry/nextjs";
|
|
219
|
+
|
|
220
|
+
const nextConfig = {};
|
|
221
|
+
|
|
222
|
+
export default nextConfig;`);
|
|
223
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
224
|
+
freshMod.exports.default = (0, utils_1.wrapWithSentryConfig)(freshMod.exports.default, mockWithSentryConfigOptionsTemplate);
|
|
225
|
+
const newCode = freshMod.generate().code;
|
|
226
|
+
// Should have exactly one withSentryConfig call
|
|
227
|
+
const withSentryConfigMatches = newCode.match(/withSentryConfig\s*\(/g);
|
|
228
|
+
(0, vitest_1.expect)(withSentryConfigMatches).toHaveLength(1);
|
|
229
|
+
(0, vitest_1.expect)(newCode).not.toContain('withSentryConfig(withSentryConfig(');
|
|
230
|
+
(0, vitest_1.expect)(newCode).toMatch(/withSentryConfig\s*\(\s*nextConfig\s*,/);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
const sentryOptionsSnapshot = `{
|
|
235
|
+
// For all available options, see:
|
|
236
|
+
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
|
237
|
+
|
|
238
|
+
org: "test-org",
|
|
239
|
+
|
|
240
|
+
project: "test-project",
|
|
241
|
+
|
|
242
|
+
// Only print logs for uploading source maps in CI
|
|
243
|
+
silent: !process.env.CI,
|
|
244
|
+
|
|
245
|
+
// For all available options, see:
|
|
246
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
247
|
+
|
|
248
|
+
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
249
|
+
widenClientFileUpload: true,
|
|
250
|
+
|
|
251
|
+
// Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
|
252
|
+
// This can increase your server load as well as your hosting bill.
|
|
253
|
+
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
|
254
|
+
// side errors will fail.
|
|
255
|
+
// tunnelRoute: "/monitoring",
|
|
256
|
+
|
|
257
|
+
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
258
|
+
disableLogger: true,
|
|
259
|
+
|
|
260
|
+
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
|
261
|
+
// See the following for more information:
|
|
262
|
+
// https://docs.sentry.io/product/crons/
|
|
263
|
+
// https://vercel.com/docs/cron-jobs
|
|
264
|
+
automaticVercelMonitors: true
|
|
265
|
+
}`;
|
|
266
|
+
//# sourceMappingURL=wizard-double-wrap-prevention.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard-double-wrap-prevention.test.js","sourceRoot":"","sources":["../../../test/nextjs/wizard-double-wrap-prevention.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect } from 'vitest';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, parseModule } from 'magicast';\nimport { getWithSentryConfigOptionsTemplate } from '../../src/nextjs/templates';\nimport {\n unwrapSentryConfigAst,\n wrapWithSentryConfig,\n} from '../../src/nextjs/utils';\n\ndescribe('Next.js wizard double wrap prevention', () => {\n const mockWithSentryConfigOptionsTemplate =\n getWithSentryConfigOptionsTemplate({\n orgSlug: 'test-org',\n projectSlug: 'test-project',\n selfHosted: false,\n sentryUrl: 'https://sentry.io',\n tunnelRoute: false,\n });\n\n describe('unwrapSentryConfigAst utility function', () => {\n describe('AST-based expression unwrapping', () => {\n it('keeps code without withSentryConfig', () => {\n const mod = parseModule('export default nextConfig');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(originalAST);\n expect(resultAST).toBe(originalAST);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n expect(exportDefaultCode).toMatchInlineSnapshot(`\"nextConfig\"`);\n });\n\n it('should handle plain object literal exports', () => {\n const mod = parseModule(\n `export default { nextConfig: { randomValue: true } }`,\n );\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(originalAST);\n\n expect(resultAST).toBe(originalAST);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(resultAST.type).toBe('ObjectExpression');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(resultAST.properties).toHaveLength(1);\n });\n\n it('should unwrap withSentryConfig with options', () => {\n const mod = parseModule(\n 'export default withSentryConfig(nextConfig, { org: \"test\" })',\n );\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const wrappedAst = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(wrappedAst);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n\n expect(exportDefaultCode).toMatchInlineSnapshot(`\"nextConfig\"`);\n });\n\n it('should unwrap withSentryConfig without options', () => {\n const mod = parseModule('export default withSentryConfig(nextConfig)');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const wrappedAst = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(wrappedAst);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n\n expect(exportDefaultCode).toMatchInlineSnapshot(`\"nextConfig\"`);\n });\n\n it('should handle nested withSentryConfig calls', () => {\n const mod = parseModule(\n 'export default withSentryConfig(withSentryConfig(nextConfig, { org: \"inner\" }), { org: \"outer\" })',\n );\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const wrappedAst = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(wrappedAst);\n\n // Should unwrap one level and return the inner withSentryConfig call\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(resultAST.type).toBe('CallExpression');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(resultAST.callee.name).toBe('withSentryConfig');\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n\n expect(exportDefaultCode).toMatchInlineSnapshot(\n `\"withSentryConfig(nextConfig, { org: \"inner\" })\"`,\n );\n });\n\n it('should handle complex expressions', () => {\n const mod = parseModule(\n 'export default withSentryConfig(someComplexExpression.withMethods())',\n );\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const wrappedAst = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const resultAST = unwrapSentryConfigAst(wrappedAst);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n\n expect(exportDefaultCode).toMatchInlineSnapshot(\n `\"someComplexExpression.withMethods()\"`,\n );\n });\n\n it('should handle object literals', () => {\n const mod = parseModule(\n 'export default withSentryConfig({ next: \"config\", obj: { next: \"nested\" } }, { org: \"test\" })',\n );\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const wrappedAst = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const resultAST = unwrapSentryConfigAst(wrappedAst);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const { code: exportDefaultCode } = generateCode({ $ast: resultAST });\n\n expect(exportDefaultCode).toMatchInlineSnapshot(\n `\"{ next: \"config\", obj: { next: \"nested\" } }\"`,\n );\n });\n\n it('should return unchanged if not a withSentryConfig call', () => {\n const mod = parseModule('export default someOtherFunction(nextConfig)');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const resultAST = unwrapSentryConfigAst(originalAST);\n\n expect(resultAST).toBe(originalAST);\n });\n });\n });\n\n describe('MJS/TS files', () => {\n it('should unwrap existing withSentryConfig and re-wrap with new config using AST', () => {\n const existingMjsContent = `import { withSentryConfig } from \"@sentry/nextjs\";\n\nconst nextConfig = {};\n\nexport default withSentryConfig(nextConfig, {\n org: \"old-org\",\n project: \"old-project\",\n});`;\n\n const mod = parseModule(existingMjsContent);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const unwrappedAst = unwrapSentryConfigAst(originalAST);\n // Verify it returns the first argument (nextConfig identifier)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(unwrappedAst.type).toBe('Identifier');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(unwrappedAst.name).toBe('nextConfig');\n\n // Create a fresh module to simulate the re-wrapping process\n const freshMod =\n parseModule(`import { withSentryConfig } from \"@sentry/nextjs\";\n\nconst nextConfig = {};\n\nexport default nextConfig;`);\n\n // Apply wrapping\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n freshMod.exports.default = wrapWithSentryConfig(\n freshMod.exports.default,\n mockWithSentryConfigOptionsTemplate,\n );\n\n const newCode = freshMod.generate().code;\n\n // Verify only one withSentryConfig call exists\n const withSentryConfigMatches = newCode.match(/withSentryConfig\\s*\\(/g);\n expect(withSentryConfigMatches).toHaveLength(1);\n\n expect(newCode).toContain('test-org');\n expect(newCode).toContain('test-project');\n expect(newCode).not.toContain('old-org');\n expect(newCode).not.toContain('old-project');\n });\n\n it('should handle complex nested configurations using AST', () => {\n const existingMjsContent = `import { withSentryConfig } from \"@sentry/nextjs\";\n\nconst nextConfig = { experimental: { appDir: true } };\n\nexport default withSentryConfig(\n withSentryConfig(nextConfig, { org: \"nested-org\" }),\n { org: \"outer-org\" }\n);`;\n\n const mod = parseModule(existingMjsContent);\n\n // First unwrap ----\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const firstUnwrapAST = unwrapSentryConfigAst(mod.exports.default.$ast);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(firstUnwrapAST.type).toBe('CallExpression');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(firstUnwrapAST.callee.name).toBe('withSentryConfig');\n\n const { code: exportDefaultCode1 } = generateCode({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n $ast: firstUnwrapAST,\n });\n expect(exportDefaultCode1).toMatchInlineSnapshot(\n `\"withSentryConfig(nextConfig, { org: \"nested-org\" })\"`,\n );\n\n // Second unwrap ----\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const secondUnwrapAST = unwrapSentryConfigAst(firstUnwrapAST);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(secondUnwrapAST.type).toBe('Identifier');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(secondUnwrapAST.name).toBe('nextConfig');\n\n const { code: exportDefaultCode2 } = generateCode({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n $ast: secondUnwrapAST,\n });\n\n expect(exportDefaultCode2).toMatchInlineSnapshot(`\"nextConfig\"`);\n });\n\n it('should handle simple export without existing withSentryConfig using AST', () => {\n const simpleMjsContent = `const nextConfig = {};\n\nexport default nextConfig;`;\n\n const mod = parseModule(simpleMjsContent);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const unwrappedAst = unwrapSentryConfigAst(originalAST);\n expect(unwrappedAst).toBe(originalAST);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n mod.exports.default = wrapWithSentryConfig(\n mod.exports.default,\n mockWithSentryConfigOptionsTemplate,\n );\n\n const newCode = mod.generate().code;\n\n // Should have exactly one withSentryConfig call\n const withSentryConfigMatches = newCode.match(/withSentryConfig\\s*\\(/g);\n expect(withSentryConfigMatches).toHaveLength(1);\n\n expect(newCode).toMatchInlineSnapshot(`\n \"const nextConfig = {};\n\n export default withSentryConfig(nextConfig, ${sentryOptionsSnapshot});\"\n `);\n });\n\n it('should handle withSentryConfig(nextConfig) without options using AST', () => {\n const existingMjsContent = `import { withSentryConfig } from \"@sentry/nextjs\";\n\nconst nextConfig = {};\n\nexport default withSentryConfig(nextConfig);`;\n\n const mod = parseModule(existingMjsContent);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access\n const originalAST = mod.exports.default.$ast;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const unwrappedAst = unwrapSentryConfigAst(originalAST);\n // Verify it returns the first argument (nextConfig identifier)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(unwrappedAst.type).toBe('Identifier');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect(unwrappedAst.name).toBe('nextConfig');\n\n // Simulate the re-wrapping process\n const freshMod =\n parseModule(`import { withSentryConfig } from \"@sentry/nextjs\";\n\nconst nextConfig = {};\n\nexport default nextConfig;`);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n freshMod.exports.default = wrapWithSentryConfig(\n freshMod.exports.default,\n mockWithSentryConfigOptionsTemplate,\n );\n\n const newCode = freshMod.generate().code;\n\n // Should have exactly one withSentryConfig call\n const withSentryConfigMatches = newCode.match(/withSentryConfig\\s*\\(/g);\n expect(withSentryConfigMatches).toHaveLength(1);\n\n expect(newCode).not.toContain('withSentryConfig(withSentryConfig(');\n expect(newCode).toMatch(/withSentryConfig\\s*\\(\\s*nextConfig\\s*,/);\n });\n });\n});\n\nconst sentryOptionsSnapshot = `{\n // For all available options, see:\n // https://www.npmjs.com/package/@sentry/webpack-plugin#options\n\n org: \"test-org\",\n\n project: \"test-project\",\n\n // Only print logs for uploading source maps in CI\n silent: !process.env.CI,\n\n // For all available options, see:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/\n\n // Upload a larger set of source maps for prettier stack traces (increases build time)\n widenClientFileUpload: true,\n\n // Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.\n // This can increase your server load as well as your hosting bill.\n // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-\n // side errors will fail.\n // tunnelRoute: \"/monitoring\",\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n\n // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)\n // See the following for more information:\n // https://docs.sentry.io/product/crons/\n // https://vercel.com/docs/cron-jobs\n automaticVercelMonitors: true\n}`;\n"]}
|
|
@@ -19,7 +19,7 @@ config.resolver.assetExts.push(
|
|
|
19
19
|
|
|
20
20
|
module.exports = config;
|
|
21
21
|
`);
|
|
22
|
-
const result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
22
|
+
const result = (0, expo_metro_1.patchMetroInMemory)(mod, 'metro.config.js');
|
|
23
23
|
(0, vitest_1.expect)(result).toBe(true);
|
|
24
24
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`
|
|
25
25
|
const {
|
|
@@ -45,7 +45,7 @@ const config = getDefaultConfig(__dirname);
|
|
|
45
45
|
|
|
46
46
|
module.exports = config;
|
|
47
47
|
`);
|
|
48
|
-
const result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
48
|
+
const result = (0, expo_metro_1.patchMetroInMemory)(mod, 'metro.config.js');
|
|
49
49
|
(0, vitest_1.expect)(result).toBe(true);
|
|
50
50
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`
|
|
51
51
|
const { getDefaultConfig, otherExport } = require("expo/metro-config");
|
|
@@ -63,7 +63,7 @@ module.exports = config;
|
|
|
63
63
|
const mod = (0, magicast_1.parseModule)(`
|
|
64
64
|
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
|
|
65
65
|
`);
|
|
66
|
-
const result = (0, expo_metro_1.patchMetroInMemory)(mod);
|
|
66
|
+
const result = (0, expo_metro_1.patchMetroInMemory)(mod, 'metro.config.js');
|
|
67
67
|
(0, vitest_1.expect)(result).toBe(false);
|
|
68
68
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`
|
|
69
69
|
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo-metro.test.js","sourceRoot":"","sources":["../../../test/react-native/expo-metro.test.ts"],"names":[],"mappings":";;AAAA,kFAAkF;AAClF,uCAAqD;AACrD,kEAAuE;AACvE,mCAAgD;AAEhD,IAAA,iBAAQ,EAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAA,aAAI,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;;;;;;;OAYrB,CAAC,CAAC;QAEL,MAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"expo-metro.test.js","sourceRoot":"","sources":["../../../test/react-native/expo-metro.test.ts"],"names":[],"mappings":";;AAAA,kFAAkF;AAClF,uCAAqD;AACrD,kEAAuE;AACvE,mCAAgD;AAEhD,IAAA,iBAAQ,EAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAA,aAAI,EAAC,6BAA6B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;;;;;;;OAYrB,CAAC,CAAC;QAEL,MAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAC1D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAA,eAAM,EAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC;;;;;;;;;;;;;;CAcL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,aAAI,EAAC,sDAAsD,EAAE,GAAG,EAAE;QAChE,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;OAMrB,CAAC,CAAC;QAEL,MAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAC1D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAA,eAAM,EAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC;;;;;;;;;;CAUL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,aAAI,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACvD,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;CAE3B,CAAC,CAAC;QAEC,MAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAC1D,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAA,eAAM,EAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC;;CAEL,CAAC,IAAI,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, parseModule } from 'magicast';\nimport { patchMetroInMemory } from '../../src/react-native/expo-metro';\nimport { describe, expect, test } from 'vitest';\n\ndescribe('expo-metro config', () => {\n test('patches minimal expo config', () => {\n const mod = parseModule(`\nconst { getDefaultConfig } = require(\"expo/metro-config\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getDefaultConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n `);\n\n const result = patchMetroInMemory(mod, 'metro.config.js');\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\n/** @type {import('expo/metro-config').MetroConfig} */\nconst config = getSentryExpoConfig(__dirname);\n\nconfig.resolver.assetExts.push(\n // Adds support for .db files for SQLite databases\n 'db'\n);\n\nmodule.exports = config;\n`.trim(),\n );\n });\n\n test('keeps expo metro config if other imports are present', () => {\n const mod = parseModule(`\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst config = getDefaultConfig(__dirname);\n\nmodule.exports = config;\n `);\n\n const result = patchMetroInMemory(mod, 'metro.config.js');\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst { getDefaultConfig, otherExport } = require(\"expo/metro-config\");\n\nconst {\n getSentryExpoConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`.trim(),\n );\n });\n\n test('does not modify when sentry already present', () => {\n const mod = parseModule(`\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n`);\n\n const result = patchMetroInMemory(mod, 'metro.config.js');\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `\nconst { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n`.trim(),\n );\n });\n});\n"]}
|
|
@@ -1,9 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
// @ts-expect-error - magicast is ESM and TS complains about that. It works though
|
|
4
27
|
const magicast_1 = require("magicast");
|
|
5
28
|
const metro_1 = require("../../src/react-native/metro");
|
|
6
29
|
const vitest_1 = require("vitest");
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
vitest_1.vi.mock('fs', async () => {
|
|
32
|
+
const actual = await vitest_1.vi.importActual('fs');
|
|
33
|
+
return {
|
|
34
|
+
...actual,
|
|
35
|
+
existsSync: vitest_1.vi.fn(),
|
|
36
|
+
};
|
|
37
|
+
});
|
|
7
38
|
(0, vitest_1.describe)('patch metro config - sentry serializer', () => {
|
|
8
39
|
(0, vitest_1.describe)('patchMetroWithSentryConfigInMemory', () => {
|
|
9
40
|
(0, vitest_1.it)('patches react native 0.72 default metro config', async () => {
|
|
@@ -18,9 +49,7 @@ const vitest_1 = require("vitest");
|
|
|
18
49
|
const config = {};
|
|
19
50
|
|
|
20
51
|
module.exports = mergeConfig(getDefaultConfig(__dirname), config);`);
|
|
21
|
-
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod,
|
|
22
|
-
/* noop */
|
|
23
|
-
});
|
|
52
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.js', true);
|
|
24
53
|
(0, vitest_1.expect)(result).toBe(true);
|
|
25
54
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code)
|
|
26
55
|
.toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
@@ -57,9 +86,7 @@ module.exports = {
|
|
|
57
86
|
}),
|
|
58
87
|
},
|
|
59
88
|
};`);
|
|
60
|
-
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod,
|
|
61
|
-
/* noop */
|
|
62
|
-
});
|
|
89
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.js', true);
|
|
63
90
|
(0, vitest_1.expect)(result).toBe(true);
|
|
64
91
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`const {
|
|
65
92
|
withSentryConfig
|
|
@@ -87,9 +114,7 @@ module.exports = withSentryConfig({
|
|
|
87
114
|
const mod = (0, magicast_1.parseModule)(`const testConfig = {};
|
|
88
115
|
|
|
89
116
|
module.exports = testConfig;`);
|
|
90
|
-
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod,
|
|
91
|
-
/* noop */
|
|
92
|
-
});
|
|
117
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.js', true);
|
|
93
118
|
(0, vitest_1.expect)(result).toBe(true);
|
|
94
119
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`const {
|
|
95
120
|
withSentryConfig
|
|
@@ -151,9 +176,7 @@ const config = {
|
|
|
151
176
|
};
|
|
152
177
|
|
|
153
178
|
module.exports = mergeConfig(getDefaultConfig(__dirname), config);`);
|
|
154
|
-
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod,
|
|
155
|
-
/* noop */
|
|
156
|
-
});
|
|
179
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.js', true);
|
|
157
180
|
(0, vitest_1.expect)(result).toBe(true);
|
|
158
181
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code)
|
|
159
182
|
.toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
@@ -212,11 +235,21 @@ const config = {
|
|
|
212
235
|
|
|
213
236
|
module.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);
|
|
214
237
|
});
|
|
238
|
+
(0, vitest_1.it)('patches CJS style metro config', async () => {
|
|
239
|
+
const mod = (0, magicast_1.parseModule)(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
240
|
+
|
|
241
|
+
const config = {};
|
|
242
|
+
|
|
243
|
+
module.exports = mergeConfig(getDefaultConfig(__dirname), config);`);
|
|
244
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.cjs', true);
|
|
245
|
+
(0, vitest_1.expect)(result).toBe(true);
|
|
246
|
+
const code = (0, magicast_1.generateCode)(mod.$ast).code;
|
|
247
|
+
(0, vitest_1.expect)(code).toContain('require("@sentry/react-native/metro")');
|
|
248
|
+
(0, vitest_1.expect)(code).toContain('withSentryConfig');
|
|
249
|
+
});
|
|
215
250
|
(0, vitest_1.it)('does not patch react native metro config exported as factory function', async () => {
|
|
216
251
|
const mod = (0, magicast_1.parseModule)(`module.exports = () => ({});`);
|
|
217
|
-
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod,
|
|
218
|
-
/* noop */
|
|
219
|
-
});
|
|
252
|
+
const result = await (0, metro_1.patchMetroWithSentryConfigInMemory)(mod, 'metro.config.js', true);
|
|
220
253
|
(0, vitest_1.expect)(result).toBe(false);
|
|
221
254
|
(0, vitest_1.expect)((0, magicast_1.generateCode)(mod.$ast).code).toBe(`module.exports = () => ({});`);
|
|
222
255
|
});
|
|
@@ -331,6 +364,31 @@ module.exports = {
|
|
|
331
364
|
});
|
|
332
365
|
});
|
|
333
366
|
});
|
|
367
|
+
(0, vitest_1.describe)('Dynamic Metro Config path', () => {
|
|
368
|
+
(0, vitest_1.beforeEach)(() => {
|
|
369
|
+
vitest_1.vi.clearAllMocks();
|
|
370
|
+
});
|
|
371
|
+
(0, vitest_1.it)('finds metro.config.js when it exists', () => {
|
|
372
|
+
vitest_1.vi.mocked(fs.existsSync).mockImplementation((path) => path === 'metro.config.js');
|
|
373
|
+
const result = (0, metro_1.findMetroConfigPath)();
|
|
374
|
+
(0, vitest_1.expect)(result).toBe('metro.config.js');
|
|
375
|
+
});
|
|
376
|
+
(0, vitest_1.it)('finds metro.config.cjs when it exists', () => {
|
|
377
|
+
vitest_1.vi.mocked(fs.existsSync).mockImplementation((path) => path === 'metro.config.cjs');
|
|
378
|
+
const result = (0, metro_1.findMetroConfigPath)();
|
|
379
|
+
(0, vitest_1.expect)(result).toBe('metro.config.cjs');
|
|
380
|
+
});
|
|
381
|
+
(0, vitest_1.it)('prefers metro.config.js over metro.config.cjs when both exist', () => {
|
|
382
|
+
vitest_1.vi.mocked(fs.existsSync).mockImplementation(() => true);
|
|
383
|
+
const result = (0, metro_1.findMetroConfigPath)();
|
|
384
|
+
(0, vitest_1.expect)(result).toBe('metro.config.js');
|
|
385
|
+
});
|
|
386
|
+
(0, vitest_1.it)('returns undefined when no metro config exists', () => {
|
|
387
|
+
vitest_1.vi.mocked(fs.existsSync).mockImplementation(() => false);
|
|
388
|
+
const result = (0, metro_1.findMetroConfigPath)();
|
|
389
|
+
(0, vitest_1.expect)(result).toBeUndefined();
|
|
390
|
+
});
|
|
391
|
+
});
|
|
334
392
|
function getModuleExportsObject(mod, index = 0) {
|
|
335
393
|
return mod.$ast.body[index]
|
|
336
394
|
.expression.right;
|