@sentry/wizard 3.34.4 → 3.36.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/dist/e2e-tests/tests/nuxt-3.test.d.ts +1 -0
  3. package/dist/e2e-tests/tests/nuxt-3.test.js +257 -0
  4. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -0
  5. package/dist/e2e-tests/tests/nuxt-4.test.d.ts +1 -0
  6. package/dist/e2e-tests/tests/nuxt-4.test.js +258 -0
  7. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -0
  8. package/dist/e2e-tests/tests/remix.test.js +92 -27
  9. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  10. package/dist/e2e-tests/tests/sveltekit.test.js +102 -42
  11. package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
  12. package/dist/e2e-tests/utils/index.d.ts +18 -1
  13. package/dist/e2e-tests/utils/index.js +31 -2
  14. package/dist/e2e-tests/utils/index.js.map +1 -1
  15. package/dist/lib/Constants.d.ts +1 -0
  16. package/dist/lib/Constants.js +1 -0
  17. package/dist/lib/Constants.js.map +1 -1
  18. package/dist/package.json +1 -1
  19. package/dist/src/android/templates.js +1 -1
  20. package/dist/src/android/templates.js.map +1 -1
  21. package/dist/src/apple/templates.js +2 -2
  22. package/dist/src/apple/templates.js.map +1 -1
  23. package/dist/src/nextjs/nextjs-wizard.js +1 -0
  24. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  25. package/dist/src/nuxt/nuxt-wizard.d.ts +3 -0
  26. package/dist/src/nuxt/nuxt-wizard.js +227 -0
  27. package/dist/src/nuxt/nuxt-wizard.js.map +1 -0
  28. package/dist/src/nuxt/sdk-example.d.ts +8 -0
  29. package/dist/src/nuxt/sdk-example.js +179 -0
  30. package/dist/src/nuxt/sdk-example.js.map +1 -0
  31. package/dist/src/nuxt/sdk-setup.d.ts +11 -0
  32. package/dist/src/nuxt/sdk-setup.js +326 -0
  33. package/dist/src/nuxt/sdk-setup.js.map +1 -0
  34. package/dist/src/nuxt/templates.d.ts +22 -0
  35. package/dist/src/nuxt/templates.js +84 -0
  36. package/dist/src/nuxt/templates.js.map +1 -0
  37. package/dist/src/nuxt/utils.d.ts +1 -0
  38. package/dist/src/nuxt/utils.js +71 -0
  39. package/dist/src/nuxt/utils.js.map +1 -0
  40. package/dist/src/remix/remix-wizard.js +2 -1
  41. package/dist/src/remix/remix-wizard.js.map +1 -1
  42. package/dist/src/run.d.ts +1 -1
  43. package/dist/src/run.js +30 -23
  44. package/dist/src/run.js.map +1 -1
  45. package/dist/src/sourcemaps/tools/rollup.js +1 -1
  46. package/dist/src/sourcemaps/tools/rollup.js.map +1 -1
  47. package/dist/src/sveltekit/sveltekit-wizard.js +2 -1
  48. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  49. package/dist/src/utils/clack-utils.d.ts +9 -2
  50. package/dist/src/utils/clack-utils.js +93 -27
  51. package/dist/src/utils/clack-utils.js.map +1 -1
  52. package/dist/src/utils/package-json.d.ts +5 -0
  53. package/dist/src/utils/package-json.js.map +1 -1
  54. package/dist/src/utils/package-manager.d.ts +1 -0
  55. package/dist/src/utils/package-manager.js +129 -0
  56. package/dist/src/utils/package-manager.js.map +1 -1
  57. package/dist/test/nuxt/templates.test.d.ts +1 -0
  58. package/dist/test/nuxt/templates.test.js +70 -0
  59. package/dist/test/nuxt/templates.test.js.map +1 -0
  60. package/e2e-tests/README.md +59 -0
  61. package/e2e-tests/test-applications/nuxt-3-test-app/README.md +75 -0
  62. package/e2e-tests/test-applications/nuxt-3-test-app/nuxt.config.ts +5 -0
  63. package/e2e-tests/test-applications/nuxt-3-test-app/package.json +18 -0
  64. package/e2e-tests/test-applications/nuxt-3-test-app/public/favicon.ico +0 -0
  65. package/e2e-tests/test-applications/nuxt-3-test-app/public/robots.txt +1 -0
  66. package/e2e-tests/tests/nuxt-3.test.ts +192 -0
  67. package/e2e-tests/tests/nuxt-4.test.ts +191 -0
  68. package/e2e-tests/tests/remix.test.ts +163 -50
  69. package/e2e-tests/tests/sveltekit.test.ts +180 -79
  70. package/e2e-tests/utils/index.ts +34 -1
  71. package/lib/Constants.ts +1 -0
  72. package/package.json +1 -1
  73. package/src/android/templates.ts +0 -2
  74. package/src/apple/templates.ts +14 -2
  75. package/src/nextjs/nextjs-wizard.ts +1 -0
  76. package/src/nuxt/nuxt-wizard.ts +177 -0
  77. package/src/nuxt/sdk-example.ts +135 -0
  78. package/src/nuxt/sdk-setup.ts +248 -0
  79. package/src/nuxt/templates.ts +296 -0
  80. package/src/nuxt/utils.ts +32 -0
  81. package/src/remix/remix-wizard.ts +2 -1
  82. package/src/run.ts +7 -0
  83. package/src/sourcemaps/tools/rollup.ts +1 -1
  84. package/src/sveltekit/sveltekit-wizard.ts +2 -1
  85. package/src/utils/clack-utils.ts +74 -13
  86. package/src/utils/package-json.ts +5 -0
  87. package/src/utils/package-manager.ts +66 -0
  88. package/test/nuxt/templates.test.ts +228 -0
