@sentry/wizard 3.1.0-beta.0 → 3.1.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 +2 -2
- package/dist/src/nextjs-wizard.js +37 -62
- package/dist/src/nextjs-wizard.js.map +1 -1
- package/dist/src/templates/nextjs-templates.d.ts +13 -0
- package/dist/src/templates/nextjs-templates.js +54 -0
- package/dist/src/templates/nextjs-templates.js.map +1 -0
- package/package.json +1 -1
- package/src/nextjs-wizard.ts +33 -230
- package/src/templates/nextjs-templates.ts +252 -0
package/CHANGELOG.md
CHANGED
|
@@ -53,11 +53,12 @@ var fs = require("fs");
|
|
|
53
53
|
var magicast_1 = require("magicast");
|
|
54
54
|
var path = require("path");
|
|
55
55
|
var clack_utils_1 = require("./clack-utils");
|
|
56
|
+
var nextjs_templates_1 = require("./templates/nextjs-templates");
|
|
56
57
|
// eslint-disable-next-line complexity
|
|
57
58
|
function runNextjsWizard(options) {
|
|
58
59
|
var _a, _b;
|
|
59
60
|
return __awaiter(this, void 0, void 0, function () {
|
|
60
|
-
var packageJsonFileContents, packageJson, continueWithoutNext, _c, sentryUrl, selfHosted, _d, projects, apiKeys, selectedProject, isUsingTypescript, configVariants, _i, configVariants_1, configVariant, jsConfig, tsConfig, jsConfigExists, tsConfigExists, shouldWriteFile, existingConfigs, overwriteExistingConfigs,
|
|
61
|
+
var packageJsonFileContents, packageJson, continueWithoutNext, _c, sentryUrl, selfHosted, _d, projects, apiKeys, selectedProject, isUsingTypescript, configVariants, _i, configVariants_1, configVariant, jsConfig, tsConfig, jsConfigExists, tsConfigExists, shouldWriteFile, existingConfigs, overwriteExistingConfigs, sentryWebpackOptionsTemplate, sentryBuildOptionsTemplate, nextConfigJs, nextConfigMjs, nextConfigJsExists, nextConfigMjsExists, nextConfgiJsContent, probablyIncludesSdk, shouldInject, injectAnyhow, nextConfgiMjsContent, probablyIncludesSdk, shouldInject, injectAnyhow, mod, expressionToWrap, newCode, e_1, shouldContinue, maybePagesDirPath, maybeSrcPagesDirPath, pagesLocation, examplePageContents, mightBeUsingVercel;
|
|
61
62
|
return __generator(this, function (_e) {
|
|
62
63
|
switch (_e.label) {
|
|
63
64
|
case 0:
|
|
@@ -170,7 +171,7 @@ function runNextjsWizard(options) {
|
|
|
170
171
|
_e.label = 11;
|
|
171
172
|
case 11:
|
|
172
173
|
if (!shouldWriteFile) return [3 /*break*/, 13];
|
|
173
|
-
return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), isUsingTypescript ? tsConfig : jsConfig), getSentryConfigContents(selectedProject.keys[0].dsn.public, configVariant), { encoding: 'utf8', flag: 'w' })];
|
|
174
|
+
return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), isUsingTypescript ? tsConfig : jsConfig), (0, nextjs_templates_1.getSentryConfigContents)(selectedProject.keys[0].dsn.public, configVariant), { encoding: 'utf8', flag: 'w' })];
|
|
174
175
|
case 12:
|
|
175
176
|
_e.sent();
|
|
176
177
|
clack.log.success("Created fresh ".concat(chalk_1.default.bold(isUsingTypescript ? tsConfig : jsConfig), "."));
|
|
@@ -179,21 +180,20 @@ function runNextjsWizard(options) {
|
|
|
179
180
|
_i++;
|
|
180
181
|
return [3 /*break*/, 9];
|
|
181
182
|
case 14:
|
|
182
|
-
|
|
183
|
-
sentryBuildOptionsTemplate =
|
|
184
|
-
newNextConfigTemplate = "const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ".concat(webpackOptionsTemplate, ",\n ").concat(sentryBuildOptionsTemplate, "\n);\n");
|
|
183
|
+
sentryWebpackOptionsTemplate = (0, nextjs_templates_1.getNextjsWebpackPluginOptionsTemplate)(selectedProject.organization.slug, selectedProject.slug);
|
|
184
|
+
sentryBuildOptionsTemplate = (0, nextjs_templates_1.getNextjsSentryBuildOptionsTemplate)();
|
|
185
185
|
nextConfigJs = 'next.config.js';
|
|
186
186
|
nextConfigMjs = 'next.config.mjs';
|
|
187
187
|
nextConfigJsExists = fs.existsSync(path.join(process.cwd(), nextConfigJs));
|
|
188
188
|
nextConfigMjsExists = fs.existsSync(path.join(process.cwd(), nextConfigMjs));
|
|
189
189
|
if (!(!nextConfigJsExists && !nextConfigMjsExists)) return [3 /*break*/, 16];
|
|
190
|
-
return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), nextConfigJs),
|
|
190
|
+
return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), nextConfigJs), (0, nextjs_templates_1.getNextjsConfigCjsTemplate)(sentryWebpackOptionsTemplate, sentryBuildOptionsTemplate), { encoding: 'utf8', flag: 'w' })];
|
|
191
191
|
case 15:
|
|
192
192
|
_e.sent();
|
|
193
193
|
clack.log.success("Created ".concat(chalk_1.default.bold('next.config.js'), " with Sentry configuration."));
|
|
194
194
|
_e.label = 16;
|
|
195
195
|
case 16:
|
|
196
|
-
if (!nextConfigJsExists) return [3 /*break*/,
|
|
196
|
+
if (!nextConfigJsExists) return [3 /*break*/, 20];
|
|
197
197
|
nextConfgiJsContent = fs.readFileSync(path.join(process.cwd(), nextConfigJs), 'utf8');
|
|
198
198
|
probablyIncludesSdk = nextConfgiJsContent.includes('@sentry/nextjs') &&
|
|
199
199
|
nextConfgiJsContent.includes('withSentryConfig');
|
|
@@ -208,30 +208,30 @@ function runNextjsWizard(options) {
|
|
|
208
208
|
shouldInject = injectAnyhow;
|
|
209
209
|
_e.label = 18;
|
|
210
210
|
case 18:
|
|
211
|
-
if (shouldInject)
|
|
212
|
-
|
|
213
|
-
fs.appendFileSync(path.join(process.cwd(), nextConfigJs), cjsAppendix, 'utf8');
|
|
214
|
-
clack.log.success("Added Sentry configuration to ".concat(chalk_1.default.bold(nextConfigJs), ". ").concat(chalk_1.default.dim('(you probably want to clean this up a bit!)')));
|
|
215
|
-
}
|
|
216
|
-
_e.label = 19;
|
|
211
|
+
if (!shouldInject) return [3 /*break*/, 20];
|
|
212
|
+
return [4 /*yield*/, fs.promises.appendFile(path.join(process.cwd(), nextConfigJs), (0, nextjs_templates_1.getNextjsConfigCjsAppendix)(sentryWebpackOptionsTemplate, sentryBuildOptionsTemplate), 'utf8')];
|
|
217
213
|
case 19:
|
|
218
|
-
|
|
214
|
+
_e.sent();
|
|
215
|
+
clack.log.success("Added Sentry configuration to ".concat(chalk_1.default.bold(nextConfigJs), ". ").concat(chalk_1.default.dim('(you probably want to clean this up a bit!)')));
|
|
216
|
+
_e.label = 20;
|
|
217
|
+
case 20:
|
|
218
|
+
if (!nextConfigMjsExists) return [3 /*break*/, 27];
|
|
219
219
|
nextConfgiMjsContent = fs.readFileSync(path.join(process.cwd(), nextConfigMjs), 'utf8');
|
|
220
220
|
probablyIncludesSdk = nextConfgiMjsContent.includes('@sentry/nextjs') &&
|
|
221
221
|
nextConfgiMjsContent.includes('withSentryConfig');
|
|
222
222
|
shouldInject = true;
|
|
223
|
-
if (!probablyIncludesSdk) return [3 /*break*/,
|
|
223
|
+
if (!probablyIncludesSdk) return [3 /*break*/, 22];
|
|
224
224
|
return [4 /*yield*/, clack.confirm({
|
|
225
225
|
message: "".concat(chalk_1.default.bold(nextConfigMjs), " already contains Sentry SDK configuration. Should the wizard modify it anyways?"),
|
|
226
226
|
})];
|
|
227
|
-
case
|
|
227
|
+
case 21:
|
|
228
228
|
injectAnyhow = _e.sent();
|
|
229
229
|
(0, clack_utils_1.abortIfCancelled)(injectAnyhow);
|
|
230
230
|
shouldInject = injectAnyhow;
|
|
231
|
-
_e.label =
|
|
232
|
-
case
|
|
233
|
-
_e.trys.push([
|
|
234
|
-
if (!shouldInject) return [3 /*break*/,
|
|
231
|
+
_e.label = 22;
|
|
232
|
+
case 22:
|
|
233
|
+
_e.trys.push([22, 25, , 27]);
|
|
234
|
+
if (!shouldInject) return [3 /*break*/, 24];
|
|
235
235
|
mod = (0, magicast_1.parseModule)(nextConfgiMjsContent);
|
|
236
236
|
mod.imports.$add({
|
|
237
237
|
from: '@sentry/nextjs',
|
|
@@ -240,36 +240,36 @@ function runNextjsWizard(options) {
|
|
|
240
240
|
});
|
|
241
241
|
expressionToWrap = (0, magicast_1.generateCode)(mod.exports.default.$ast).code;
|
|
242
242
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
243
|
-
mod.exports.default = magicast_1.builders.raw("withSentryConfig(\n ".concat(expressionToWrap, ",\n ").concat(
|
|
243
|
+
mod.exports.default = magicast_1.builders.raw("withSentryConfig(\n ".concat(expressionToWrap, ",\n ").concat(sentryWebpackOptionsTemplate, ",\n ").concat(sentryBuildOptionsTemplate, "\n)"));
|
|
244
244
|
newCode = mod.generate().code;
|
|
245
245
|
return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), nextConfigMjs), newCode, {
|
|
246
246
|
encoding: 'utf8',
|
|
247
247
|
flag: 'w',
|
|
248
248
|
})];
|
|
249
|
-
case
|
|
249
|
+
case 23:
|
|
250
250
|
_e.sent();
|
|
251
251
|
clack.log.success("Added Sentry configuration to ".concat(chalk_1.default.bold(nextConfigMjs), ". ").concat(chalk_1.default.dim('(you probably want to clean this up a bit!)')));
|
|
252
|
-
_e.label =
|
|
253
|
-
case
|
|
254
|
-
case
|
|
252
|
+
_e.label = 24;
|
|
253
|
+
case 24: return [3 /*break*/, 27];
|
|
254
|
+
case 25:
|
|
255
255
|
e_1 = _e.sent();
|
|
256
256
|
clack.log.warn(chalk_1.default.yellow("Something went wrong writing to ".concat(chalk_1.default.bold(nextConfigMjs))));
|
|
257
257
|
clack.log.info("Please put the following code snippet into ".concat(chalk_1.default.bold(nextConfigMjs), ": ").concat(chalk_1.default.dim('You probably have to clean it up a bit.'), "\n"));
|
|
258
258
|
// eslint-disable-next-line no-console
|
|
259
|
-
console.log(
|
|
259
|
+
console.log((0, nextjs_templates_1.getNextjsConfigEsmCopyPasteSnippet)(sentryWebpackOptionsTemplate, sentryBuildOptionsTemplate));
|
|
260
260
|
return [4 /*yield*/, clack.confirm({
|
|
261
261
|
message: "Are you done putting the snippet above into ".concat(chalk_1.default.bold(nextConfigMjs), "?"),
|
|
262
262
|
active: 'Yes',
|
|
263
263
|
inactive: 'No, get me out of here',
|
|
264
264
|
})];
|
|
265
|
-
case
|
|
265
|
+
case 26:
|
|
266
266
|
shouldContinue = _e.sent();
|
|
267
267
|
(0, clack_utils_1.abortIfCancelled)(shouldContinue);
|
|
268
268
|
if (!shouldContinue) {
|
|
269
269
|
(0, clack_utils_1.abort)();
|
|
270
270
|
}
|
|
271
|
-
return [3 /*break*/,
|
|
272
|
-
case
|
|
271
|
+
return [3 /*break*/, 27];
|
|
272
|
+
case 27:
|
|
273
273
|
maybePagesDirPath = path.join(process.cwd(), 'pages');
|
|
274
274
|
maybeSrcPagesDirPath = path.join(process.cwd(), 'src', 'pages');
|
|
275
275
|
pagesLocation = fs.existsSync(maybePagesDirPath) &&
|
|
@@ -285,28 +285,28 @@ function runNextjsWizard(options) {
|
|
|
285
285
|
recursive: true,
|
|
286
286
|
});
|
|
287
287
|
}
|
|
288
|
-
if (!pagesLocation) return [3 /*break*/,
|
|
289
|
-
examplePageContents =
|
|
288
|
+
if (!pagesLocation) return [3 /*break*/, 30];
|
|
289
|
+
examplePageContents = (0, nextjs_templates_1.getSentryExamplePageContents)({
|
|
290
290
|
selfHosted: selfHosted,
|
|
291
291
|
orgSlug: selectedProject.organization.slug,
|
|
292
292
|
projectId: selectedProject.id,
|
|
293
293
|
url: sentryUrl,
|
|
294
294
|
});
|
|
295
295
|
return [4 /*yield*/, fs.promises.writeFile(path.join.apply(path, __spreadArray(__spreadArray([process.cwd()], pagesLocation, false), ['sentry-example-page.js'], false)), examplePageContents, { encoding: 'utf8', flag: 'w' })];
|
|
296
|
-
case
|
|
296
|
+
case 28:
|
|
297
297
|
_e.sent();
|
|
298
298
|
clack.log.success("Created ".concat(chalk_1.default.bold(path.join.apply(path, __spreadArray(__spreadArray([], pagesLocation, false), ['sentry-example-page.js'], false))), "."));
|
|
299
299
|
fs.mkdirSync(path.join.apply(path, __spreadArray(__spreadArray([process.cwd()], pagesLocation, false), ['api'], false)), {
|
|
300
300
|
recursive: true,
|
|
301
301
|
});
|
|
302
302
|
return [4 /*yield*/, fs.promises.writeFile(path.join.apply(path, __spreadArray(__spreadArray([process.cwd()], pagesLocation, false), ['api',
|
|
303
|
-
'sentry-example-api.js'], false)),
|
|
304
|
-
case
|
|
303
|
+
'sentry-example-api.js'], false)), (0, nextjs_templates_1.getSentryExampleApiRoute)(), { encoding: 'utf8', flag: 'w' })];
|
|
304
|
+
case 29:
|
|
305
305
|
_e.sent();
|
|
306
306
|
clack.log.success("Created ".concat(chalk_1.default.bold(path.join.apply(path, __spreadArray(__spreadArray([], pagesLocation, false), ['api', 'sentry-example-api.js'], false))), "."));
|
|
307
|
-
_e.label =
|
|
308
|
-
case
|
|
309
|
-
case
|
|
307
|
+
_e.label = 30;
|
|
308
|
+
case 30: return [4 /*yield*/, (0, clack_utils_1.addSentryCliRc)(apiKeys.token)];
|
|
309
|
+
case 31:
|
|
310
310
|
_e.sent();
|
|
311
311
|
mightBeUsingVercel = fs.existsSync(path.join(process.cwd(), 'vercel.json'));
|
|
312
312
|
clack.outro("".concat(chalk_1.default.green('Everything is set up!'), "\n\n ").concat(chalk_1.default.cyan('You can validate your setup by starting your dev environment (`next dev`) and visiting "/sentry-example-page".'), "\n").concat(mightBeUsingVercel
|
|
@@ -318,29 +318,4 @@ function runNextjsWizard(options) {
|
|
|
318
318
|
});
|
|
319
319
|
}
|
|
320
320
|
exports.runNextjsWizard = runNextjsWizard;
|
|
321
|
-
function getSentryConfigContents(dsn, config) {
|
|
322
|
-
var primer;
|
|
323
|
-
if (config === 'server') {
|
|
324
|
-
primer = "// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
325
|
-
}
|
|
326
|
-
else if (config === 'client') {
|
|
327
|
-
primer = "// This file configures the initialization of Sentry on the client.\n// The config you add here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
328
|
-
}
|
|
329
|
-
else if (config === 'edge') {
|
|
330
|
-
primer = "// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
331
|
-
}
|
|
332
|
-
var additionalOptions = '';
|
|
333
|
-
if (config === 'client') {
|
|
334
|
-
additionalOptions = "\n\n replaysOnErrorSampleRate: 1.0,\n\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // You can remove this option if you're not planning to use the Sentry Session Replay feature:\n integrations: [\n new Sentry.Replay({\n // Additional Replay configuration goes in here, for example:\n maskAllText: true,\n blockAllMedia: true,\n }),\n ],";
|
|
335
|
-
}
|
|
336
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
337
|
-
return "".concat(primer, "\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"").concat(dsn, "\",\n\n // Adjust this value in production, or use tracesSampler for greater control\n tracesSampleRate: 1,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,").concat(additionalOptions, "\n});\n");
|
|
338
|
-
}
|
|
339
|
-
function createExamplePage(options) {
|
|
340
|
-
var issuesPageLink = options.selfHosted
|
|
341
|
-
? "".concat(options.url, "organizations/").concat(options.orgSlug, "/issues/?project=").concat(options.projectId)
|
|
342
|
-
: "https://".concat(options.orgSlug, ".sentry.io/issues/?project=").concat(options.projectId);
|
|
343
|
-
return "import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\n\nexport default function Home() {\n return (\n <div>\n <Head>\n <title>Sentry Onboarding</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n ></path>\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={async () => {\n const transaction = Sentry.startTransaction({\n name: \"Example Frontend Transaction\",\n });\n\n Sentry.configureScope((scope) => {\n scope.setSpan(transaction);\n });\n\n try {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n throw new Error(\"Sentry Example Frontend Error\");\n }\n } finally {\n transaction.finish();\n }\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"".concat(issuesPageLink, "\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">\n https://docs.sentry.io/platforms/javascript/guides/nextjs/\n </a>\n </p>\n </main>\n </div>\n );\n}\n");
|
|
344
|
-
}
|
|
345
|
-
var exampleApiRoute = "// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n throw new Error(\"Sentry Example API Route Error\");\n res.status(200).json({ name: \"John Doe\" });\n}\n";
|
|
346
321
|
//# sourceMappingURL=nextjs-wizard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs-wizard.js","sourceRoot":"","sources":["../../src/nextjs-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { builders, generateCode, parseModule } from 'magicast';\nimport * as path from 'path';\n\nimport {\n abort,\n abortIfCancelled,\n addSentryCliRc,\n askForSelfHosted,\n askForWizardLogin,\n confirmContinueEvenThoughNoGitRepo,\n installPackage,\n printWelcome,\n SentryProjectData,\n} from './clack-utils';\n\ninterface NextjsWizardOptions {\n promoCode?: string;\n}\n\n// eslint-disable-next-line complexity\nexport async function runNextjsWizard(\n options: NextjsWizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Next.js Wizard',\n promoCode: options.promoCode,\n });\n\n await confirmContinueEvenThoughNoGitRepo();\n\n const packageJsonFileContents = await fs.promises\n .readFile(path.join(process.cwd(), 'package.json'), 'utf8')\n .catch(() => {\n clack.log.error(\n 'Could not find package.json. Make sure to run the wizard in the root of your Next.js app!',\n );\n abort();\n });\n\n let packageJson:\n | { dependencies?: { ['@sentry/nextjs']: string; ['next']: string } }\n | undefined = undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n packageJson = JSON.parse(packageJsonFileContents);\n } catch (e) {\n clack.log.error(\n 'Unable to parse your package.json. Make sure it has a valid format!',\n );\n\n abort();\n }\n\n if (!packageJson?.dependencies?.['next']) {\n const continueWithoutNext = await clack.confirm({\n message:\n 'Next.js does not seem to be installed. Do you still want to continue?',\n initialValue: false,\n });\n\n abortIfCancelled(continueWithoutNext);\n\n if (!continueWithoutNext) {\n abort();\n }\n }\n\n const { url: sentryUrl, selfHosted } = await askForSelfHosted();\n\n const { projects, apiKeys } = await askForWizardLogin({\n promoCode: options.promoCode,\n url: sentryUrl,\n });\n\n const selectedProject: SentryProjectData | symbol = await clack.select({\n message: 'Select your Sentry project.',\n options: projects.map(project => {\n return {\n value: project,\n label: `${project.organization.slug}/${project.slug}`,\n };\n }),\n });\n\n abortIfCancelled(selectedProject);\n\n await installPackage({\n packageName: '@sentry/nextjs',\n alreadyInstalled: !!packageJson?.dependencies?.['@sentry/nextjs'],\n });\n\n let isUsingTypescript = false;\n try {\n isUsingTypescript = fs.existsSync(\n path.join(process.cwd(), 'tsconfig.json'),\n );\n } catch (e) {\n // noop - Default to assuming user is not using typescript\n }\n\n const configVariants = ['server', 'client', 'edge'] as const;\n\n for (const configVariant of configVariants) {\n const jsConfig = `sentry.${configVariant}.config.js`;\n const tsConfig = `sentry.${configVariant}.config.ts`;\n\n const jsConfigExists = fs.existsSync(path.join(process.cwd(), jsConfig));\n const tsConfigExists = fs.existsSync(path.join(process.cwd(), tsConfig));\n\n let shouldWriteFile = true;\n\n if (jsConfigExists || tsConfigExists) {\n const existingConfigs = [];\n\n if (jsConfigExists) {\n existingConfigs.push(jsConfig);\n }\n\n if (tsConfigExists) {\n existingConfigs.push(tsConfig);\n }\n\n const overwriteExistingConfigs = await clack.confirm({\n message: `Found existing Sentry ${configVariant} config (${existingConfigs.join(\n ', ',\n )}). Overwrite ${existingConfigs.length > 1 ? 'them' : 'it'}?`,\n });\n\n abortIfCancelled(overwriteExistingConfigs);\n\n shouldWriteFile = overwriteExistingConfigs;\n\n if (overwriteExistingConfigs) {\n if (jsConfigExists) {\n fs.unlinkSync(path.join(process.cwd(), jsConfig));\n clack.log.warn(`Removed existing ${chalk.bold(jsConfig)}.`);\n }\n if (tsConfigExists) {\n fs.unlinkSync(path.join(process.cwd(), tsConfig));\n clack.log.warn(`Removed existing ${chalk.bold(tsConfig)}.`);\n }\n }\n }\n\n if (shouldWriteFile) {\n await fs.promises.writeFile(\n path.join(process.cwd(), isUsingTypescript ? tsConfig : jsConfig),\n getSentryConfigContents(\n selectedProject.keys[0].dsn.public,\n configVariant,\n ),\n { encoding: 'utf8', flag: 'w' },\n );\n clack.log.success(\n `Created fresh ${chalk.bold(isUsingTypescript ? tsConfig : jsConfig)}.`,\n );\n }\n }\n\n const webpackOptionsTemplate = `{\n // For all available options, see:\n // https://github.com/getsentry/sentry-webpack-plugin#options\n\n // Suppresses source map uploading logs during build\n silent: true,\n\n org: \"${selectedProject.organization.slug}\",\n project: \"${selectedProject.slug}\",\n }`;\n\n const sentryBuildOptionsTemplate = `{\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 // Transpiles SDK to be compatible with IE11 (increases bundle size)\n transpileClientSDK: true,\n\n // Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)\n tunnelRoute: \"/monitoring\",\n\n // Hides source maps from generated client bundles\n hideSourceMaps: true,\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n }`;\n\n const newNextConfigTemplate = `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ${webpackOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\n`;\n\n const nextConfigJs = 'next.config.js';\n const nextConfigMjs = 'next.config.mjs';\n\n const nextConfigJsExists = fs.existsSync(\n path.join(process.cwd(), nextConfigJs),\n );\n const nextConfigMjsExists = fs.existsSync(\n path.join(process.cwd(), nextConfigMjs),\n );\n\n if (!nextConfigJsExists && !nextConfigMjsExists) {\n await fs.promises.writeFile(\n path.join(process.cwd(), nextConfigJs),\n newNextConfigTemplate,\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold('next.config.js')} with Sentry configuration.`,\n );\n }\n\n if (nextConfigJsExists) {\n const nextConfgiJsContent = fs.readFileSync(\n path.join(process.cwd(), nextConfigJs),\n 'utf8',\n );\n\n const probablyIncludesSdk =\n nextConfgiJsContent.includes('@sentry/nextjs') &&\n nextConfgiJsContent.includes('withSentryConfig');\n\n let shouldInject = true;\n\n if (probablyIncludesSdk) {\n const injectAnyhow = await clack.confirm({\n message: `${chalk.bold(\n nextConfigMjs,\n )} already contains Sentry SDK configuration. Should the wizard modify it anyways?`,\n });\n\n abortIfCancelled(injectAnyhow);\n\n shouldInject = injectAnyhow;\n }\n\n if (shouldInject) {\n const cjsAppendix = `\n\n// Inected Content via Sentry Wizard Below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(\n module.exports,\n ${webpackOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\n`;\n fs.appendFileSync(\n path.join(process.cwd(), nextConfigJs),\n cjsAppendix,\n 'utf8',\n );\n\n clack.log.success(\n `Added Sentry configuration to ${chalk.bold(nextConfigJs)}. ${chalk.dim(\n '(you probably want to clean this up a bit!)',\n )}`,\n );\n }\n }\n\n if (nextConfigMjsExists) {\n const nextConfgiMjsContent = fs.readFileSync(\n path.join(process.cwd(), nextConfigMjs),\n 'utf8',\n );\n\n const probablyIncludesSdk =\n nextConfgiMjsContent.includes('@sentry/nextjs') &&\n nextConfgiMjsContent.includes('withSentryConfig');\n\n let shouldInject = true;\n\n if (probablyIncludesSdk) {\n const injectAnyhow = await clack.confirm({\n message: `${chalk.bold(\n nextConfigMjs,\n )} already contains Sentry SDK configuration. Should the wizard modify it anyways?`,\n });\n\n abortIfCancelled(injectAnyhow);\n shouldInject = injectAnyhow;\n }\n\n try {\n if (shouldInject) {\n const mod = parseModule(nextConfgiMjsContent);\n mod.imports.$add({\n from: '@sentry/nextjs',\n imported: 'withSentryConfig',\n local: 'withSentryConfig',\n });\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access\n const expressionToWrap = generateCode(mod.exports.default.$ast).code;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n mod.exports.default = builders.raw(`withSentryConfig(\n ${expressionToWrap},\n ${webpackOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n)`);\n const newCode = mod.generate().code;\n\n await fs.promises.writeFile(\n path.join(process.cwd(), nextConfigMjs),\n newCode,\n {\n encoding: 'utf8',\n flag: 'w',\n },\n );\n clack.log.success(\n `Added Sentry configuration to ${chalk.bold(\n nextConfigMjs,\n )}. ${chalk.dim('(you probably want to clean this up a bit!)')}`,\n );\n }\n } catch (e) {\n clack.log.warn(\n chalk.yellow(\n `Something went wrong writing to ${chalk.bold(nextConfigMjs)}`,\n ),\n );\n clack.log.info(\n `Please put the following code snippet into ${chalk.bold(\n nextConfigMjs,\n )}: ${chalk.dim('You probably have to clean it up a bit.')}\\n`,\n );\n\n // eslint-disable-next-line no-console\n console.log(`\\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(\n yourNextConfig,\n ${webpackOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\\n`);\n\n const shouldContinue = await clack.confirm({\n message: `Are you done putting the snippet above into ${chalk.bold(\n nextConfigMjs,\n )}?`,\n active: 'Yes',\n inactive: 'No, get me out of here',\n });\n\n abortIfCancelled(shouldContinue);\n if (!shouldContinue) {\n abort();\n }\n }\n }\n\n const maybePagesDirPath = path.join(process.cwd(), 'pages');\n const maybeSrcPagesDirPath = path.join(process.cwd(), 'src', 'pages');\n\n let pagesLocation =\n fs.existsSync(maybePagesDirPath) &&\n fs.lstatSync(maybePagesDirPath).isDirectory()\n ? ['pages']\n : fs.existsSync(maybeSrcPagesDirPath) &&\n fs.lstatSync(maybeSrcPagesDirPath).isDirectory()\n ? ['src', 'pages']\n : undefined;\n\n if (!pagesLocation) {\n pagesLocation = ['pages'];\n fs.mkdirSync(path.join(process.cwd(), ...pagesLocation), {\n recursive: true,\n });\n }\n\n if (pagesLocation) {\n const examplePageContents = createExamplePage({\n selfHosted,\n orgSlug: selectedProject.organization.slug,\n projectId: selectedProject.id,\n url: sentryUrl,\n });\n\n await fs.promises.writeFile(\n path.join(process.cwd(), ...pagesLocation, 'sentry-example-page.js'),\n examplePageContents,\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold(\n path.join(...pagesLocation, 'sentry-example-page.js'),\n )}.`,\n );\n\n fs.mkdirSync(path.join(process.cwd(), ...pagesLocation, 'api'), {\n recursive: true,\n });\n\n await fs.promises.writeFile(\n path.join(\n process.cwd(),\n ...pagesLocation,\n 'api',\n 'sentry-example-api.js',\n ),\n exampleApiRoute,\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold(\n path.join(...pagesLocation, 'api', 'sentry-example-api.js'),\n )}.`,\n );\n }\n\n await addSentryCliRc(apiKeys.token);\n\n const mightBeUsingVercel = fs.existsSync(\n path.join(process.cwd(), 'vercel.json'),\n );\n\n clack.outro(\n `${chalk.green('Everything is set up!')}\n\n ${chalk.cyan(\n 'You can validate your setup by starting your dev environment (`next dev`) and visiting \"/sentry-example-page\".',\n )}\n${\n mightBeUsingVercel\n ? `\n ▲ It seems like you're using Vercel. We recommend using the Sentry Vercel integration: https://vercel.com/integrations/sentry\n`\n : ''\n}\n ${chalk.dim(\n 'If you encounter any issues, let us know here: https://github.com/getsentry/sentry-javascript/issues',\n )}`,\n );\n}\n\nfunction getSentryConfigContents(\n dsn: string,\n config: 'server' | 'client' | 'edge',\n): string {\n let primer;\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'client') {\n primer = `// This file configures the initialization of Sentry on the client.\n// The config you add here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let additionalOptions = '';\n if (config === 'client') {\n additionalOptions = `\n\n replaysOnErrorSampleRate: 1.0,\n\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // You can remove this option if you're not planning to use the Sentry Session Replay feature:\n integrations: [\n new Sentry.Replay({\n // Additional Replay configuration goes in here, for example:\n maskAllText: true,\n blockAllMedia: true,\n }),\n ],`;\n }\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",\n\n // Adjust this value in production, or use tracesSampler for greater control\n tracesSampleRate: 1,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,${additionalOptions}\n});\n`;\n}\n\nfunction createExamplePage(options: {\n selfHosted: boolean;\n url: string;\n orgSlug: string;\n projectId: string;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\n\nexport default function Home() {\n return (\n <div>\n <Head>\n <title>Sentry Onboarding</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n ></path>\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={async () => {\n const transaction = Sentry.startTransaction({\n name: \"Example Frontend Transaction\",\n });\n\n Sentry.configureScope((scope) => {\n scope.setSpan(transaction);\n });\n\n try {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n throw new Error(\"Sentry Example Frontend Error\");\n }\n } finally {\n transaction.finish();\n }\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"${issuesPageLink}\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">\n https://docs.sentry.io/platforms/javascript/guides/nextjs/\n </a>\n </p>\n </main>\n </div>\n );\n}\n`;\n}\n\nconst exampleApiRoute = `// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n throw new Error(\"Sentry Example API Route Error\");\n res.status(200).json({ name: \"John Doe\" });\n}\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"nextjs-wizard.js","sourceRoot":"","sources":["../../src/nextjs-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { builders, generateCode, parseModule } from 'magicast';\nimport * as path from 'path';\n\nimport {\n abort,\n abortIfCancelled,\n addSentryCliRc,\n askForSelfHosted,\n askForWizardLogin,\n confirmContinueEvenThoughNoGitRepo,\n installPackage,\n printWelcome,\n SentryProjectData,\n} from './clack-utils';\nimport {\n getNextjsConfigCjsAppendix,\n getNextjsConfigCjsTemplate,\n getNextjsConfigEsmCopyPasteSnippet,\n getNextjsSentryBuildOptionsTemplate,\n getNextjsWebpackPluginOptionsTemplate,\n getSentryConfigContents,\n getSentryExampleApiRoute,\n getSentryExamplePageContents,\n} from './templates/nextjs-templates';\n\ninterface NextjsWizardOptions {\n promoCode?: string;\n}\n\n// eslint-disable-next-line complexity\nexport async function runNextjsWizard(\n options: NextjsWizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Next.js Wizard',\n promoCode: options.promoCode,\n });\n\n await confirmContinueEvenThoughNoGitRepo();\n\n const packageJsonFileContents = await fs.promises\n .readFile(path.join(process.cwd(), 'package.json'), 'utf8')\n .catch(() => {\n clack.log.error(\n 'Could not find package.json. Make sure to run the wizard in the root of your Next.js app!',\n );\n abort();\n });\n\n let packageJson:\n | { dependencies?: { ['@sentry/nextjs']: string; ['next']: string } }\n | undefined = undefined;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n packageJson = JSON.parse(packageJsonFileContents);\n } catch (e) {\n clack.log.error(\n 'Unable to parse your package.json. Make sure it has a valid format!',\n );\n\n abort();\n }\n\n if (!packageJson?.dependencies?.['next']) {\n const continueWithoutNext = await clack.confirm({\n message:\n 'Next.js does not seem to be installed. Do you still want to continue?',\n initialValue: false,\n });\n\n abortIfCancelled(continueWithoutNext);\n\n if (!continueWithoutNext) {\n abort();\n }\n }\n\n const { url: sentryUrl, selfHosted } = await askForSelfHosted();\n\n const { projects, apiKeys } = await askForWizardLogin({\n promoCode: options.promoCode,\n url: sentryUrl,\n });\n\n const selectedProject: SentryProjectData | symbol = await clack.select({\n message: 'Select your Sentry project.',\n options: projects.map(project => {\n return {\n value: project,\n label: `${project.organization.slug}/${project.slug}`,\n };\n }),\n });\n\n abortIfCancelled(selectedProject);\n\n await installPackage({\n packageName: '@sentry/nextjs',\n alreadyInstalled: !!packageJson?.dependencies?.['@sentry/nextjs'],\n });\n\n let isUsingTypescript = false;\n try {\n isUsingTypescript = fs.existsSync(\n path.join(process.cwd(), 'tsconfig.json'),\n );\n } catch (e) {\n // noop - Default to assuming user is not using typescript\n }\n\n const configVariants = ['server', 'client', 'edge'] as const;\n\n for (const configVariant of configVariants) {\n const jsConfig = `sentry.${configVariant}.config.js`;\n const tsConfig = `sentry.${configVariant}.config.ts`;\n\n const jsConfigExists = fs.existsSync(path.join(process.cwd(), jsConfig));\n const tsConfigExists = fs.existsSync(path.join(process.cwd(), tsConfig));\n\n let shouldWriteFile = true;\n\n if (jsConfigExists || tsConfigExists) {\n const existingConfigs = [];\n\n if (jsConfigExists) {\n existingConfigs.push(jsConfig);\n }\n\n if (tsConfigExists) {\n existingConfigs.push(tsConfig);\n }\n\n const overwriteExistingConfigs = await clack.confirm({\n message: `Found existing Sentry ${configVariant} config (${existingConfigs.join(\n ', ',\n )}). Overwrite ${existingConfigs.length > 1 ? 'them' : 'it'}?`,\n });\n\n abortIfCancelled(overwriteExistingConfigs);\n\n shouldWriteFile = overwriteExistingConfigs;\n\n if (overwriteExistingConfigs) {\n if (jsConfigExists) {\n fs.unlinkSync(path.join(process.cwd(), jsConfig));\n clack.log.warn(`Removed existing ${chalk.bold(jsConfig)}.`);\n }\n if (tsConfigExists) {\n fs.unlinkSync(path.join(process.cwd(), tsConfig));\n clack.log.warn(`Removed existing ${chalk.bold(tsConfig)}.`);\n }\n }\n }\n\n if (shouldWriteFile) {\n await fs.promises.writeFile(\n path.join(process.cwd(), isUsingTypescript ? tsConfig : jsConfig),\n getSentryConfigContents(\n selectedProject.keys[0].dsn.public,\n configVariant,\n ),\n { encoding: 'utf8', flag: 'w' },\n );\n clack.log.success(\n `Created fresh ${chalk.bold(isUsingTypescript ? tsConfig : jsConfig)}.`,\n );\n }\n }\n\n const sentryWebpackOptionsTemplate = getNextjsWebpackPluginOptionsTemplate(\n selectedProject.organization.slug,\n selectedProject.slug,\n );\n const sentryBuildOptionsTemplate = getNextjsSentryBuildOptionsTemplate();\n\n const nextConfigJs = 'next.config.js';\n const nextConfigMjs = 'next.config.mjs';\n\n const nextConfigJsExists = fs.existsSync(\n path.join(process.cwd(), nextConfigJs),\n );\n const nextConfigMjsExists = fs.existsSync(\n path.join(process.cwd(), nextConfigMjs),\n );\n\n if (!nextConfigJsExists && !nextConfigMjsExists) {\n await fs.promises.writeFile(\n path.join(process.cwd(), nextConfigJs),\n getNextjsConfigCjsTemplate(\n sentryWebpackOptionsTemplate,\n sentryBuildOptionsTemplate,\n ),\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold('next.config.js')} with Sentry configuration.`,\n );\n }\n\n if (nextConfigJsExists) {\n const nextConfgiJsContent = fs.readFileSync(\n path.join(process.cwd(), nextConfigJs),\n 'utf8',\n );\n\n const probablyIncludesSdk =\n nextConfgiJsContent.includes('@sentry/nextjs') &&\n nextConfgiJsContent.includes('withSentryConfig');\n\n let shouldInject = true;\n\n if (probablyIncludesSdk) {\n const injectAnyhow = await clack.confirm({\n message: `${chalk.bold(\n nextConfigMjs,\n )} already contains Sentry SDK configuration. Should the wizard modify it anyways?`,\n });\n\n abortIfCancelled(injectAnyhow);\n\n shouldInject = injectAnyhow;\n }\n\n if (shouldInject) {\n await fs.promises.appendFile(\n path.join(process.cwd(), nextConfigJs),\n getNextjsConfigCjsAppendix(\n sentryWebpackOptionsTemplate,\n sentryBuildOptionsTemplate,\n ),\n 'utf8',\n );\n\n clack.log.success(\n `Added Sentry configuration to ${chalk.bold(nextConfigJs)}. ${chalk.dim(\n '(you probably want to clean this up a bit!)',\n )}`,\n );\n }\n }\n\n if (nextConfigMjsExists) {\n const nextConfgiMjsContent = fs.readFileSync(\n path.join(process.cwd(), nextConfigMjs),\n 'utf8',\n );\n\n const probablyIncludesSdk =\n nextConfgiMjsContent.includes('@sentry/nextjs') &&\n nextConfgiMjsContent.includes('withSentryConfig');\n\n let shouldInject = true;\n\n if (probablyIncludesSdk) {\n const injectAnyhow = await clack.confirm({\n message: `${chalk.bold(\n nextConfigMjs,\n )} already contains Sentry SDK configuration. Should the wizard modify it anyways?`,\n });\n\n abortIfCancelled(injectAnyhow);\n shouldInject = injectAnyhow;\n }\n\n try {\n if (shouldInject) {\n const mod = parseModule(nextConfgiMjsContent);\n mod.imports.$add({\n from: '@sentry/nextjs',\n imported: 'withSentryConfig',\n local: 'withSentryConfig',\n });\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access\n const expressionToWrap = generateCode(mod.exports.default.$ast).code;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n mod.exports.default = builders.raw(`withSentryConfig(\n ${expressionToWrap},\n ${sentryWebpackOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n)`);\n const newCode = mod.generate().code;\n\n await fs.promises.writeFile(\n path.join(process.cwd(), nextConfigMjs),\n newCode,\n {\n encoding: 'utf8',\n flag: 'w',\n },\n );\n clack.log.success(\n `Added Sentry configuration to ${chalk.bold(\n nextConfigMjs,\n )}. ${chalk.dim('(you probably want to clean this up a bit!)')}`,\n );\n }\n } catch (e) {\n clack.log.warn(\n chalk.yellow(\n `Something went wrong writing to ${chalk.bold(nextConfigMjs)}`,\n ),\n );\n clack.log.info(\n `Please put the following code snippet into ${chalk.bold(\n nextConfigMjs,\n )}: ${chalk.dim('You probably have to clean it up a bit.')}\\n`,\n );\n\n // eslint-disable-next-line no-console\n console.log(\n getNextjsConfigEsmCopyPasteSnippet(\n sentryWebpackOptionsTemplate,\n sentryBuildOptionsTemplate,\n ),\n );\n\n const shouldContinue = await clack.confirm({\n message: `Are you done putting the snippet above into ${chalk.bold(\n nextConfigMjs,\n )}?`,\n active: 'Yes',\n inactive: 'No, get me out of here',\n });\n\n abortIfCancelled(shouldContinue);\n if (!shouldContinue) {\n abort();\n }\n }\n }\n\n const maybePagesDirPath = path.join(process.cwd(), 'pages');\n const maybeSrcPagesDirPath = path.join(process.cwd(), 'src', 'pages');\n\n let pagesLocation =\n fs.existsSync(maybePagesDirPath) &&\n fs.lstatSync(maybePagesDirPath).isDirectory()\n ? ['pages']\n : fs.existsSync(maybeSrcPagesDirPath) &&\n fs.lstatSync(maybeSrcPagesDirPath).isDirectory()\n ? ['src', 'pages']\n : undefined;\n\n if (!pagesLocation) {\n pagesLocation = ['pages'];\n fs.mkdirSync(path.join(process.cwd(), ...pagesLocation), {\n recursive: true,\n });\n }\n\n if (pagesLocation) {\n const examplePageContents = getSentryExamplePageContents({\n selfHosted,\n orgSlug: selectedProject.organization.slug,\n projectId: selectedProject.id,\n url: sentryUrl,\n });\n\n await fs.promises.writeFile(\n path.join(process.cwd(), ...pagesLocation, 'sentry-example-page.js'),\n examplePageContents,\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold(\n path.join(...pagesLocation, 'sentry-example-page.js'),\n )}.`,\n );\n\n fs.mkdirSync(path.join(process.cwd(), ...pagesLocation, 'api'), {\n recursive: true,\n });\n\n await fs.promises.writeFile(\n path.join(\n process.cwd(),\n ...pagesLocation,\n 'api',\n 'sentry-example-api.js',\n ),\n getSentryExampleApiRoute(),\n { encoding: 'utf8', flag: 'w' },\n );\n\n clack.log.success(\n `Created ${chalk.bold(\n path.join(...pagesLocation, 'api', 'sentry-example-api.js'),\n )}.`,\n );\n }\n\n await addSentryCliRc(apiKeys.token);\n\n const mightBeUsingVercel = fs.existsSync(\n path.join(process.cwd(), 'vercel.json'),\n );\n\n clack.outro(\n `${chalk.green('Everything is set up!')}\n\n ${chalk.cyan(\n 'You can validate your setup by starting your dev environment (`next dev`) and visiting \"/sentry-example-page\".',\n )}\n${\n mightBeUsingVercel\n ? `\n ▲ It seems like you're using Vercel. We recommend using the Sentry Vercel integration: https://vercel.com/integrations/sentry\n`\n : ''\n}\n ${chalk.dim(\n 'If you encounter any issues, let us know here: https://github.com/getsentry/sentry-javascript/issues',\n )}`,\n );\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function getNextjsWebpackPluginOptionsTemplate(orgSlug: string, projectSlug: string): string;
|
|
2
|
+
export declare function getNextjsSentryBuildOptionsTemplate(): string;
|
|
3
|
+
export declare function getNextjsConfigCjsTemplate(sentryWebpackPluginOptionsTemplate: string, sentryBuildOptionsTemplate: string): string;
|
|
4
|
+
export declare function getNextjsConfigCjsAppendix(sentryWebpackPluginOptionsTemplate: string, sentryBuildOptionsTemplate: string): string;
|
|
5
|
+
export declare function getNextjsConfigEsmCopyPasteSnippet(sentryWebpackPluginOptionsTemplate: string, sentryBuildOptionsTemplate: string): string;
|
|
6
|
+
export declare function getSentryConfigContents(dsn: string, config: 'server' | 'client' | 'edge'): string;
|
|
7
|
+
export declare function getSentryExamplePageContents(options: {
|
|
8
|
+
selfHosted: boolean;
|
|
9
|
+
url: string;
|
|
10
|
+
orgSlug: string;
|
|
11
|
+
projectId: string;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function getSentryExampleApiRoute(): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSentryExampleApiRoute = exports.getSentryExamplePageContents = exports.getSentryConfigContents = exports.getNextjsConfigEsmCopyPasteSnippet = exports.getNextjsConfigCjsAppendix = exports.getNextjsConfigCjsTemplate = exports.getNextjsSentryBuildOptionsTemplate = exports.getNextjsWebpackPluginOptionsTemplate = void 0;
|
|
4
|
+
function getNextjsWebpackPluginOptionsTemplate(orgSlug, projectSlug) {
|
|
5
|
+
return "{\n // For all available options, see:\n // https://github.com/getsentry/sentry-webpack-plugin#options\n\n // Suppresses source map uploading logs during build\n silent: true,\n\n org: \"".concat(orgSlug, "\",\n project: \"").concat(projectSlug, "\",\n }");
|
|
6
|
+
}
|
|
7
|
+
exports.getNextjsWebpackPluginOptionsTemplate = getNextjsWebpackPluginOptionsTemplate;
|
|
8
|
+
function getNextjsSentryBuildOptionsTemplate() {
|
|
9
|
+
return "{\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 // Transpiles SDK to be compatible with IE11 (increases bundle size)\n transpileClientSDK: true,\n\n // Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)\n tunnelRoute: \"/monitoring\",\n\n // Hides source maps from generated client bundles\n hideSourceMaps: true,\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n }";
|
|
10
|
+
}
|
|
11
|
+
exports.getNextjsSentryBuildOptionsTemplate = getNextjsSentryBuildOptionsTemplate;
|
|
12
|
+
function getNextjsConfigCjsTemplate(sentryWebpackPluginOptionsTemplate, sentryBuildOptionsTemplate) {
|
|
13
|
+
return "const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ".concat(sentryWebpackPluginOptionsTemplate, ",\n ").concat(sentryBuildOptionsTemplate, "\n);\n");
|
|
14
|
+
}
|
|
15
|
+
exports.getNextjsConfigCjsTemplate = getNextjsConfigCjsTemplate;
|
|
16
|
+
function getNextjsConfigCjsAppendix(sentryWebpackPluginOptionsTemplate, sentryBuildOptionsTemplate) {
|
|
17
|
+
return "\n\n// Inected Content via Sentry Wizard Below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(\n module.exports,\n ".concat(sentryWebpackPluginOptionsTemplate, ",\n ").concat(sentryBuildOptionsTemplate, "\n);\n");
|
|
18
|
+
}
|
|
19
|
+
exports.getNextjsConfigCjsAppendix = getNextjsConfigCjsAppendix;
|
|
20
|
+
function getNextjsConfigEsmCopyPasteSnippet(sentryWebpackPluginOptionsTemplate, sentryBuildOptionsTemplate) {
|
|
21
|
+
return "\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(\n yourNextConfig,\n ".concat(sentryWebpackPluginOptionsTemplate, ",\n ").concat(sentryBuildOptionsTemplate, "\n);\n");
|
|
22
|
+
}
|
|
23
|
+
exports.getNextjsConfigEsmCopyPasteSnippet = getNextjsConfigEsmCopyPasteSnippet;
|
|
24
|
+
function getSentryConfigContents(dsn, config) {
|
|
25
|
+
var primer;
|
|
26
|
+
if (config === 'server') {
|
|
27
|
+
primer = "// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
28
|
+
}
|
|
29
|
+
else if (config === 'client') {
|
|
30
|
+
primer = "// This file configures the initialization of Sentry on the client.\n// The config you add here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
31
|
+
}
|
|
32
|
+
else if (config === 'edge') {
|
|
33
|
+
primer = "// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/";
|
|
34
|
+
}
|
|
35
|
+
var additionalOptions = '';
|
|
36
|
+
if (config === 'client') {
|
|
37
|
+
additionalOptions = "\n\n replaysOnErrorSampleRate: 1.0,\n\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // You can remove this option if you're not planning to use the Sentry Session Replay feature:\n integrations: [\n new Sentry.Replay({\n // Additional Replay configuration goes in here, for example:\n maskAllText: true,\n blockAllMedia: true,\n }),\n ],";
|
|
38
|
+
}
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
40
|
+
return "".concat(primer, "\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"").concat(dsn, "\",\n\n // Adjust this value in production, or use tracesSampler for greater control\n tracesSampleRate: 1,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,").concat(additionalOptions, "\n});\n");
|
|
41
|
+
}
|
|
42
|
+
exports.getSentryConfigContents = getSentryConfigContents;
|
|
43
|
+
function getSentryExamplePageContents(options) {
|
|
44
|
+
var issuesPageLink = options.selfHosted
|
|
45
|
+
? "".concat(options.url, "organizations/").concat(options.orgSlug, "/issues/?project=").concat(options.projectId)
|
|
46
|
+
: "https://".concat(options.orgSlug, ".sentry.io/issues/?project=").concat(options.projectId);
|
|
47
|
+
return "import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\n\nexport default function Home() {\n return (\n <div>\n <Head>\n <title>Sentry Onboarding</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n ></path>\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={async () => {\n const transaction = Sentry.startTransaction({\n name: \"Example Frontend Transaction\",\n });\n\n Sentry.configureScope((scope) => {\n scope.setSpan(transaction);\n });\n\n try {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n throw new Error(\"Sentry Example Frontend Error\");\n }\n } finally {\n transaction.finish();\n }\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"".concat(issuesPageLink, "\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">\n https://docs.sentry.io/platforms/javascript/guides/nextjs/\n </a>\n </p>\n </main>\n </div>\n );\n}\n");
|
|
48
|
+
}
|
|
49
|
+
exports.getSentryExamplePageContents = getSentryExamplePageContents;
|
|
50
|
+
function getSentryExampleApiRoute() {
|
|
51
|
+
return "// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n throw new Error(\"Sentry Example API Route Error\");\n res.status(200).json({ name: \"John Doe\" });\n}\n";
|
|
52
|
+
}
|
|
53
|
+
exports.getSentryExampleApiRoute = getSentryExampleApiRoute;
|
|
54
|
+
//# sourceMappingURL=nextjs-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs-templates.js","sourceRoot":"","sources":["../../../src/templates/nextjs-templates.ts"],"names":[],"mappings":";;;AAAA,SAAgB,qCAAqC,CACnD,OAAe,EACf,WAAmB;IAEnB,OAAO,oNAOG,OAAO,iCACH,WAAW,aACvB,CAAC;AACL,CAAC;AAdD,sFAcC;AAED,SAAgB,mCAAmC;IACjD,OAAO,usBAkBL,CAAC;AACL,CAAC;AApBD,kFAoBC;AAED,SAAgB,0BAA0B,CACxC,kCAA0C,EAC1C,0BAAkC;IAElC,OAAO,gMAOL,kCAAkC,kBAClC,0BAA0B,WAE7B,CAAC;AACF,CAAC;AAfD,gEAeC;AAED,SAAgB,0BAA0B,CACxC,kCAA0C,EAC1C,0BAAkC;IAElC,OAAO,kLAQL,kCAAkC,kBAClC,0BAA0B,WAE7B,CAAC;AACF,CAAC;AAhBD,gEAgBC;AAED,SAAgB,kCAAkC,CAChD,kCAA0C,EAC1C,0BAAkC;IAElC,OAAO,iJAOL,kCAAkC,kBAClC,0BAA0B,WAE7B,CAAC;AACF,CAAC;AAfD,gFAeC;AAED,SAAgB,uBAAuB,CACrC,GAAW,EACX,MAAoC;IAEpC,IAAI,MAAM,CAAC;IACX,IAAI,MAAM,KAAK,QAAQ,EAAE;QACvB,MAAM,GAAG,oNAEiD,CAAC;KAC5D;SAAM,IAAI,MAAM,KAAK,QAAQ,EAAE;QAC9B,MAAM,GAAG,6NAEiD,CAAC;KAC5D;SAAM,IAAI,MAAM,KAAK,MAAM,EAAE;QAC5B,MAAM,GAAG,+WAGiD,CAAC;KAC5D;IAED,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,MAAM,KAAK,QAAQ,EAAE;QACvB,iBAAiB,GAAG,gfAenB,CAAC;KACH;IAED,4EAA4E;IAC5E,OAAO,UAAG,MAAM,wFAKR,GAAG,4PAMI,iBAAiB,YAEjC,CAAC;AACF,CAAC;AAvDD,0DAuDC;AAED,SAAgB,4BAA4B,CAAC,OAK5C;IACC,IAAM,cAAc,GAAG,OAAO,CAAC,UAAU;QACvC,CAAC,CAAC,UAAG,OAAO,CAAC,GAAG,2BAAiB,OAAO,CAAC,OAAO,8BAAoB,OAAO,CAAC,SAAS,CAAE;QACvF,CAAC,CAAC,kBAAW,OAAO,CAAC,OAAO,wCAA8B,OAAO,CAAC,SAAS,CAAE,CAAC;IAEhF,OAAO,uxGAwEY,cAAc,8VAYlC,CAAC;AACF,CAAC;AA/FD,oEA+FC;AAED,SAAgB,wBAAwB;IACtC,OAAO,qNAKR,CAAC;AACF,CAAC;AAPD,4DAOC","sourcesContent":["export function getNextjsWebpackPluginOptionsTemplate(\n orgSlug: string,\n projectSlug: string,\n): string {\n return `{\n // For all available options, see:\n // https://github.com/getsentry/sentry-webpack-plugin#options\n\n // Suppresses source map uploading logs during build\n silent: true,\n\n org: \"${orgSlug}\",\n project: \"${projectSlug}\",\n }`;\n}\n\nexport function getNextjsSentryBuildOptionsTemplate(): string {\n return `{\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 // Transpiles SDK to be compatible with IE11 (increases bundle size)\n transpileClientSDK: true,\n\n // Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)\n tunnelRoute: \"/monitoring\",\n\n // Hides source maps from generated client bundles\n hideSourceMaps: true,\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n }`;\n}\n\nexport function getNextjsConfigCjsTemplate(\n sentryWebpackPluginOptionsTemplate: string,\n sentryBuildOptionsTemplate: string,\n): string {\n return `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ${sentryWebpackPluginOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigCjsAppendix(\n sentryWebpackPluginOptionsTemplate: string,\n sentryBuildOptionsTemplate: string,\n): string {\n return `\n\n// Inected Content via Sentry Wizard Below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(\n module.exports,\n ${sentryWebpackPluginOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigEsmCopyPasteSnippet(\n sentryWebpackPluginOptionsTemplate: string,\n sentryBuildOptionsTemplate: string,\n): string {\n return `\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(\n yourNextConfig,\n ${sentryWebpackPluginOptionsTemplate},\n ${sentryBuildOptionsTemplate}\n);\n`;\n}\n\nexport function getSentryConfigContents(\n dsn: string,\n config: 'server' | 'client' | 'edge',\n): string {\n let primer;\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'client') {\n primer = `// This file configures the initialization of Sentry on the client.\n// The config you add here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let additionalOptions = '';\n if (config === 'client') {\n additionalOptions = `\n\n replaysOnErrorSampleRate: 1.0,\n\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // You can remove this option if you're not planning to use the Sentry Session Replay feature:\n integrations: [\n new Sentry.Replay({\n // Additional Replay configuration goes in here, for example:\n maskAllText: true,\n blockAllMedia: true,\n }),\n ],`;\n }\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",\n\n // Adjust this value in production, or use tracesSampler for greater control\n tracesSampleRate: 1,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,${additionalOptions}\n});\n`;\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n url: string;\n orgSlug: string;\n projectId: string;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\n\nexport default function Home() {\n return (\n <div>\n <Head>\n <title>Sentry Onboarding</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n ></path>\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={async () => {\n const transaction = Sentry.startTransaction({\n name: \"Example Frontend Transaction\",\n });\n\n Sentry.configureScope((scope) => {\n scope.setSpan(transaction);\n });\n\n try {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n throw new Error(\"Sentry Example Frontend Error\");\n }\n } finally {\n transaction.finish();\n }\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"${issuesPageLink}\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">\n https://docs.sentry.io/platforms/javascript/guides/nextjs/\n </a>\n </p>\n </main>\n </div>\n );\n}\n`;\n}\n\nexport function getSentryExampleApiRoute() {\n return `// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n throw new Error(\"Sentry Example API Route Error\");\n res.status(200).json({ name: \"John Doe\" });\n}\n`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.1.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"homepage": "https://github.com/getsentry/sentry-wizard",
|
|
5
5
|
"repository": "https://github.com/getsentry/sentry-wizard",
|
|
6
6
|
"description": "Sentry wizard helping you to configure your project",
|
package/src/nextjs-wizard.ts
CHANGED
|
@@ -16,6 +16,16 @@ import {
|
|
|
16
16
|
printWelcome,
|
|
17
17
|
SentryProjectData,
|
|
18
18
|
} from './clack-utils';
|
|
19
|
+
import {
|
|
20
|
+
getNextjsConfigCjsAppendix,
|
|
21
|
+
getNextjsConfigCjsTemplate,
|
|
22
|
+
getNextjsConfigEsmCopyPasteSnippet,
|
|
23
|
+
getNextjsSentryBuildOptionsTemplate,
|
|
24
|
+
getNextjsWebpackPluginOptionsTemplate,
|
|
25
|
+
getSentryConfigContents,
|
|
26
|
+
getSentryExampleApiRoute,
|
|
27
|
+
getSentryExamplePageContents,
|
|
28
|
+
} from './templates/nextjs-templates';
|
|
19
29
|
|
|
20
30
|
interface NextjsWizardOptions {
|
|
21
31
|
promoCode?: string;
|
|
@@ -162,48 +172,11 @@ export async function runNextjsWizard(
|
|
|
162
172
|
}
|
|
163
173
|
}
|
|
164
174
|
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
silent: true,
|
|
171
|
-
|
|
172
|
-
org: "${selectedProject.organization.slug}",
|
|
173
|
-
project: "${selectedProject.slug}",
|
|
174
|
-
}`;
|
|
175
|
-
|
|
176
|
-
const sentryBuildOptionsTemplate = `{
|
|
177
|
-
// For all available options, see:
|
|
178
|
-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
179
|
-
|
|
180
|
-
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
181
|
-
widenClientFileUpload: true,
|
|
182
|
-
|
|
183
|
-
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
|
184
|
-
transpileClientSDK: true,
|
|
185
|
-
|
|
186
|
-
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
|
|
187
|
-
tunnelRoute: "/monitoring",
|
|
188
|
-
|
|
189
|
-
// Hides source maps from generated client bundles
|
|
190
|
-
hideSourceMaps: true,
|
|
191
|
-
|
|
192
|
-
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
193
|
-
disableLogger: true,
|
|
194
|
-
}`;
|
|
195
|
-
|
|
196
|
-
const newNextConfigTemplate = `const { withSentryConfig } = require("@sentry/nextjs");
|
|
197
|
-
|
|
198
|
-
/** @type {import('next').NextConfig} */
|
|
199
|
-
const nextConfig = {};
|
|
200
|
-
|
|
201
|
-
module.exports = withSentryConfig(
|
|
202
|
-
nextConfig,
|
|
203
|
-
${webpackOptionsTemplate},
|
|
204
|
-
${sentryBuildOptionsTemplate}
|
|
205
|
-
);
|
|
206
|
-
`;
|
|
175
|
+
const sentryWebpackOptionsTemplate = getNextjsWebpackPluginOptionsTemplate(
|
|
176
|
+
selectedProject.organization.slug,
|
|
177
|
+
selectedProject.slug,
|
|
178
|
+
);
|
|
179
|
+
const sentryBuildOptionsTemplate = getNextjsSentryBuildOptionsTemplate();
|
|
207
180
|
|
|
208
181
|
const nextConfigJs = 'next.config.js';
|
|
209
182
|
const nextConfigMjs = 'next.config.mjs';
|
|
@@ -218,7 +191,10 @@ module.exports = withSentryConfig(
|
|
|
218
191
|
if (!nextConfigJsExists && !nextConfigMjsExists) {
|
|
219
192
|
await fs.promises.writeFile(
|
|
220
193
|
path.join(process.cwd(), nextConfigJs),
|
|
221
|
-
|
|
194
|
+
getNextjsConfigCjsTemplate(
|
|
195
|
+
sentryWebpackOptionsTemplate,
|
|
196
|
+
sentryBuildOptionsTemplate,
|
|
197
|
+
),
|
|
222
198
|
{ encoding: 'utf8', flag: 'w' },
|
|
223
199
|
);
|
|
224
200
|
|
|
@@ -252,21 +228,12 @@ module.exports = withSentryConfig(
|
|
|
252
228
|
}
|
|
253
229
|
|
|
254
230
|
if (shouldInject) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// Inected Content via Sentry Wizard Below
|
|
258
|
-
|
|
259
|
-
const { withSentryConfig } = require("@sentry/nextjs");
|
|
260
|
-
|
|
261
|
-
module.exports = withSentryConfig(
|
|
262
|
-
module.exports,
|
|
263
|
-
${webpackOptionsTemplate},
|
|
264
|
-
${sentryBuildOptionsTemplate}
|
|
265
|
-
);
|
|
266
|
-
`;
|
|
267
|
-
fs.appendFileSync(
|
|
231
|
+
await fs.promises.appendFile(
|
|
268
232
|
path.join(process.cwd(), nextConfigJs),
|
|
269
|
-
|
|
233
|
+
getNextjsConfigCjsAppendix(
|
|
234
|
+
sentryWebpackOptionsTemplate,
|
|
235
|
+
sentryBuildOptionsTemplate,
|
|
236
|
+
),
|
|
270
237
|
'utf8',
|
|
271
238
|
);
|
|
272
239
|
|
|
@@ -314,7 +281,7 @@ module.exports = withSentryConfig(
|
|
|
314
281
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
315
282
|
mod.exports.default = builders.raw(`withSentryConfig(
|
|
316
283
|
${expressionToWrap},
|
|
317
|
-
${
|
|
284
|
+
${sentryWebpackOptionsTemplate},
|
|
318
285
|
${sentryBuildOptionsTemplate}
|
|
319
286
|
)`);
|
|
320
287
|
const newCode = mod.generate().code;
|
|
@@ -346,15 +313,12 @@ module.exports = withSentryConfig(
|
|
|
346
313
|
);
|
|
347
314
|
|
|
348
315
|
// eslint-disable-next-line no-console
|
|
349
|
-
console.log(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
${webpackOptionsTemplate},
|
|
356
|
-
${sentryBuildOptionsTemplate}
|
|
357
|
-
);\n`);
|
|
316
|
+
console.log(
|
|
317
|
+
getNextjsConfigEsmCopyPasteSnippet(
|
|
318
|
+
sentryWebpackOptionsTemplate,
|
|
319
|
+
sentryBuildOptionsTemplate,
|
|
320
|
+
),
|
|
321
|
+
);
|
|
358
322
|
|
|
359
323
|
const shouldContinue = await clack.confirm({
|
|
360
324
|
message: `Are you done putting the snippet above into ${chalk.bold(
|
|
@@ -391,7 +355,7 @@ export default withSentryConfig(
|
|
|
391
355
|
}
|
|
392
356
|
|
|
393
357
|
if (pagesLocation) {
|
|
394
|
-
const examplePageContents =
|
|
358
|
+
const examplePageContents = getSentryExamplePageContents({
|
|
395
359
|
selfHosted,
|
|
396
360
|
orgSlug: selectedProject.organization.slug,
|
|
397
361
|
projectId: selectedProject.id,
|
|
@@ -421,7 +385,7 @@ export default withSentryConfig(
|
|
|
421
385
|
'api',
|
|
422
386
|
'sentry-example-api.js',
|
|
423
387
|
),
|
|
424
|
-
|
|
388
|
+
getSentryExampleApiRoute(),
|
|
425
389
|
{ encoding: 'utf8', flag: 'w' },
|
|
426
390
|
);
|
|
427
391
|
|
|
@@ -456,164 +420,3 @@ ${
|
|
|
456
420
|
)}`,
|
|
457
421
|
);
|
|
458
422
|
}
|
|
459
|
-
|
|
460
|
-
function getSentryConfigContents(
|
|
461
|
-
dsn: string,
|
|
462
|
-
config: 'server' | 'client' | 'edge',
|
|
463
|
-
): string {
|
|
464
|
-
let primer;
|
|
465
|
-
if (config === 'server') {
|
|
466
|
-
primer = `// This file configures the initialization of Sentry on the server.
|
|
467
|
-
// The config you add here will be used whenever the server handles a request.
|
|
468
|
-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
469
|
-
} else if (config === 'client') {
|
|
470
|
-
primer = `// This file configures the initialization of Sentry on the client.
|
|
471
|
-
// The config you add here will be used whenever a users loads a page in their browser.
|
|
472
|
-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
473
|
-
} else if (config === 'edge') {
|
|
474
|
-
primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
|
|
475
|
-
// The config you add here will be used whenever one of the edge features is loaded.
|
|
476
|
-
// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.
|
|
477
|
-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
let additionalOptions = '';
|
|
481
|
-
if (config === 'client') {
|
|
482
|
-
additionalOptions = `
|
|
483
|
-
|
|
484
|
-
replaysOnErrorSampleRate: 1.0,
|
|
485
|
-
|
|
486
|
-
// This sets the sample rate to be 10%. You may want this to be 100% while
|
|
487
|
-
// in development and sample at a lower rate in production
|
|
488
|
-
replaysSessionSampleRate: 0.1,
|
|
489
|
-
|
|
490
|
-
// You can remove this option if you're not planning to use the Sentry Session Replay feature:
|
|
491
|
-
integrations: [
|
|
492
|
-
new Sentry.Replay({
|
|
493
|
-
// Additional Replay configuration goes in here, for example:
|
|
494
|
-
maskAllText: true,
|
|
495
|
-
blockAllMedia: true,
|
|
496
|
-
}),
|
|
497
|
-
],`;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
501
|
-
return `${primer}
|
|
502
|
-
|
|
503
|
-
import * as Sentry from "@sentry/nextjs";
|
|
504
|
-
|
|
505
|
-
Sentry.init({
|
|
506
|
-
dsn: "${dsn}",
|
|
507
|
-
|
|
508
|
-
// Adjust this value in production, or use tracesSampler for greater control
|
|
509
|
-
tracesSampleRate: 1,
|
|
510
|
-
|
|
511
|
-
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
512
|
-
debug: false,${additionalOptions}
|
|
513
|
-
});
|
|
514
|
-
`;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
function createExamplePage(options: {
|
|
518
|
-
selfHosted: boolean;
|
|
519
|
-
url: string;
|
|
520
|
-
orgSlug: string;
|
|
521
|
-
projectId: string;
|
|
522
|
-
}): string {
|
|
523
|
-
const issuesPageLink = options.selfHosted
|
|
524
|
-
? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`
|
|
525
|
-
: `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;
|
|
526
|
-
|
|
527
|
-
return `import Head from "next/head";
|
|
528
|
-
import * as Sentry from "@sentry/nextjs";
|
|
529
|
-
|
|
530
|
-
export default function Home() {
|
|
531
|
-
return (
|
|
532
|
-
<div>
|
|
533
|
-
<Head>
|
|
534
|
-
<title>Sentry Onboarding</title>
|
|
535
|
-
<meta name="description" content="Test Sentry for your Next.js app!" />
|
|
536
|
-
</Head>
|
|
537
|
-
|
|
538
|
-
<main
|
|
539
|
-
style={{
|
|
540
|
-
minHeight: "100vh",
|
|
541
|
-
display: "flex",
|
|
542
|
-
flexDirection: "column",
|
|
543
|
-
justifyContent: "center",
|
|
544
|
-
alignItems: "center",
|
|
545
|
-
}}
|
|
546
|
-
>
|
|
547
|
-
<h1 style={{ fontSize: "4rem", margin: "14px 0" }}>
|
|
548
|
-
<svg
|
|
549
|
-
style={{
|
|
550
|
-
height: "1em",
|
|
551
|
-
}}
|
|
552
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
553
|
-
viewBox="0 0 200 44"
|
|
554
|
-
>
|
|
555
|
-
<path
|
|
556
|
-
fill="currentColor"
|
|
557
|
-
d="M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z"
|
|
558
|
-
></path>
|
|
559
|
-
</svg>
|
|
560
|
-
</h1>
|
|
561
|
-
|
|
562
|
-
<p>Get started by sending us a sample error:</p>
|
|
563
|
-
<button
|
|
564
|
-
type="button"
|
|
565
|
-
style={{
|
|
566
|
-
padding: "12px",
|
|
567
|
-
cursor: "pointer",
|
|
568
|
-
backgroundColor: "#AD6CAA",
|
|
569
|
-
borderRadius: "4px",
|
|
570
|
-
border: "none",
|
|
571
|
-
color: "white",
|
|
572
|
-
fontSize: "14px",
|
|
573
|
-
margin: "18px",
|
|
574
|
-
}}
|
|
575
|
-
onClick={async () => {
|
|
576
|
-
const transaction = Sentry.startTransaction({
|
|
577
|
-
name: "Example Frontend Transaction",
|
|
578
|
-
});
|
|
579
|
-
|
|
580
|
-
Sentry.configureScope((scope) => {
|
|
581
|
-
scope.setSpan(transaction);
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
try {
|
|
585
|
-
const res = await fetch("/api/sentry-example-api");
|
|
586
|
-
if (!res.ok) {
|
|
587
|
-
throw new Error("Sentry Example Frontend Error");
|
|
588
|
-
}
|
|
589
|
-
} finally {
|
|
590
|
-
transaction.finish();
|
|
591
|
-
}
|
|
592
|
-
}}
|
|
593
|
-
>
|
|
594
|
-
Throw error!
|
|
595
|
-
</button>
|
|
596
|
-
|
|
597
|
-
<p>
|
|
598
|
-
Next, look for the error on the{" "}
|
|
599
|
-
<a href="${issuesPageLink}">Issues Page</a>.
|
|
600
|
-
</p>
|
|
601
|
-
<p style={{ marginTop: "24px" }}>
|
|
602
|
-
For more information, see{" "}
|
|
603
|
-
<a href="https://docs.sentry.io/platforms/javascript/guides/nextjs/">
|
|
604
|
-
https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
|
605
|
-
</a>
|
|
606
|
-
</p>
|
|
607
|
-
</main>
|
|
608
|
-
</div>
|
|
609
|
-
);
|
|
610
|
-
}
|
|
611
|
-
`;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const exampleApiRoute = `// A faulty API route to test Sentry's error monitoring
|
|
615
|
-
export default function handler(_req, res) {
|
|
616
|
-
throw new Error("Sentry Example API Route Error");
|
|
617
|
-
res.status(200).json({ name: "John Doe" });
|
|
618
|
-
}
|
|
619
|
-
`;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
export function getNextjsWebpackPluginOptionsTemplate(
|
|
2
|
+
orgSlug: string,
|
|
3
|
+
projectSlug: string,
|
|
4
|
+
): string {
|
|
5
|
+
return `{
|
|
6
|
+
// For all available options, see:
|
|
7
|
+
// https://github.com/getsentry/sentry-webpack-plugin#options
|
|
8
|
+
|
|
9
|
+
// Suppresses source map uploading logs during build
|
|
10
|
+
silent: true,
|
|
11
|
+
|
|
12
|
+
org: "${orgSlug}",
|
|
13
|
+
project: "${projectSlug}",
|
|
14
|
+
}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getNextjsSentryBuildOptionsTemplate(): string {
|
|
18
|
+
return `{
|
|
19
|
+
// For all available options, see:
|
|
20
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
21
|
+
|
|
22
|
+
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
23
|
+
widenClientFileUpload: true,
|
|
24
|
+
|
|
25
|
+
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
|
26
|
+
transpileClientSDK: true,
|
|
27
|
+
|
|
28
|
+
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
|
|
29
|
+
tunnelRoute: "/monitoring",
|
|
30
|
+
|
|
31
|
+
// Hides source maps from generated client bundles
|
|
32
|
+
hideSourceMaps: true,
|
|
33
|
+
|
|
34
|
+
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
35
|
+
disableLogger: true,
|
|
36
|
+
}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getNextjsConfigCjsTemplate(
|
|
40
|
+
sentryWebpackPluginOptionsTemplate: string,
|
|
41
|
+
sentryBuildOptionsTemplate: string,
|
|
42
|
+
): string {
|
|
43
|
+
return `const { withSentryConfig } = require("@sentry/nextjs");
|
|
44
|
+
|
|
45
|
+
/** @type {import('next').NextConfig} */
|
|
46
|
+
const nextConfig = {};
|
|
47
|
+
|
|
48
|
+
module.exports = withSentryConfig(
|
|
49
|
+
nextConfig,
|
|
50
|
+
${sentryWebpackPluginOptionsTemplate},
|
|
51
|
+
${sentryBuildOptionsTemplate}
|
|
52
|
+
);
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getNextjsConfigCjsAppendix(
|
|
57
|
+
sentryWebpackPluginOptionsTemplate: string,
|
|
58
|
+
sentryBuildOptionsTemplate: string,
|
|
59
|
+
): string {
|
|
60
|
+
return `
|
|
61
|
+
|
|
62
|
+
// Inected Content via Sentry Wizard Below
|
|
63
|
+
|
|
64
|
+
const { withSentryConfig } = require("@sentry/nextjs");
|
|
65
|
+
|
|
66
|
+
module.exports = withSentryConfig(
|
|
67
|
+
module.exports,
|
|
68
|
+
${sentryWebpackPluginOptionsTemplate},
|
|
69
|
+
${sentryBuildOptionsTemplate}
|
|
70
|
+
);
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function getNextjsConfigEsmCopyPasteSnippet(
|
|
75
|
+
sentryWebpackPluginOptionsTemplate: string,
|
|
76
|
+
sentryBuildOptionsTemplate: string,
|
|
77
|
+
): string {
|
|
78
|
+
return `
|
|
79
|
+
|
|
80
|
+
// next.config.mjs
|
|
81
|
+
import { withSentryConfig } from "@sentry/nextjs";
|
|
82
|
+
|
|
83
|
+
export default withSentryConfig(
|
|
84
|
+
yourNextConfig,
|
|
85
|
+
${sentryWebpackPluginOptionsTemplate},
|
|
86
|
+
${sentryBuildOptionsTemplate}
|
|
87
|
+
);
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getSentryConfigContents(
|
|
92
|
+
dsn: string,
|
|
93
|
+
config: 'server' | 'client' | 'edge',
|
|
94
|
+
): string {
|
|
95
|
+
let primer;
|
|
96
|
+
if (config === 'server') {
|
|
97
|
+
primer = `// This file configures the initialization of Sentry on the server.
|
|
98
|
+
// The config you add here will be used whenever the server handles a request.
|
|
99
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
100
|
+
} else if (config === 'client') {
|
|
101
|
+
primer = `// This file configures the initialization of Sentry on the client.
|
|
102
|
+
// The config you add here will be used whenever a users loads a page in their browser.
|
|
103
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
104
|
+
} else if (config === 'edge') {
|
|
105
|
+
primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
|
|
106
|
+
// The config you add here will be used whenever one of the edge features is loaded.
|
|
107
|
+
// Note that this config is unrelated to the Verel Edge Runtime and is also required when running locally.
|
|
108
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let additionalOptions = '';
|
|
112
|
+
if (config === 'client') {
|
|
113
|
+
additionalOptions = `
|
|
114
|
+
|
|
115
|
+
replaysOnErrorSampleRate: 1.0,
|
|
116
|
+
|
|
117
|
+
// This sets the sample rate to be 10%. You may want this to be 100% while
|
|
118
|
+
// in development and sample at a lower rate in production
|
|
119
|
+
replaysSessionSampleRate: 0.1,
|
|
120
|
+
|
|
121
|
+
// You can remove this option if you're not planning to use the Sentry Session Replay feature:
|
|
122
|
+
integrations: [
|
|
123
|
+
new Sentry.Replay({
|
|
124
|
+
// Additional Replay configuration goes in here, for example:
|
|
125
|
+
maskAllText: true,
|
|
126
|
+
blockAllMedia: true,
|
|
127
|
+
}),
|
|
128
|
+
],`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
132
|
+
return `${primer}
|
|
133
|
+
|
|
134
|
+
import * as Sentry from "@sentry/nextjs";
|
|
135
|
+
|
|
136
|
+
Sentry.init({
|
|
137
|
+
dsn: "${dsn}",
|
|
138
|
+
|
|
139
|
+
// Adjust this value in production, or use tracesSampler for greater control
|
|
140
|
+
tracesSampleRate: 1,
|
|
141
|
+
|
|
142
|
+
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
143
|
+
debug: false,${additionalOptions}
|
|
144
|
+
});
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function getSentryExamplePageContents(options: {
|
|
149
|
+
selfHosted: boolean;
|
|
150
|
+
url: string;
|
|
151
|
+
orgSlug: string;
|
|
152
|
+
projectId: string;
|
|
153
|
+
}): string {
|
|
154
|
+
const issuesPageLink = options.selfHosted
|
|
155
|
+
? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`
|
|
156
|
+
: `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;
|
|
157
|
+
|
|
158
|
+
return `import Head from "next/head";
|
|
159
|
+
import * as Sentry from "@sentry/nextjs";
|
|
160
|
+
|
|
161
|
+
export default function Home() {
|
|
162
|
+
return (
|
|
163
|
+
<div>
|
|
164
|
+
<Head>
|
|
165
|
+
<title>Sentry Onboarding</title>
|
|
166
|
+
<meta name="description" content="Test Sentry for your Next.js app!" />
|
|
167
|
+
</Head>
|
|
168
|
+
|
|
169
|
+
<main
|
|
170
|
+
style={{
|
|
171
|
+
minHeight: "100vh",
|
|
172
|
+
display: "flex",
|
|
173
|
+
flexDirection: "column",
|
|
174
|
+
justifyContent: "center",
|
|
175
|
+
alignItems: "center",
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
<h1 style={{ fontSize: "4rem", margin: "14px 0" }}>
|
|
179
|
+
<svg
|
|
180
|
+
style={{
|
|
181
|
+
height: "1em",
|
|
182
|
+
}}
|
|
183
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
184
|
+
viewBox="0 0 200 44"
|
|
185
|
+
>
|
|
186
|
+
<path
|
|
187
|
+
fill="currentColor"
|
|
188
|
+
d="M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z"
|
|
189
|
+
></path>
|
|
190
|
+
</svg>
|
|
191
|
+
</h1>
|
|
192
|
+
|
|
193
|
+
<p>Get started by sending us a sample error:</p>
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
style={{
|
|
197
|
+
padding: "12px",
|
|
198
|
+
cursor: "pointer",
|
|
199
|
+
backgroundColor: "#AD6CAA",
|
|
200
|
+
borderRadius: "4px",
|
|
201
|
+
border: "none",
|
|
202
|
+
color: "white",
|
|
203
|
+
fontSize: "14px",
|
|
204
|
+
margin: "18px",
|
|
205
|
+
}}
|
|
206
|
+
onClick={async () => {
|
|
207
|
+
const transaction = Sentry.startTransaction({
|
|
208
|
+
name: "Example Frontend Transaction",
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
Sentry.configureScope((scope) => {
|
|
212
|
+
scope.setSpan(transaction);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const res = await fetch("/api/sentry-example-api");
|
|
217
|
+
if (!res.ok) {
|
|
218
|
+
throw new Error("Sentry Example Frontend Error");
|
|
219
|
+
}
|
|
220
|
+
} finally {
|
|
221
|
+
transaction.finish();
|
|
222
|
+
}
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
Throw error!
|
|
226
|
+
</button>
|
|
227
|
+
|
|
228
|
+
<p>
|
|
229
|
+
Next, look for the error on the{" "}
|
|
230
|
+
<a href="${issuesPageLink}">Issues Page</a>.
|
|
231
|
+
</p>
|
|
232
|
+
<p style={{ marginTop: "24px" }}>
|
|
233
|
+
For more information, see{" "}
|
|
234
|
+
<a href="https://docs.sentry.io/platforms/javascript/guides/nextjs/">
|
|
235
|
+
https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
|
236
|
+
</a>
|
|
237
|
+
</p>
|
|
238
|
+
</main>
|
|
239
|
+
</div>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
`;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function getSentryExampleApiRoute() {
|
|
246
|
+
return `// A faulty API route to test Sentry's error monitoring
|
|
247
|
+
export default function handler(_req, res) {
|
|
248
|
+
throw new Error("Sentry Example API Route Error");
|
|
249
|
+
res.status(200).json({ name: "John Doe" });
|
|
250
|
+
}
|
|
251
|
+
`;
|
|
252
|
+
}
|