@sentry/wizard 3.10.0 → 3.12.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 +54 -7
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +8 -4
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Android.d.ts +9 -0
- package/dist/lib/Steps/Integrations/Android.js +86 -0
- package/dist/lib/Steps/Integrations/Android.js.map +1 -0
- package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/PromptForParameters.js +36 -3
- package/dist/lib/Steps/PromptForParameters.js.map +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
- package/dist/package.json +4 -3
- package/dist/src/android/android-wizard.d.ts +2 -0
- package/dist/src/android/android-wizard.js +225 -0
- package/dist/src/android/android-wizard.js.map +1 -0
- package/dist/src/android/code-tools.d.ts +47 -0
- package/dist/src/android/code-tools.js +173 -0
- package/dist/src/android/code-tools.js.map +1 -0
- package/dist/src/android/gradle.d.ts +62 -0
- package/dist/src/android/gradle.js +286 -0
- package/dist/src/android/gradle.js.map +1 -0
- package/dist/src/android/manifest.d.ts +57 -0
- package/dist/src/android/manifest.js +183 -0
- package/dist/src/android/manifest.js.map +1 -0
- package/dist/src/android/templates.d.ts +11 -0
- package/dist/src/android/templates.js +34 -0
- package/dist/src/android/templates.js.map +1 -0
- package/dist/src/apple/apple-wizard.js +123 -64
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/cocoapod.js +4 -3
- package/dist/src/apple/cocoapod.js.map +1 -1
- package/dist/src/apple/code-tools.d.ts +1 -1
- package/dist/src/apple/code-tools.js +43 -19
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/fastlane.d.ts +1 -1
- package/dist/src/apple/fastlane.js +12 -6
- package/dist/src/apple/fastlane.js.map +1 -1
- package/dist/src/apple/templates.d.ts +2 -2
- package/dist/src/apple/templates.js +4 -4
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +19 -3
- package/dist/src/apple/xcode-manager.js +126 -24
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +49 -11
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.d.ts +2 -0
- package/dist/src/nextjs/templates.js +6 -2
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/remix/remix-wizard.js +10 -20
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +26 -13
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.js +19 -16
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.d.ts +2 -1
- package/dist/src/sourcemaps/tools/vite.js +123 -111
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sourcemaps/tools/webpack.d.ts +6 -1
- package/dist/src/sourcemaps/tools/webpack.js +290 -25
- package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +5 -5
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +34 -44
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/telemetry.js +1 -0
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +9 -5
- package/dist/src/utils/ast-utils.js +26 -11
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +74 -28
- package/dist/src/utils/clack-utils.js +427 -264
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-manager.d.ts +10 -0
- package/dist/{lib/Helper/PackageManager.js → src/utils/package-manager.js} +42 -74
- package/dist/src/utils/package-manager.js.map +1 -0
- package/dist/src/utils/release-registry.d.ts +1 -0
- package/dist/src/utils/release-registry.js +68 -0
- package/dist/src/utils/release-registry.js.map +1 -0
- package/dist/src/utils/sentrycli-utils.d.ts +4 -0
- package/dist/src/utils/sentrycli-utils.js +41 -0
- package/dist/src/utils/sentrycli-utils.js.map +1 -0
- package/dist/test/android/code-tools.test.d.ts +1 -0
- package/dist/test/android/code-tools.test.js +34 -0
- package/dist/test/android/code-tools.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/vite.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/vite.test.js +132 -0
- package/dist/test/sourcemaps/tools/vite.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.js +179 -0
- package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -0
- package/dist/test/utils/ast-utils.test.js +42 -7
- package/dist/test/utils/ast-utils.test.js.map +1 -1
- package/dist/test/utils/clack-utils.test.d.ts +1 -0
- package/dist/test/utils/clack-utils.test.js +200 -0
- package/dist/test/utils/clack-utils.test.js.map +1 -0
- package/lib/Constants.ts +5 -0
- package/lib/Steps/ChooseIntegration.ts +7 -3
- package/lib/Steps/Integrations/Android.ts +23 -0
- package/lib/Steps/Integrations/ReactNative.ts +9 -3
- package/lib/Steps/PromptForParameters.ts +48 -3
- package/lib/Steps/SentryProjectSelector.ts +3 -1
- package/package.json +4 -3
- package/src/android/android-wizard.ts +204 -0
- package/src/android/code-tools.ts +170 -0
- package/src/android/gradle.ts +250 -0
- package/src/android/manifest.ts +180 -0
- package/src/android/templates.ts +88 -0
- package/src/apple/apple-wizard.ts +113 -35
- package/src/apple/cocoapod.ts +6 -3
- package/src/apple/code-tools.ts +46 -18
- package/src/apple/fastlane.ts +6 -12
- package/src/apple/templates.ts +2 -8
- package/src/apple/xcode-manager.ts +167 -25
- package/src/nextjs/nextjs-wizard.ts +72 -8
- package/src/nextjs/templates.ts +16 -2
- package/src/remix/remix-wizard.ts +10 -15
- package/src/sourcemaps/sourcemaps-wizard.ts +19 -5
- package/src/sourcemaps/tools/nextjs.ts +2 -2
- package/src/sourcemaps/tools/sentry-cli.ts +8 -7
- package/src/sourcemaps/tools/vite.ts +143 -79
- package/src/sourcemaps/tools/webpack.ts +369 -30
- package/src/sourcemaps/utils/detect-tool.ts +2 -1
- package/src/sveltekit/sdk-setup.ts +10 -6
- package/src/sveltekit/sveltekit-wizard.ts +5 -14
- package/src/telemetry.ts +2 -0
- package/src/utils/ast-utils.ts +29 -11
- package/src/utils/clack-utils.ts +485 -283
- package/src/utils/package-manager.ts +61 -0
- package/src/utils/release-registry.ts +19 -0
- package/src/utils/sentrycli-utils.ts +22 -0
- package/test/android/code-tools.test.ts +49 -0
- package/test/sourcemaps/tools/vite.test.ts +149 -0
- package/test/sourcemaps/tools/webpack.test.ts +303 -0
- package/test/utils/ast-utils.test.ts +28 -9
- package/test/utils/clack-utils.test.ts +142 -0
- package/dist/lib/Helper/PackageManager.d.ts +0 -22
- package/dist/lib/Helper/PackageManager.js.map +0 -1
- package/dist/src/utils/vendor/clack-custom-select.d.ts +0 -21
- package/dist/src/utils/vendor/clack-custom-select.js +0 -137
- package/dist/src/utils/vendor/clack-custom-select.js.map +0 -1
- package/lib/Helper/PackageManager.ts +0 -59
- package/src/utils/vendor/clack-custom-select.ts +0 -160
|
@@ -2,17 +2,30 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
5
|
-
|
|
5
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
6
|
+
import clack from '@clack/prompts';
|
|
6
7
|
import * as fs from 'fs';
|
|
7
8
|
import { SentryProjectData } from '../utils/types';
|
|
8
9
|
import * as templates from './templates';
|
|
10
|
+
import * as path from 'path';
|
|
9
11
|
const xcode = require('xcode');
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
interface ProjetFile {
|
|
14
|
+
key: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}
|
|
12
17
|
|
|
13
|
-
function setDebugInformationFormat(proj: any): void {
|
|
18
|
+
function setDebugInformationFormat(proj: any, targetName: string): void {
|
|
14
19
|
const xcObjects = proj.hash.project.objects;
|
|
15
|
-
const
|
|
20
|
+
const targetKey: string = Object.keys(xcObjects.PBXNativeTarget || {}).filter(
|
|
21
|
+
(key) => {
|
|
22
|
+
return (
|
|
23
|
+
!key.endsWith('_comment') &&
|
|
24
|
+
xcObjects.PBXNativeTarget[key].name === targetName
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
)[0];
|
|
28
|
+
const target = xcObjects.PBXNativeTarget[targetKey];
|
|
16
29
|
|
|
17
30
|
xcObjects.XCConfigurationList[
|
|
18
31
|
target.buildConfigurationList
|
|
@@ -23,7 +36,7 @@ function setDebugInformationFormat(proj: any): void {
|
|
|
23
36
|
});
|
|
24
37
|
}
|
|
25
38
|
|
|
26
|
-
function addSentrySPM(proj: any): void {
|
|
39
|
+
function addSentrySPM(proj: any, targetName: string): void {
|
|
27
40
|
const xcObjects = proj.hash.project.objects;
|
|
28
41
|
|
|
29
42
|
const sentryFrameworkUUID = proj.generateUuid() as string;
|
|
@@ -61,7 +74,16 @@ function addSentrySPM(proj: any): void {
|
|
|
61
74
|
}
|
|
62
75
|
}
|
|
63
76
|
|
|
64
|
-
const
|
|
77
|
+
const targetKey: string = Object.keys(xcObjects.PBXNativeTarget || {}).filter(
|
|
78
|
+
(key) => {
|
|
79
|
+
return (
|
|
80
|
+
!key.endsWith('_comment') &&
|
|
81
|
+
xcObjects.PBXNativeTarget[key].name === targetName
|
|
82
|
+
);
|
|
83
|
+
},
|
|
84
|
+
)[0];
|
|
85
|
+
const target = xcObjects.PBXNativeTarget[targetKey];
|
|
86
|
+
|
|
65
87
|
if (!target.packageProductDependencies) {
|
|
66
88
|
target.packageProductDependencies = [];
|
|
67
89
|
}
|
|
@@ -106,15 +128,25 @@ function addSentrySPM(proj: any): void {
|
|
|
106
128
|
};
|
|
107
129
|
xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID + '_comment'] =
|
|
108
130
|
'Sentry';
|
|
131
|
+
|
|
132
|
+
clack.log.step('Added Sentry SPM dependency to your project');
|
|
109
133
|
}
|
|
110
134
|
|
|
111
135
|
function addUploadSymbolsScript(
|
|
112
136
|
xcodeProject: any,
|
|
113
137
|
sentryProject: SentryProjectData,
|
|
114
|
-
|
|
138
|
+
targetName: string,
|
|
115
139
|
uploadSource = true,
|
|
116
140
|
): void {
|
|
117
141
|
const xcObjects = xcodeProject.hash.project.objects;
|
|
142
|
+
const targetKey: string = Object.keys(xcObjects.PBXNativeTarget || {}).filter(
|
|
143
|
+
(key) => {
|
|
144
|
+
return (
|
|
145
|
+
!key.endsWith('_comment') &&
|
|
146
|
+
xcObjects.PBXNativeTarget[key].name === targetName
|
|
147
|
+
);
|
|
148
|
+
},
|
|
149
|
+
)[0];
|
|
118
150
|
|
|
119
151
|
for (const scriptKey in xcObjects.PBXShellScriptBuildPhase || {}) {
|
|
120
152
|
if (!scriptKey.endsWith('_comment')) {
|
|
@@ -132,7 +164,7 @@ function addUploadSymbolsScript(
|
|
|
132
164
|
[],
|
|
133
165
|
'PBXShellScriptBuildPhase',
|
|
134
166
|
'Upload Debug Symbols to Sentry',
|
|
135
|
-
|
|
167
|
+
targetKey,
|
|
136
168
|
{
|
|
137
169
|
inputFileListPaths: [],
|
|
138
170
|
outputFileListPaths: [],
|
|
@@ -141,29 +173,139 @@ function addUploadSymbolsScript(
|
|
|
141
173
|
shellScript: templates.getRunScriptTemplate(
|
|
142
174
|
sentryProject.organization.slug,
|
|
143
175
|
sentryProject.slug,
|
|
144
|
-
apiKeys.token,
|
|
145
176
|
uploadSource,
|
|
146
177
|
),
|
|
147
178
|
},
|
|
148
179
|
);
|
|
180
|
+
clack.log.step(`Added Sentry upload script to "${targetName}" build phase`);
|
|
149
181
|
}
|
|
150
182
|
|
|
151
|
-
export
|
|
152
|
-
projectPath: string
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
183
|
+
export class XcodeProject {
|
|
184
|
+
projectPath: string;
|
|
185
|
+
project: any;
|
|
186
|
+
objects: any;
|
|
187
|
+
files: ProjetFile[] | undefined;
|
|
188
|
+
|
|
189
|
+
public constructor(projectPath: string) {
|
|
190
|
+
this.projectPath = projectPath;
|
|
191
|
+
this.project = xcode.project(projectPath);
|
|
192
|
+
this.project.parseSync();
|
|
193
|
+
this.objects = this.project.hash.project.objects;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public getAllTargets(): string[] {
|
|
197
|
+
return Object.keys(this.objects.PBXNativeTarget || {})
|
|
198
|
+
.filter((key) => {
|
|
199
|
+
return (
|
|
200
|
+
!key.endsWith('_comment') &&
|
|
201
|
+
this.objects.PBXNativeTarget[key].productType.startsWith(
|
|
202
|
+
'"com.apple.product-type.application',
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
})
|
|
206
|
+
.map((key) => {
|
|
207
|
+
return this.objects.PBXNativeTarget[key].name as string;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public updateXcodeProject(
|
|
212
|
+
sentryProject: SentryProjectData,
|
|
213
|
+
target: string,
|
|
214
|
+
apiKeys: { token: string },
|
|
215
|
+
addSPMReference: boolean,
|
|
216
|
+
uploadSource = true,
|
|
217
|
+
): void {
|
|
218
|
+
addUploadSymbolsScript(this.project, sentryProject, target, uploadSource);
|
|
219
|
+
if (uploadSource) {
|
|
220
|
+
setDebugInformationFormat(this.project, target);
|
|
221
|
+
}
|
|
222
|
+
if (addSPMReference) {
|
|
223
|
+
addSentrySPM(this.project, target);
|
|
224
|
+
}
|
|
225
|
+
const newContent = this.project.writeSync();
|
|
226
|
+
fs.writeFileSync(this.projectPath, newContent);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public filesForTarget(target: string): string[] | undefined {
|
|
230
|
+
const files = this.projectFiles();
|
|
231
|
+
const fileDictionary: any = {};
|
|
232
|
+
files.forEach((file) => {
|
|
233
|
+
fileDictionary[file.key] = file.path;
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const nativeTarget = Object.keys(this.objects.PBXNativeTarget || {}).filter(
|
|
237
|
+
(key) => {
|
|
238
|
+
return (
|
|
239
|
+
!key.endsWith('_comment') &&
|
|
240
|
+
this.objects.PBXNativeTarget[key].name === target
|
|
241
|
+
);
|
|
242
|
+
},
|
|
243
|
+
)[0];
|
|
244
|
+
|
|
245
|
+
if (nativeTarget === undefined) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const buildPhaseKey = this.objects.PBXNativeTarget[
|
|
250
|
+
nativeTarget
|
|
251
|
+
].buildPhases.filter((phase: any) => {
|
|
252
|
+
return this.objects.PBXSourcesBuildPhase[phase.value] !== undefined;
|
|
253
|
+
})[0];
|
|
254
|
+
|
|
255
|
+
if (buildPhaseKey === undefined) {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const buildPhases = this.objects.PBXSourcesBuildPhase[buildPhaseKey.value];
|
|
260
|
+
if (buildPhases === undefined) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const baseDir = path.dirname(path.dirname(this.projectPath));
|
|
265
|
+
|
|
266
|
+
return buildPhases.files
|
|
267
|
+
.map((file: any) => {
|
|
268
|
+
const buildFile = fileDictionary[
|
|
269
|
+
this.objects.PBXBuildFile[file.value].fileRef
|
|
270
|
+
] as string;
|
|
271
|
+
if (!buildFile) {
|
|
272
|
+
return '';
|
|
273
|
+
}
|
|
274
|
+
return path.join(baseDir, buildFile);
|
|
275
|
+
})
|
|
276
|
+
.filter((f: string) => f.length > 0) as string[];
|
|
163
277
|
}
|
|
164
|
-
|
|
165
|
-
|
|
278
|
+
|
|
279
|
+
projectFiles(): ProjetFile[] {
|
|
280
|
+
if (this.files === undefined) {
|
|
281
|
+
const proj = this.project.getFirstProject();
|
|
282
|
+
const mainGroupKey = proj.firstProject.mainGroup;
|
|
283
|
+
const mainGroup = this.objects.PBXGroup[mainGroupKey];
|
|
284
|
+
this.files = this.buildGroup(mainGroup);
|
|
285
|
+
}
|
|
286
|
+
return this.files;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
buildGroup(group: any, path = ''): ProjetFile[] {
|
|
290
|
+
const result: ProjetFile[] = [];
|
|
291
|
+
for (const child of group.children) {
|
|
292
|
+
if (this.objects.PBXFileReference[child.value]) {
|
|
293
|
+
const fileReference = this.objects.PBXFileReference[child.value];
|
|
294
|
+
result.push({
|
|
295
|
+
key: child.value,
|
|
296
|
+
path: `${path}${fileReference.path.replace(/"/g, '')}`,
|
|
297
|
+
});
|
|
298
|
+
} else if (this.objects.PBXGroup[child.value]) {
|
|
299
|
+
const groupReference = this.objects.PBXGroup[child.value];
|
|
300
|
+
const groupChildren = this.buildGroup(
|
|
301
|
+
groupReference,
|
|
302
|
+
groupReference.path
|
|
303
|
+
? `${path}${groupReference.path.replace(/"/g, '')}/`
|
|
304
|
+
: path,
|
|
305
|
+
);
|
|
306
|
+
result.push(...groupChildren);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
166
310
|
}
|
|
167
|
-
const newContent = proj.writeSync();
|
|
168
|
-
fs.writeFileSync(projectPath, newContent);
|
|
169
311
|
}
|
|
@@ -10,7 +10,7 @@ import * as path from 'path';
|
|
|
10
10
|
import {
|
|
11
11
|
abort,
|
|
12
12
|
abortIfCancelled,
|
|
13
|
-
|
|
13
|
+
addSentryCliConfig,
|
|
14
14
|
confirmContinueEvenThoughNoGitRepo,
|
|
15
15
|
ensurePackageIsInstalled,
|
|
16
16
|
getOrAskForProjectData,
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
getNextjsWebpackPluginOptionsTemplate,
|
|
29
29
|
getSentryConfigContents,
|
|
30
30
|
getSentryExampleApiRoute,
|
|
31
|
+
getSentryExampleAppDirApiRoute,
|
|
31
32
|
getSentryExamplePageContents,
|
|
32
33
|
} from './templates';
|
|
33
34
|
|
|
@@ -44,7 +45,7 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
44
45
|
await ensurePackageIsInstalled(packageJson, 'next', 'Next.js');
|
|
45
46
|
|
|
46
47
|
const { selectedProject, authToken, selfHosted, sentryUrl } =
|
|
47
|
-
await getOrAskForProjectData(options);
|
|
48
|
+
await getOrAskForProjectData(options, 'javascript-nextjs');
|
|
48
49
|
|
|
49
50
|
await installPackage({
|
|
50
51
|
packageName: '@sentry/nextjs',
|
|
@@ -279,8 +280,11 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
|
|
283
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
282
284
|
const maybePagesDirPath = path.join(process.cwd(), 'pages');
|
|
283
|
-
const maybeSrcPagesDirPath = path.join(
|
|
285
|
+
const maybeSrcPagesDirPath = path.join(srcDir, 'pages');
|
|
286
|
+
const maybeAppDirPath = path.join(process.cwd(), 'app');
|
|
287
|
+
const maybeSrcAppDirPath = path.join(srcDir, 'app');
|
|
284
288
|
|
|
285
289
|
let pagesLocation =
|
|
286
290
|
fs.existsSync(maybePagesDirPath) &&
|
|
@@ -291,23 +295,83 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
291
295
|
? ['src', 'pages']
|
|
292
296
|
: undefined;
|
|
293
297
|
|
|
294
|
-
|
|
295
|
-
|
|
298
|
+
const appLocation =
|
|
299
|
+
fs.existsSync(maybeAppDirPath) &&
|
|
300
|
+
fs.lstatSync(maybeAppDirPath).isDirectory()
|
|
301
|
+
? ['app']
|
|
302
|
+
: fs.existsSync(maybeSrcAppDirPath) &&
|
|
303
|
+
fs.lstatSync(maybeSrcAppDirPath).isDirectory()
|
|
304
|
+
? ['src', 'app']
|
|
305
|
+
: undefined;
|
|
306
|
+
|
|
307
|
+
if (!pagesLocation && !appLocation) {
|
|
308
|
+
pagesLocation =
|
|
309
|
+
fs.existsSync(srcDir) && fs.lstatSync(srcDir).isDirectory()
|
|
310
|
+
? ['src', 'pages']
|
|
311
|
+
: ['pages'];
|
|
296
312
|
fs.mkdirSync(path.join(process.cwd(), ...pagesLocation), {
|
|
297
313
|
recursive: true,
|
|
298
314
|
});
|
|
299
315
|
}
|
|
300
316
|
|
|
301
|
-
if (
|
|
317
|
+
if (appLocation) {
|
|
318
|
+
const examplePageContents = getSentryExamplePageContents({
|
|
319
|
+
selfHosted,
|
|
320
|
+
orgSlug: selectedProject.organization.slug,
|
|
321
|
+
projectId: selectedProject.id,
|
|
322
|
+
url: sentryUrl,
|
|
323
|
+
useClient: true,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
await fs.promises.writeFile(
|
|
327
|
+
path.join(
|
|
328
|
+
process.cwd(),
|
|
329
|
+
...appLocation,
|
|
330
|
+
'sentry-example-page',
|
|
331
|
+
'page.jsx',
|
|
332
|
+
),
|
|
333
|
+
examplePageContents,
|
|
334
|
+
{ encoding: 'utf8', flag: 'w' },
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
clack.log.success(
|
|
338
|
+
`Created ${chalk.bold(
|
|
339
|
+
path.join(...appLocation, 'sentry-example-page', 'page.jsx'),
|
|
340
|
+
)}.`,
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
fs.mkdirSync(path.join(process.cwd(), ...appLocation, 'api'), {
|
|
344
|
+
recursive: true,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
await fs.promises.writeFile(
|
|
348
|
+
path.join(
|
|
349
|
+
process.cwd(),
|
|
350
|
+
...appLocation,
|
|
351
|
+
'api',
|
|
352
|
+
'sentry-example-api',
|
|
353
|
+
'route.js',
|
|
354
|
+
),
|
|
355
|
+
getSentryExampleAppDirApiRoute(),
|
|
356
|
+
{ encoding: 'utf8', flag: 'w' },
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
clack.log.success(
|
|
360
|
+
`Created ${chalk.bold(
|
|
361
|
+
path.join(...appLocation, 'api', 'sentry-example-api', 'route.js'),
|
|
362
|
+
)}.`,
|
|
363
|
+
);
|
|
364
|
+
} else if (pagesLocation) {
|
|
302
365
|
const examplePageContents = getSentryExamplePageContents({
|
|
303
366
|
selfHosted,
|
|
304
367
|
orgSlug: selectedProject.organization.slug,
|
|
305
368
|
projectId: selectedProject.id,
|
|
306
369
|
url: sentryUrl,
|
|
370
|
+
useClient: false,
|
|
307
371
|
});
|
|
308
372
|
|
|
309
373
|
await fs.promises.writeFile(
|
|
310
|
-
path.join(process.cwd(), ...pagesLocation, 'sentry-example-page.
|
|
374
|
+
path.join(process.cwd(), ...pagesLocation, 'sentry-example-page.jsx'),
|
|
311
375
|
examplePageContents,
|
|
312
376
|
{ encoding: 'utf8', flag: 'w' },
|
|
313
377
|
);
|
|
@@ -340,7 +404,7 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
340
404
|
);
|
|
341
405
|
}
|
|
342
406
|
|
|
343
|
-
await
|
|
407
|
+
await addSentryCliConfig(authToken);
|
|
344
408
|
|
|
345
409
|
const mightBeUsingVercel = fs.existsSync(
|
|
346
410
|
path.join(process.cwd(), 'vercel.json'),
|
package/src/nextjs/templates.ts
CHANGED
|
@@ -150,15 +150,18 @@ export function getSentryExamplePageContents(options: {
|
|
|
150
150
|
url: string;
|
|
151
151
|
orgSlug: string;
|
|
152
152
|
projectId: string;
|
|
153
|
+
useClient: boolean;
|
|
153
154
|
}): string {
|
|
154
155
|
const issuesPageLink = options.selfHosted
|
|
155
156
|
? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`
|
|
156
157
|
: `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;
|
|
157
158
|
|
|
158
|
-
return
|
|
159
|
+
return `${
|
|
160
|
+
options.useClient ? '"use client";\n\n' : ''
|
|
161
|
+
}import Head from "next/head";
|
|
159
162
|
import * as Sentry from "@sentry/nextjs";
|
|
160
163
|
|
|
161
|
-
export default function
|
|
164
|
+
export default function Page() {
|
|
162
165
|
return (
|
|
163
166
|
<div>
|
|
164
167
|
<Head>
|
|
@@ -250,3 +253,14 @@ export default function handler(_req, res) {
|
|
|
250
253
|
}
|
|
251
254
|
`;
|
|
252
255
|
}
|
|
256
|
+
|
|
257
|
+
export function getSentryExampleAppDirApiRoute() {
|
|
258
|
+
return `import { NextResponse } from "next/server";
|
|
259
|
+
|
|
260
|
+
// A faulty API route to test Sentry's error monitoring
|
|
261
|
+
export function GET() {
|
|
262
|
+
throw new Error("Sentry Example API Route Error");
|
|
263
|
+
return NextResponse.json({ data: "Testing Sentry Error..." });
|
|
264
|
+
}
|
|
265
|
+
`;
|
|
266
|
+
}
|
|
@@ -3,16 +3,15 @@ import clack from '@clack/prompts';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
askForProjectSelection,
|
|
8
|
-
askForSelfHosted,
|
|
9
|
-
askForWizardLogin,
|
|
6
|
+
addSentryCliConfig,
|
|
10
7
|
confirmContinueEvenThoughNoGitRepo,
|
|
11
8
|
ensurePackageIsInstalled,
|
|
9
|
+
getOrAskForProjectData,
|
|
12
10
|
getPackageDotJson,
|
|
13
11
|
installPackage,
|
|
14
12
|
isUsingTypeScript,
|
|
15
13
|
printWelcome,
|
|
14
|
+
sourceMapsCliSetupConfig,
|
|
16
15
|
} from '../utils/clack-utils';
|
|
17
16
|
import { hasPackageInstalled } from '../utils/package-json';
|
|
18
17
|
import { WizardOptions } from '../utils/types';
|
|
@@ -54,15 +53,10 @@ async function runRemixWizardWithTelemetry(
|
|
|
54
53
|
// We expect `@remix-run/dev` to be installed for every Remix project
|
|
55
54
|
await ensurePackageIsInstalled(packageJson, '@remix-run/dev', 'Remix');
|
|
56
55
|
|
|
57
|
-
const {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
url: sentryUrl,
|
|
62
|
-
platform: 'javascript-remix',
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const selectedProject = await askForProjectSelection(projects);
|
|
56
|
+
const { selectedProject, authToken } = await getOrAskForProjectData(
|
|
57
|
+
options,
|
|
58
|
+
'javascript-remix',
|
|
59
|
+
);
|
|
66
60
|
|
|
67
61
|
await traceStep('Install Sentry SDK', () =>
|
|
68
62
|
installPackage({
|
|
@@ -76,8 +70,9 @@ async function runRemixWizardWithTelemetry(
|
|
|
76
70
|
const isTS = isUsingTypeScript();
|
|
77
71
|
const isV2 = isRemixV2(remixConfig, packageJson);
|
|
78
72
|
|
|
79
|
-
await
|
|
80
|
-
|
|
73
|
+
await addSentryCliConfig(
|
|
74
|
+
authToken,
|
|
75
|
+
sourceMapsCliSetupConfig,
|
|
81
76
|
selectedProject.organization.slug,
|
|
82
77
|
selectedProject.name,
|
|
83
78
|
);
|
|
@@ -4,9 +4,9 @@ import chalk from 'chalk';
|
|
|
4
4
|
import * as Sentry from '@sentry/node';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
abort,
|
|
7
8
|
abortIfCancelled,
|
|
8
9
|
confirmContinueEvenThoughNoGitRepo,
|
|
9
|
-
detectPackageManager,
|
|
10
10
|
SENTRY_DOT_ENV_FILE,
|
|
11
11
|
printWelcome,
|
|
12
12
|
SENTRY_CLI_RC_FILE,
|
|
@@ -30,6 +30,7 @@ import { configureAngularSourcemapGenerationFlow } from './tools/angular';
|
|
|
30
30
|
import { detectUsedTool, SupportedTools } from './utils/detect-tool';
|
|
31
31
|
import { configureNextJsSourceMapsUpload } from './tools/nextjs';
|
|
32
32
|
import { configureRemixSourceMapsUpload } from './tools/remix';
|
|
33
|
+
import { detectPackageManger } from '../utils/package-manager';
|
|
33
34
|
|
|
34
35
|
export async function runSourcemapsWizard(
|
|
35
36
|
options: WizardOptions,
|
|
@@ -89,6 +90,14 @@ You can turn this off by running the wizard with the '--disable-telemetry' flag.
|
|
|
89
90
|
|
|
90
91
|
Sentry.setTag('selected-tool', selectedTool);
|
|
91
92
|
|
|
93
|
+
if (selectedTool === 'no-tool') {
|
|
94
|
+
clack.log.info(
|
|
95
|
+
"No Problem! But in this case, there's nothing to configure :)",
|
|
96
|
+
);
|
|
97
|
+
await abort('Exiting, have a great day!', 0);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
await traceStep('tool-setup', () =>
|
|
93
102
|
startToolSetupFlow(
|
|
94
103
|
selectedTool,
|
|
@@ -115,7 +124,7 @@ You can turn this off by running the wizard with the '--disable-telemetry' flag.
|
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
async function askForUsedBundlerTool(): Promise<SupportedTools> {
|
|
118
|
-
const selectedTool
|
|
127
|
+
const selectedTool = await abortIfCancelled(
|
|
119
128
|
clack.select({
|
|
120
129
|
message: 'Which framework, bundler or build tool are you using?',
|
|
121
130
|
options: [
|
|
@@ -165,10 +174,15 @@ async function askForUsedBundlerTool(): Promise<SupportedTools> {
|
|
|
165
174
|
hint: 'Configure source maps when using tsc as build tool',
|
|
166
175
|
},
|
|
167
176
|
{
|
|
168
|
-
label: '
|
|
177
|
+
label: 'I use another tool',
|
|
169
178
|
value: 'sentry-cli',
|
|
170
179
|
hint: 'This will configure source maps upload for you using sentry-cli',
|
|
171
180
|
},
|
|
181
|
+
{
|
|
182
|
+
label: "I don't minify, transpile or bundle my code",
|
|
183
|
+
value: 'no-tool',
|
|
184
|
+
hint: 'This will exit the wizard',
|
|
185
|
+
},
|
|
172
186
|
],
|
|
173
187
|
initialValue: await detectUsedTool(),
|
|
174
188
|
}),
|
|
@@ -317,8 +331,8 @@ SENTRY_AUTH_TOKEN=${authToken}
|
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
function printOutro(url: string, orgSlug: string, projectId: string) {
|
|
320
|
-
const
|
|
321
|
-
const buildCommand =
|
|
334
|
+
const packageManager = detectPackageManger();
|
|
335
|
+
const buildCommand = packageManager?.buildCommand ?? 'npm run build';
|
|
322
336
|
|
|
323
337
|
const urlObject = new URL(url);
|
|
324
338
|
urlObject.host = `${orgSlug}.${urlObject.host}`;
|
|
@@ -3,7 +3,7 @@ import * as clack from '@clack/prompts';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { runNextjsWizard } from '../../nextjs/nextjs-wizard';
|
|
5
5
|
import { traceStep } from '../../telemetry';
|
|
6
|
-
import { abortIfCancelled,
|
|
6
|
+
import { abortIfCancelled, addSentryCliConfig } from '../../utils/clack-utils';
|
|
7
7
|
import { WizardOptions } from '../../utils/types';
|
|
8
8
|
|
|
9
9
|
import { SourceMapUploadToolConfigurationOptions } from './types';
|
|
@@ -99,7 +99,7 @@ In case you already tried the wizard, we can also show you how to configure your
|
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
await traceStep('nextjs-manual-sentryclirc', () =>
|
|
102
|
-
|
|
102
|
+
addSentryCliConfig(options.authToken),
|
|
103
103
|
);
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -6,8 +6,7 @@ import * as path from 'path';
|
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import {
|
|
8
8
|
abortIfCancelled,
|
|
9
|
-
|
|
10
|
-
detectPackageManager,
|
|
9
|
+
addSentryCliConfig,
|
|
11
10
|
getPackageDotJson,
|
|
12
11
|
installPackage,
|
|
13
12
|
} from '../../utils/clack-utils';
|
|
@@ -15,6 +14,7 @@ import {
|
|
|
15
14
|
import { SourceMapUploadToolConfigurationOptions } from './types';
|
|
16
15
|
import { hasPackageInstalled, PackageDotJson } from '../../utils/package-json';
|
|
17
16
|
import { traceStep } from '../../telemetry';
|
|
17
|
+
import { detectPackageManger } from '../../utils/package-manager';
|
|
18
18
|
|
|
19
19
|
const SENTRY_NPM_SCRIPT_NAME = 'sentry:sourcemaps';
|
|
20
20
|
|
|
@@ -96,7 +96,7 @@ export async function configureSentryCLI(
|
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
await
|
|
99
|
+
await addSentryCliConfig(options.authToken);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export async function setupNpmScriptInCI(): Promise<void> {
|
|
@@ -205,7 +205,8 @@ async function addSentryCommandToBuildCommand(
|
|
|
205
205
|
(s) => s !== SENTRY_NPM_SCRIPT_NAME,
|
|
206
206
|
);
|
|
207
207
|
|
|
208
|
-
const
|
|
208
|
+
const packageManager = detectPackageManger();
|
|
209
|
+
const packageManagerName = packageManager?.name ?? 'npm';
|
|
209
210
|
|
|
210
211
|
// Heuristic to pre-select the build command:
|
|
211
212
|
// Often, 'build' is the prod build command, so we favour it.
|
|
@@ -220,7 +221,7 @@ async function addSentryCommandToBuildCommand(
|
|
|
220
221
|
(await abortIfCancelled(
|
|
221
222
|
clack.confirm({
|
|
222
223
|
message: `Is ${chalk.cyan(
|
|
223
|
-
`${
|
|
224
|
+
`${packageManagerName} run ${buildCommand}`,
|
|
224
225
|
)} your production build command?`,
|
|
225
226
|
}),
|
|
226
227
|
));
|
|
@@ -228,7 +229,7 @@ async function addSentryCommandToBuildCommand(
|
|
|
228
229
|
if (allNpmScripts.length && (!buildCommand || !isProdBuildCommand)) {
|
|
229
230
|
buildCommand = await abortIfCancelled(
|
|
230
231
|
clack.select({
|
|
231
|
-
message: `Which ${
|
|
232
|
+
message: `Which ${packageManagerName} command in your ${chalk.cyan(
|
|
232
233
|
'package.json',
|
|
233
234
|
)} builds your application for production?`,
|
|
234
235
|
options: allNpmScripts
|
|
@@ -254,7 +255,7 @@ Please add it manually to your prod build command.`,
|
|
|
254
255
|
packageDotJson.scripts[
|
|
255
256
|
buildCommand
|
|
256
257
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
257
|
-
] = `${packageDotJson.scripts[buildCommand]} && ${
|
|
258
|
+
] = `${packageDotJson.scripts[buildCommand]} && ${packageManager} run ${SENTRY_NPM_SCRIPT_NAME}`;
|
|
258
259
|
|
|
259
260
|
await fs.promises.writeFile(
|
|
260
261
|
path.join(process.cwd(), 'package.json'),
|