@@ -9,68 +9,122 @@ import {
9
9
  checkIfRunsOnProdMode,
10
10
  checkPackageJson,
11
11
  cleanupGit,
12
+ createFile,
12
13
  KEYS,
14
+ modifyFile,
13
15
  revertLocalChanges,
14
16
  startWizardInstance,
15
17
  TEST_ARGS,
16
18
  } from '../utils';
17
19
  import * as path from 'path';
18
20
 
19
- describe('Remix', () => {
20
- const integration = Integration.remix;
21
- const projectDir = path.resolve(
22
- __dirname,
23
- '../test-applications/remix-test-app',
24
- );
21
+ const SERVER_TEMPLATE = `import { createRequestHandler } from '@remix-run/express';
22
+ import { installGlobals } from '@remix-run/node';
23
+ import compression from 'compression';
24
+ import express from 'express';
25
+ import morgan from 'morgan';
26
+
27
+ installGlobals();
28
+
29
+ const viteDevServer =
30
+ process.env.NODE_ENV === 'production'
31
+ ? undefined
32
+ : await import('vite').then(vite =>
33
+ vite.createServer({
34
+ server: { middlewareMode: true },
35
+ }),
36
+ );
37
+
38
+ const app = express();
39
+
40
+ app.use(compression());
41
+ app.disable('x-powered-by');
42
+
43
+ if (viteDevServer) {
44
+ app.use(viteDevServer.middlewares);
45
+ } else {
46
+ app.use('/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' }));
47
+ }
48
+
49
+ app.use(express.static('build/client', { maxAge: '1h' }));
50
+ app.use(morgan('tiny'));
51
+
52
+ app.all(
53
+ '*',
54
+ createRequestHandler({
55
+ build: viteDevServer
56
+ ? () => viteDevServer.ssrLoadModule('virtual:remix/server-build')
57
+ : await import('./build/server/index.js'),
58
+ }),
59
+ );
60
+
61
+ app.listen(0, () => console.log('Express server listening'));
62
+ `;
25
63
 
26
- beforeAll(async () => {
27
- const wizardInstance = startWizardInstance(integration, projectDir);
28
- const packageManagerPrompted = await wizardInstance.waitForOutput(
64
+
65
+ async function runWizardOnRemixProject(projectDir: string, integration: Integration, fileModificationFn?: (projectDir: string, integration: Integration) => unknown) {
66
+ const wizardInstance = startWizardInstance(integration, projectDir);
67
+ let packageManagerPrompted = false;
68
+
69
+ if (fileModificationFn) {
70
+ fileModificationFn(projectDir, integration);
71
+
72
+ await wizardInstance.waitForOutput(
73
+ 'Do you want to continue anyway?',
74
+ );
75
+
76
+ packageManagerPrompted = await wizardInstance.sendStdinAndWaitForOutput(
77
+ [KEYS.ENTER],
29
78
  'Please select your package manager.',
30
79
  );
80
+ } else {
31
81
 
32
- const tracingOptionPrompted =
33
- packageManagerPrompted &&
34
- (await wizardInstance.sendStdinAndWaitForOutput(
35
- // Selecting `yarn` as the package manager
36
- [KEYS.DOWN, KEYS.ENTER],
37
- // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
38
- 'to track the performance of your application?',
39
- {
40
- timeout: 240_000,
41
- },
42
- ));
43
-
44
- const replayOptionPrompted =
45
- tracingOptionPrompted &&
46
- (await wizardInstance.sendStdinAndWaitForOutput(
47
- [KEYS.ENTER],
48
- // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
49
- 'to get a video-like reproduction of errors during a user session?',
50
- ));
51
-
52
- replayOptionPrompted &&
53
- (await wizardInstance.sendStdinAndWaitForOutput(
54
- [KEYS.ENTER],
55
- 'Do you want to create an example page',
56
- {
57
- optional: true,
58
- },
59
- ));
60
-
61
- await wizardInstance.sendStdinAndWaitForOutput(
62
- [KEYS.ENTER, KEYS.ENTER],
63
- 'Sentry has been successfully configured for your Remix project',
82
+ packageManagerPrompted = await wizardInstance.waitForOutput(
83
+ 'Please select your package manager.',
64
84
  );
85
+ }
65
86
 
66
- wizardInstance.kill();
67
- });
87
+ const tracingOptionPrompted =
88
+ packageManagerPrompted &&
89
+ (await wizardInstance.sendStdinAndWaitForOutput(
90
+ // Selecting `yarn` as the package manager
91
+ [KEYS.DOWN, KEYS.ENTER],
92
+ // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
93
+ 'to track the performance of your application?',
94
+ {
95
+ timeout: 240_000,
96
+ },
97
+ ));
68
98
 
69
- afterAll(() => {
70
- revertLocalChanges(projectDir);
71
- cleanupGit(projectDir);
72
- });
99
+ const replayOptionPrompted =
100
+ tracingOptionPrompted &&
101
+ (await wizardInstance.sendStdinAndWaitForOutput(
102
+ [KEYS.ENTER],
103
+ // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
104
+ 'to get a video-like reproduction of errors during a user session?',
105
+ ));
106
+
107
+ replayOptionPrompted &&
108
+ (await wizardInstance.sendStdinAndWaitForOutput(
109
+ [KEYS.ENTER],
110
+ 'Do you want to create an example page',
111
+ {
112
+ optional: true,
113
+ },
114
+ ));
73
115
 
116
+ await wizardInstance.sendStdinAndWaitForOutput(
117
+ [KEYS.ENTER, KEYS.ENTER],
118
+ 'Sentry has been successfully configured for your Remix project',
119
+ );
120
+
121
+ wizardInstance.kill();
122
+ };
123
+
124
+ function checkRemixProject(projectDir: string, integration: Integration, options?: {
125
+ devModeExpectedOutput?: string;
126
+ prodModeExpectedOutput?: string;
127
+ }) {
74
128
  test('package.json is updated correctly', () => {
75
129
  checkPackageJson(projectDir, integration);
76
130
  });
@@ -140,15 +194,74 @@ describe('Remix', () => {
140
194
  ]);
141
195
  });
142
196
 
143
- test('builds correctly', async () => {
197
+ test('builds successfully', async () => {
144
198
  await checkIfBuilds(projectDir, 'built');
145
199
  });
146
200
 
147
201
  test('runs on dev mode correctly', async () => {
148
- await checkIfRunsOnDevMode(projectDir, 'to expose');
202
+ await checkIfRunsOnDevMode(projectDir, options?.devModeExpectedOutput || 'to expose');
149
203
  });
150
204
 
151
205
  test('runs on prod mode correctly', async () => {
152
- await checkIfRunsOnProdMode(projectDir, '[remix-serve]');
206
+ await checkIfRunsOnProdMode(projectDir, options?.prodModeExpectedOutput || '[remix-serve]');
207
+ });
208
+ }
209
+
210
+ describe('Remix', () => {
211
+ describe('with empty project', () => {
212
+ const integration = Integration.remix;
213
+ const projectDir = path.resolve(
214
+ __dirname,
215
+ '../test-applications/remix-test-app',
216
+ );
217
+
218
+ beforeAll(async () => {
219
+ await runWizardOnRemixProject(projectDir, integration);
220
+ });
221
+
222
+ afterAll(() => {
223
+ revertLocalChanges(projectDir);
224
+ cleanupGit(projectDir);
225
+ });
226
+
227
+ checkRemixProject(projectDir, integration);
228
+ });
229
+
230
+ describe('with existing custom Express server', () => {
231
+ const integration = Integration.remix;
232
+ const projectDir = path.resolve(
233
+ __dirname,
234
+ '../test-applications/remix-test-app',
235
+ );
236
+
237
+ beforeAll(async () => {
238
+ await runWizardOnRemixProject(projectDir, integration, (projectDir) => {
239
+ createFile(
240
+ `${projectDir}/server.mjs`,
241
+ SERVER_TEMPLATE,
242
+ );
243
+
244
+ modifyFile(`${projectDir}/package.json`, {
245
+ '"start": "remix-serve ./build/server/index.js"': '"start": "node ./server.mjs"',
246
+ '"dev": "remix vite:dev"': '"dev": "node ./server.mjs"',
247
+ });
248
+ });
249
+ });
250
+
251
+ afterAll(() => {
252
+ revertLocalChanges(projectDir);
253
+ cleanupGit(projectDir);
254
+ });
255
+
256
+ checkRemixProject(projectDir, integration, {
257
+ devModeExpectedOutput: 'Express server listening',
258
+ prodModeExpectedOutput: 'Express server listening',
259
+ });
260
+
261
+ test('server.mjs contains instrumentation file import', () => {
262
+ checkFileContents(`${projectDir}/server.mjs`, [
263
+ "import './instrumentation.server.mjs';",
264
+ ]);
265
+ });
153
266
  });
154
267
  });
@@ -9,6 +9,7 @@ import {
9
9
  checkIfRunsOnProdMode,
10
10
  checkPackageJson,
11
11
  cleanupGit,
12
+ createFile,
12
13
  KEYS,
13
14
  revertLocalChanges,
14
15
  startWizardInstance,
@@ -16,65 +17,93 @@ import {
16
17
  } from '../utils';
17
18
  import * as path from 'path';
18
19
 
19
- describe('Sveltekit', () => {
20
- const integration = Integration.sveltekit;
21
- const projectDir = path.resolve(
22
- __dirname,
23
- '../test-applications/sveltekit-test-app',
24
- );
25
-
26
- beforeAll(async () => {
27
- const wizardInstance = startWizardInstance(integration, projectDir);
20
+ const SERVER_HOOK_TEMPLATE = `import type { Handle } from '@sveltejs/kit';
21
+
22
+ export const handle: Handle = async ({ event, resolve }) => {
23
+ if (event.url.pathname.startsWith('/custom')) {
24
+ return new Response('custom response');
25
+ }
26
+
27
+ const response = await resolve(event);
28
+ return response;
29
+ };
30
+ `;
31
+ const CLIENT_HOOK_TEMPLATE = `
32
+ export async function handleError({ error, event }) {
33
+ // you can capture the \`error\` and \`event\` from the client
34
+ // but it only runs if the unexpected error comes from \`+ page.ts\`
35
+ console.log(error)
36
+
37
+ return {
38
+ // don't show sensitive data to the user
39
+ message: 'Yikes! 💩',
40
+ }
41
+ }
42
+ `;
43
+
44
+ async function runWizardOnSvelteKitProject(projectDir: string, integration: Integration, fileModificationFn?: (projectDir: string, integration: Integration) => unknown) {
45
+ const wizardInstance = startWizardInstance(integration, projectDir);
46
+ let packageManagerPrompted = false;
47
+
48
+ if (fileModificationFn) {
49
+ fileModificationFn(projectDir, integration);
50
+
51
+ // As we modified project, we have a warning prompt before we get the package manager prompt
52
+ await wizardInstance.waitForOutput(
53
+ 'Do you want to continue anyway?',
54
+ );
28
55
 
29
- const packageManagerPrompted = await wizardInstance.waitForOutput(
56
+ packageManagerPrompted = await wizardInstance.sendStdinAndWaitForOutput(
57
+ [KEYS.ENTER],
30
58
  'Please select your package manager.',
31
- {
32
- optional: true,
33
- }
34
59
  );
35
-
36
- const tracingOptionPrompted =
37
- packageManagerPrompted &&
38
- (await wizardInstance.sendStdinAndWaitForOutput(
39
- // Selecting `yarn` as the package manager
40
- [KEYS.DOWN, KEYS.ENTER],
41
- // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
42
- 'to track the performance of your application?',
43
- {
44
- timeout: 240_000,
45
- }
46
- ));
47
-
48
- const replayOptionPrompted =
49
- tracingOptionPrompted &&
50
- (await wizardInstance.sendStdinAndWaitForOutput(
51
- [KEYS.ENTER],
52
- // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
53
- 'to get a video-like reproduction of errors during a user session?',
54
- ));
55
-
56
- replayOptionPrompted &&
57
- (await wizardInstance.sendStdinAndWaitForOutput(
58
- [KEYS.ENTER],
59
- 'Do you want to create an example page',
60
- {
61
- optional: true,
62
- },
63
- ));
64
-
65
- await wizardInstance.sendStdinAndWaitForOutput(
66
- [KEYS.ENTER, KEYS.ENTER],
67
- 'Successfully installed the Sentry SvelteKit SDK!',
60
+ } else {
61
+ packageManagerPrompted = await wizardInstance.waitForOutput(
62
+ 'Please select your package manager'
68
63
  );
64
+ }
65
+
66
+ const tracingOptionPrompted =
67
+ packageManagerPrompted &&
68
+ (await wizardInstance.sendStdinAndWaitForOutput(
69
+ // Selecting `yarn` as the package manager
70
+ [KEYS.DOWN, KEYS.ENTER],
71
+ // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
72
+ 'to track the performance of your application?',
73
+ {
74
+ timeout: 240_000,
75
+ }
76
+ ));
77
+
78
+ const replayOptionPrompted =
79
+ tracingOptionPrompted &&
80
+ (await wizardInstance.sendStdinAndWaitForOutput(
81
+ [KEYS.ENTER],
82
+ // "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
83
+ 'to get a video-like reproduction of errors during a user session?',
84
+ ));
85
+
86
+ replayOptionPrompted &&
87
+ (await wizardInstance.sendStdinAndWaitForOutput(
88
+ [KEYS.ENTER],
89
+ 'Do you want to create an example page',
90
+ {
91
+ optional: true,
92
+ },
93
+ ));
69
94
 
70
- wizardInstance.kill();
71
- });
95
+ await wizardInstance.sendStdinAndWaitForOutput(
96
+ [KEYS.ENTER, KEYS.ENTER],
97
+ 'Successfully installed the Sentry SvelteKit SDK!',
98
+ );
72
99
 
73
- afterAll(() => {
74
- revertLocalChanges(projectDir);
75
- cleanupGit(projectDir);
76
- });
100
+ wizardInstance.kill();
101
+ }
77
102
 
103
+ function checkSvelteKitProject(projectDir: string, integration: Integration, options?: {
104
+ devModeExpectedOutput: string;
105
+ prodModeExpectedOutput: string;
106
+ }) {
78
107
  test('should have the correct package.json', () => {
79
108
  checkPackageJson(projectDir, integration);
80
109
  });
@@ -99,11 +128,43 @@ describe('Sveltekit', () => {
99
128
  checkFileExists(path.resolve(projectDir, 'src/hooks.client.ts'));
100
129
  });
101
130
 
102
- test('hooks.client.ts contains sentry import', () => {
103
- checkFileContents(
104
- path.resolve(projectDir, 'src/hooks.client.ts'),
105
- [`import * as Sentry from '@sentry/sveltekit';`,
106
- `Sentry.init({
131
+ test('builds successfully', async () => {
132
+ await checkIfBuilds(projectDir, 'Successfully uploaded source maps to Sentry');
133
+ });
134
+
135
+ test('runs on dev mode correctly', async () => {
136
+ await checkIfRunsOnDevMode(projectDir, options?.devModeExpectedOutput || 'ready in');
137
+ });
138
+
139
+ test('runs on prod mode correctly', async () => {
140
+ await checkIfRunsOnProdMode(projectDir, options?.prodModeExpectedOutput || 'to expose', 'preview');
141
+ });
142
+ }
143
+
144
+ describe('Sveltekit', () => {
145
+ describe('without existing hooks', () => {
146
+ const integration = Integration.sveltekit;
147
+ const projectDir = path.resolve(
148
+ __dirname,
149
+ '../test-applications/sveltekit-test-app',
150
+ );
151
+
152
+ beforeAll(async () => {
153
+ await runWizardOnSvelteKitProject(projectDir, integration);
154
+ });
155
+
156
+ afterAll(() => {
157
+ revertLocalChanges(projectDir);
158
+ cleanupGit(projectDir);
159
+ });
160
+
161
+ checkSvelteKitProject(projectDir, integration);
162
+
163
+ test('hooks.client.ts contains sentry', () => {
164
+ checkFileContents(
165
+ path.resolve(projectDir, 'src/hooks.client.ts'),
166
+ [`import * as Sentry from '@sentry/sveltekit';`,
167
+ `Sentry.init({
107
168
  dsn: '${TEST_ARGS.PROJECT_DSN}',
108
169
 
109
170
  tracesSampleRate: 1.0,
@@ -118,37 +179,77 @@ describe('Sveltekit', () => {
118
179
 
119
180
  // If you don't want to use Session Replay, just remove the line below:
120
181
  integrations: [replayIntegration()],
121
- });`]);
122
- });
123
-
124
-
125
- test('hooks.server.ts contains sentry import', () => {
126
- checkFileContents(
127
- path.resolve(projectDir, 'src/hooks.server.ts'),
128
- [
129
- `import * as Sentry from '@sentry/sveltekit';`,
130
- `Sentry.init({
182
+ });`, 'export const handleError = handleErrorWithSentry(']);
183
+ });
184
+
185
+ test('hooks.server.ts contains sentry', () => {
186
+ checkFileContents(
187
+ path.resolve(projectDir, 'src/hooks.server.ts'),
188
+ [
189
+ `import * as Sentry from '@sentry/sveltekit';`,
190
+ `Sentry.init({
131
191
  dsn: '${TEST_ARGS.PROJECT_DSN}',
132
192
 
133
193
  tracesSampleRate: 1.0,
134
194
 
135
195
  // uncomment the line below to enable Spotlight (https://spotlightjs.com)
136
196
  // spotlight: import.meta.env.DEV,
137
- });`])
138
- });
139
-
140
-
141
- test('runs on dev mode correctly', async () => {
142
- await checkIfRunsOnDevMode(projectDir, 'ready in');
197
+ });`, 'export const handleError = handleErrorWithSentry();']);
198
+ });
143
199
  });
144
200
 
145
- test('should build successfully', async () => {
146
- await checkIfBuilds(projectDir, 'Successfully uploaded source maps to Sentry');
147
- });
201
+ describe('with existing hooks', () => {
202
+ const integration = Integration.sveltekit;
203
+ const projectDir = path.resolve(
204
+ __dirname,
205
+ '../test-applications/sveltekit-test-app',
206
+ );
148
207
 
149
- test('runs on prod mode correctly', async () => {
150
- // We can't use the full prompt `Network: use--host to expose` as `--host` can be printed in bold.
151
- await checkIfRunsOnProdMode(projectDir, 'to expose', "preview");
208
+ beforeAll(async () => {
209
+ await runWizardOnSvelteKitProject(projectDir, integration, (projectDir) => {
210
+ createFile(
211
+ path.resolve(projectDir, 'src/hooks.server.ts'),
212
+ SERVER_HOOK_TEMPLATE,
213
+ )
214
+
215
+ createFile(
216
+ path.resolve(projectDir, 'src/hooks.client.ts'),
217
+ CLIENT_HOOK_TEMPLATE,
218
+ )
219
+ });
220
+ });
221
+
222
+ afterAll(() => {
223
+ revertLocalChanges(projectDir);
224
+ cleanupGit(projectDir);
225
+ });
226
+
227
+ checkSvelteKitProject(projectDir, integration);
228
+
229
+ // These are removed from the common tests as the content is different
230
+ // when the hooks are merged instead of created from the template
231
+ test('hooks.client.ts contains sentry instrumentation', () => {
232
+ checkFileContents(
233
+ path.resolve(projectDir, 'src/hooks.client.ts'),
234
+ [`import * as Sentry from '@sentry/sveltekit';`,
235
+ `Sentry.init({
236
+ dsn: "${TEST_ARGS.PROJECT_DSN}",
237
+ tracesSampleRate: 1,
238
+ replaysSessionSampleRate: 0.1,
239
+ replaysOnErrorSampleRate: 1,
240
+ integrations: [Sentry.replayIntegration()]
241
+ })`, 'export const handleError = Sentry.handleErrorWithSentry(']);
242
+ });
243
+
244
+ test('hooks.server.ts contains sentry init', () => {
245
+ checkFileContents(
246
+ path.resolve(projectDir, 'src/hooks.server.ts'),
247
+ [`import * as Sentry from '@sentry/sveltekit';`,
248
+ `Sentry.init({
249
+ dsn: "${TEST_ARGS.PROJECT_DSN}",
250
+ tracesSampleRate: 1
251
+ })`, 'export const handleError = Sentry.handleErrorWithSentry();']);
252
+ });
152
253
  });
153
254
  });
154
255
 
@@ -227,11 +227,42 @@ export function startWizardInstance(
227
227
  }
228
228
 
229
229
  /**
230
- * Read the file contents and check if it contains the given content
230
+ * Create a file with the given content
231
231
  *
232
232
  * @param filePath
233
233
  * @param content
234
234
  */
235
+ export function createFile(filePath: string, content?: string) {
236
+ return fs.writeFileSync(filePath, content || '');
237
+ }
238
+
239
+ /**
240
+ * Modify the file with the new content
241
+ *
242
+ * @param filePath
243
+ * @param oldContent
244
+ * @param newContent
245
+ */
246
+ export function modifyFile(
247
+ filePath: string,
248
+ replaceMap: Record<string, string>,
249
+ ) {
250
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
251
+ let newFileContent = fileContent;
252
+
253
+ for (const [oldContent, newContent] of Object.entries(replaceMap)) {
254
+ newFileContent = newFileContent.replace(oldContent, newContent);
255
+ }
256
+
257
+ fs.writeFileSync(filePath, newFileContent);
258
+ }
259
+
260
+ /**
261
+ * Read the file contents and check if it contains the given content
262
+ *
263
+ * @param {string} filePath
264
+ * @param {(string | string[])} content
265
+ */
235
266
  export function checkFileContents(
236
267
  filePath: string,
237
268
  content: string | string[],
@@ -255,6 +286,7 @@ export function checkFileExists(filePath: string) {
255
286
 
256
287
  /**
257
288
  * Check if the package.json contains the given integration
289
+ *
258
290
  * @param projectDir
259
291
  * @param integration
260
292
  */
@@ -264,6 +296,7 @@ export function checkPackageJson(projectDir: string, integration: Integration) {
264
296
 
265
297
  /**
266
298
  * Check if the .sentryclirc contains the auth token
299
+ *
267
300
  * @param projectDir
268
301
  */
269
302
  export function checkSentryCliRc(projectDir: string) {
package/lib/Constants.ts CHANGED
@@ -6,6 +6,7 @@ export enum Integration {
6
6
  cordova = 'cordova',
7
7
  electron = 'electron',
8
8
  nextjs = 'nextjs',
9
+ nuxt = 'nuxt',
9
10
  remix = 'remix',
10
11
  sveltekit = 'sveltekit',
11
12
  sourcemaps = 'sourcemaps',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/wizard",
3
- "version": "3.34.4",
3
+ "version": "3.36.0",
4
4
  "homepage": "https://github.com/getsentry/sentry-wizard",
5
5
  "repository": "https://github.com/getsentry/sentry-wizard",
6
6
  "description": "Sentry wizard helping you to configure your project",
@@ -33,8 +33,6 @@ export const manifest = (dsn: string) => `
33
33
 
34
34
  <!-- enable the performance API by setting a sample-rate, adjust in production env -->
35
35
  <meta-data android:name="io.sentry.traces.sample-rate" android:value="1.0" />
36
- <!-- enable profiling when starting transactions, adjust in production env -->
37
- <meta-data android:name="io.sentry.traces.profiling.sample-rate" android:value="1.0" />
38
36
  `;
39
37
 
40
38
  export const sentryImport = `import io.sentry.Sentry;\n`;
@@ -20,7 +20,13 @@ export function getSwiftSnippet(dsn: string): string {
20
20
  return ` SentrySDK.start { options in
21
21
  options.dsn = "${dsn}"
22
22
  options.debug = true // Enabled debug when first installing is always helpful
23
- options.enableTracing = true
23
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
24
+ // We recommend adjusting this value in production.
25
+ options.tracesSampleRate = 1.0
26
+
27
+ // Sample rate for profiling, applied on top of TracesSampleRate.
28
+ // We recommend adjusting this value in production.
29
+ options.profilesSampleRate = 1.0
24
30
 
25
31
  // Uncomment the following lines to add more data to your events
26
32
  // options.attachScreenshot = true // This adds a screenshot to the error events
@@ -34,7 +40,13 @@ export function getObjcSnippet(dsn: string): string {
34
40
  return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {
35
41
  options.dsn = @"${dsn}";
36
42
  options.debug = YES; // Enabled debug when first installing is always helpful
37
- options.enableTracing = YES;
43
+ // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
44
+ // We recommend adjusting this value in production.
45
+ options.tracesSampleRate = @1.0;
46
+
47
+ // Sample rate for profiling, applied on top of TracesSampleRate.
48
+ // We recommend adjusting this value in production.
49
+ options.profilesSampleRate = @1.0;
38
50
 
39
51
  //Uncomment the following lines to add more data to your events
40
52
  //options.attachScreenshot = YES; //This will add a screenshot to the error events
@@ -94,6 +94,7 @@ export async function runNextjsWizardWithTelemetry(
94
94
  const { packageManager: packageManagerFromInstallStep } =
95
95
  await installPackage({
96
96
  packageName: '@sentry/nextjs@^8',
97
+ packageNameDisplayLabel: '@sentry/nextjs',
97
98
  alreadyInstalled: !!packageJson?.dependencies?.['@sentry/nextjs'],
98
99
  });
99
100