@sentry/wizard 3.5.0 → 3.7.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 +15 -0
- package/bin.ts +1 -34
- package/dist/bin.js +1 -28
- package/dist/bin.js.map +1 -1
- package/dist/lib/Constants.d.ts +2 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Helper/Wizard.js +2 -0
- package/dist/lib/Helper/Wizard.js.map +1 -1
- package/dist/lib/Helper/__tests__/SentryCli.js +1 -0
- package/dist/lib/Helper/__tests__/SentryCli.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +4 -0
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Apple.d.ts +10 -0
- package/dist/lib/Steps/Integrations/Apple.js +92 -0
- package/dist/lib/Steps/Integrations/Apple.js.map +1 -0
- package/dist/lib/Steps/Integrations/NextJsShim.js +1 -0
- package/dist/lib/Steps/Integrations/NextJsShim.js.map +1 -1
- package/dist/lib/Steps/Integrations/SourceMapsShim.d.ts +1 -1
- package/dist/lib/Steps/Integrations/SourceMapsShim.js +2 -1
- package/dist/lib/Steps/Integrations/SourceMapsShim.js.map +1 -1
- package/dist/lib/Steps/Integrations/SvelteKitShim.js +1 -0
- package/dist/lib/Steps/Integrations/SvelteKitShim.js.map +1 -1
- package/dist/package.json +2 -2
- package/dist/src/apple/apple-wizard.d.ts +2 -0
- package/dist/src/apple/apple-wizard.js +197 -0
- package/dist/src/apple/apple-wizard.js.map +1 -0
- package/dist/src/apple/code-tools.d.ts +1 -0
- package/dist/src/apple/code-tools.js +100 -0
- package/dist/src/apple/code-tools.js.map +1 -0
- package/dist/src/apple/templates.d.ts +4 -0
- package/dist/src/apple/templates.js +19 -0
- package/dist/src/apple/templates.js.map +1 -0
- package/dist/src/apple/xcode-manager.d.ts +4 -0
- package/dist/src/apple/xcode-manager.js +145 -0
- package/dist/src/apple/xcode-manager.js.map +1 -0
- package/dist/src/nextjs/nextjs-wizard.js +4 -10
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +193 -71
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sourcemaps/tools/angular.d.ts +1 -0
- package/dist/src/sourcemaps/tools/angular.js +76 -0
- package/dist/src/sourcemaps/tools/angular.js.map +1 -0
- package/dist/src/sourcemaps/tools/esbuild.js +2 -1
- package/dist/src/sourcemaps/tools/esbuild.js.map +1 -1
- package/dist/src/sourcemaps/tools/rollup.js +2 -1
- package/dist/src/sourcemaps/tools/rollup.js.map +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.d.ts +1 -0
- package/dist/src/sourcemaps/tools/sentry-cli.js +52 -24
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +2 -1
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sourcemaps/tools/webpack.js +2 -1
- package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.d.ts +3 -0
- package/dist/src/sourcemaps/utils/detect-tool.js +73 -0
- package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -0
- package/dist/src/sourcemaps/utils/other-wizards.d.ts +4 -0
- package/dist/src/sourcemaps/utils/other-wizards.js +183 -0
- package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -0
- package/dist/src/sourcemaps/utils/sdk-version.js +14 -13
- package/dist/src/sourcemaps/utils/sdk-version.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +5 -3
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +2 -1
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/sveltekit/templates.js +1 -1
- package/dist/src/sveltekit/templates.js.map +1 -1
- package/dist/src/telemetry.d.ts +1 -0
- package/dist/src/telemetry.js +7 -1
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/utils/bash.d.ts +3 -0
- package/dist/src/utils/bash.js +118 -0
- package/dist/src/utils/bash.js.map +1 -0
- package/dist/src/utils/clack-utils.d.ts +12 -8
- package/dist/src/utils/clack-utils.js +83 -40
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-json.d.ts +19 -0
- package/dist/src/utils/package-json.js +29 -0
- package/dist/src/utils/package-json.js.map +1 -0
- package/dist/src/utils/types.d.ts +4 -0
- package/dist/src/utils/types.js.map +1 -1
- package/lib/Constants.ts +6 -0
- package/lib/Helper/Wizard.ts +3 -0
- package/lib/Helper/__tests__/SentryCli.ts +2 -1
- package/lib/Steps/ChooseIntegration.ts +4 -0
- package/lib/Steps/Integrations/Apple.ts +27 -0
- package/lib/Steps/Integrations/NextJsShim.ts +1 -0
- package/lib/Steps/Integrations/SourceMapsShim.ts +2 -1
- package/lib/Steps/Integrations/SvelteKitShim.ts +1 -0
- package/package-lock.json +8910 -0
- package/package.json +2 -2
- package/src/apple/apple-wizard.ts +150 -0
- package/src/apple/code-tools.ts +81 -0
- package/src/apple/templates.ts +39 -0
- package/src/apple/xcode-manager.ts +147 -0
- package/src/nextjs/nextjs-wizard.ts +6 -10
- package/src/sourcemaps/sourcemaps-wizard.ts +211 -92
- package/src/sourcemaps/tools/angular.ts +42 -0
- package/src/sourcemaps/tools/esbuild.ts +1 -1
- package/src/sourcemaps/tools/rollup.ts +2 -4
- package/src/sourcemaps/tools/sentry-cli.ts +45 -27
- package/src/sourcemaps/tools/vite.ts +1 -1
- package/src/sourcemaps/tools/webpack.ts +1 -1
- package/src/sourcemaps/utils/detect-tool.ts +41 -0
- package/src/sourcemaps/utils/other-wizards.ts +148 -0
- package/src/sourcemaps/utils/sdk-version.ts +9 -16
- package/src/sveltekit/sdk-setup.ts +5 -2
- package/src/sveltekit/sveltekit-wizard.ts +1 -1
- package/src/sveltekit/templates.ts +1 -1
- package/src/telemetry.ts +8 -0
- package/src/utils/bash.ts +44 -0
- package/src/utils/clack-utils.ts +82 -51
- package/src/utils/package-json.ts +45 -0
- package/src/utils/types.ts +5 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
2
|
+
import clack from '@clack/prompts';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { runNextjsWizard } from '../../nextjs/nextjs-wizard';
|
|
5
|
+
import { runSvelteKitWizard } from '../../sveltekit/sveltekit-wizard';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
abort,
|
|
9
|
+
abortIfCancelled,
|
|
10
|
+
getPackageDotJson,
|
|
11
|
+
} from '../../utils/clack-utils';
|
|
12
|
+
import {
|
|
13
|
+
findInstalledPackageFromList,
|
|
14
|
+
hasPackageInstalled,
|
|
15
|
+
} from '../../utils/package-json';
|
|
16
|
+
|
|
17
|
+
import * as Sentry from '@sentry/node';
|
|
18
|
+
import { WizardOptions } from '../../utils/types';
|
|
19
|
+
|
|
20
|
+
type WizardFunction = (options: WizardOptions) => Promise<void>;
|
|
21
|
+
|
|
22
|
+
type FrameworkInfo = {
|
|
23
|
+
frameworkName: string;
|
|
24
|
+
frameworkSlug: string;
|
|
25
|
+
frameworkPackage: string;
|
|
26
|
+
sourcemapsDocsLink: string;
|
|
27
|
+
wizard: WizardFunction;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const sdkMap: Record<string, FrameworkInfo> = {
|
|
31
|
+
'@sentry/nextjs': {
|
|
32
|
+
frameworkName: 'Next.js',
|
|
33
|
+
frameworkSlug: 'nextjs',
|
|
34
|
+
frameworkPackage: 'next',
|
|
35
|
+
sourcemapsDocsLink:
|
|
36
|
+
'https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-source-maps',
|
|
37
|
+
wizard: runNextjsWizard,
|
|
38
|
+
},
|
|
39
|
+
'@sentry/sveltekit': {
|
|
40
|
+
frameworkName: 'SvelteKit',
|
|
41
|
+
frameworkSlug: 'sveltekit',
|
|
42
|
+
frameworkPackage: '@sveltejs/kit',
|
|
43
|
+
sourcemapsDocsLink:
|
|
44
|
+
'https://docs.sentry.io/platforms/javascript/guides/sveltekit/manual-setup/#configure-source-maps-upload',
|
|
45
|
+
wizard: runSvelteKitWizard,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export async function checkIfMoreSuitableWizardExistsAndAskForRedirect(): Promise<
|
|
50
|
+
WizardFunction | undefined
|
|
51
|
+
> {
|
|
52
|
+
const sdkName = await checkIfMoreSuitableWizardExists();
|
|
53
|
+
|
|
54
|
+
if (!sdkName) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return await askForRedirect(sdkName);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function checkIfMoreSuitableWizardExists(): Promise<string | undefined> {
|
|
62
|
+
Sentry.setTag('using-wrong-wizard', false);
|
|
63
|
+
|
|
64
|
+
const packageJson = await getPackageDotJson();
|
|
65
|
+
|
|
66
|
+
const installedSdkPackage = findInstalledPackageFromList(
|
|
67
|
+
Object.keys(sdkMap),
|
|
68
|
+
packageJson,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (!installedSdkPackage) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const sdkPackageName = installedSdkPackage.name;
|
|
76
|
+
|
|
77
|
+
const { frameworkPackage } = sdkMap[sdkPackageName];
|
|
78
|
+
|
|
79
|
+
if (!hasPackageInstalled(frameworkPackage, packageJson)) {
|
|
80
|
+
// The user has installed the SDK but not the framework.
|
|
81
|
+
// Maybe it's a false positive and the user is using a different framework.
|
|
82
|
+
// Let's not redirect them to the framework wizard in that case.
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Sentry.setTag('using-wrong-wizard', true);
|
|
87
|
+
|
|
88
|
+
return sdkPackageName;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function askForRedirect(
|
|
92
|
+
sdkName: string,
|
|
93
|
+
): Promise<WizardFunction | undefined> {
|
|
94
|
+
const { frameworkName, sourcemapsDocsLink, frameworkSlug, wizard } =
|
|
95
|
+
sdkMap[sdkName];
|
|
96
|
+
|
|
97
|
+
clack.log.warn(
|
|
98
|
+
`${chalk.yellow(
|
|
99
|
+
`It seems like you're using this wizard in a ${frameworkName} project.`,
|
|
100
|
+
)}
|
|
101
|
+
|
|
102
|
+
We recommend using our dedicated ${frameworkName} wizard instead of this wizard.
|
|
103
|
+
The ${frameworkName} wizard will set up our ${sdkName} SDK and also configure uploading source maps for you.
|
|
104
|
+
|
|
105
|
+
If you already tried the ${frameworkName} wizard and it didn't work for you, check out the following guides:
|
|
106
|
+
|
|
107
|
+
Manual source maps configuration for ${frameworkName}:
|
|
108
|
+
${sourcemapsDocsLink}
|
|
109
|
+
|
|
110
|
+
Troubleshooting Source Maps:
|
|
111
|
+
https://docs.sentry.io/platforms/javascript/guides/${frameworkSlug}/sourcemaps/troubleshooting_js/
|
|
112
|
+
`,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const nextStep: 'redirect' | 'continue' | 'stop' = await abortIfCancelled(
|
|
116
|
+
clack.select({
|
|
117
|
+
message: `Do you want to run the ${frameworkName} wizard now?`,
|
|
118
|
+
options: [
|
|
119
|
+
{
|
|
120
|
+
label: 'Yes',
|
|
121
|
+
value: 'redirect',
|
|
122
|
+
hint: `${chalk.green('Recommended')}`,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
label: 'No, continue with this wizard',
|
|
126
|
+
value: 'continue',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
label: "No, I'll check out the guides ",
|
|
130
|
+
value: 'stop',
|
|
131
|
+
hint: 'Exit this wizard',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
}),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
Sentry.setTag('wrong-wizard-decision', nextStep);
|
|
138
|
+
|
|
139
|
+
switch (nextStep) {
|
|
140
|
+
case 'redirect':
|
|
141
|
+
return wizard;
|
|
142
|
+
case 'stop':
|
|
143
|
+
await abort('Exiting Wizard', 0);
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -5,11 +5,11 @@ import { minVersion, satisfies } from 'semver';
|
|
|
5
5
|
import {
|
|
6
6
|
abortIfCancelled,
|
|
7
7
|
getPackageDotJson,
|
|
8
|
-
getPackageVersion,
|
|
9
8
|
installPackage,
|
|
10
9
|
} from '../../utils/clack-utils';
|
|
11
10
|
|
|
12
11
|
import * as Sentry from '@sentry/node';
|
|
12
|
+
import { findInstalledPackageFromList } from '../../utils/package-json';
|
|
13
13
|
|
|
14
14
|
const MINIMUM_DEBUG_ID_SDK_VERSION = '7.47.0';
|
|
15
15
|
|
|
@@ -36,12 +36,7 @@ const SENTRY_SDK_PACKAGE_NAMES = [
|
|
|
36
36
|
// Base SDKs
|
|
37
37
|
'@sentry/browser',
|
|
38
38
|
'@sentry/node',
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
type SdkPackage = {
|
|
42
|
-
name: (typeof SENTRY_SDK_PACKAGE_NAMES)[number];
|
|
43
|
-
version: string;
|
|
44
|
-
};
|
|
39
|
+
];
|
|
45
40
|
|
|
46
41
|
/**
|
|
47
42
|
* Check for a minimum SDK version and prompt the user to upgrade if necessary.
|
|
@@ -57,15 +52,10 @@ type SdkPackage = {
|
|
|
57
52
|
* -> We tell users to manually upgrade (migrate between majors)
|
|
58
53
|
*/
|
|
59
54
|
export async function ensureMinimumSdkVersionIsInstalled(): Promise<void> {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
version: getPackageVersion(packageName, packageJson),
|
|
65
|
-
})).filter((sdkPackage): sdkPackage is SdkPackage => !!sdkPackage.version);
|
|
66
|
-
|
|
67
|
-
const installedSdkPackage =
|
|
68
|
-
installedSdkPackages.length > 0 && installedSdkPackages[0];
|
|
55
|
+
const installedSdkPackage = findInstalledPackageFromList(
|
|
56
|
+
SENTRY_SDK_PACKAGE_NAMES,
|
|
57
|
+
await getPackageDotJson(),
|
|
58
|
+
);
|
|
69
59
|
|
|
70
60
|
// Case 1:
|
|
71
61
|
if (!installedSdkPackage) {
|
|
@@ -75,6 +65,8 @@ export async function ensureMinimumSdkVersionIsInstalled(): Promise<void> {
|
|
|
75
65
|
const { name: installedSdkName, version: installedSdkVersionOrRange } =
|
|
76
66
|
installedSdkPackage;
|
|
77
67
|
|
|
68
|
+
Sentry.setTag('installed-sdk', installedSdkName);
|
|
69
|
+
|
|
78
70
|
const minInstalledVersion = getMinInstalledVersion(
|
|
79
71
|
installedSdkVersionOrRange,
|
|
80
72
|
installedSdkName,
|
|
@@ -198,6 +190,7 @@ async function handleAutoUpdateSdk(packageName: string) {
|
|
|
198
190
|
|
|
199
191
|
async function handleNoSdkInstalled(): Promise<void> {
|
|
200
192
|
Sentry.setTag('initial-sdk-version', 'none');
|
|
193
|
+
Sentry.setTag('installed-sdk', 'none');
|
|
201
194
|
|
|
202
195
|
clack.log.warn(
|
|
203
196
|
`${chalk.yellowBright(
|
|
@@ -13,6 +13,7 @@ import { builders, generateCode, loadFile, parseModule } from 'magicast';
|
|
|
13
13
|
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
14
14
|
import { addVitePlugin } from 'magicast/helpers';
|
|
15
15
|
import { getClientHooksTemplate, getServerHooksTemplate } from './templates';
|
|
16
|
+
import { isUsingTypeScript } from '../utils/clack-utils';
|
|
16
17
|
|
|
17
18
|
const SVELTE_CONFIG_FILE = 'svelte.config.js';
|
|
18
19
|
|
|
@@ -40,13 +41,15 @@ export async function createOrMergeSvelteKitFiles(
|
|
|
40
41
|
|
|
41
42
|
const viteConfig = findHooksFile(path.resolve(process.cwd(), 'vite.config'));
|
|
42
43
|
|
|
44
|
+
const fileEnding = isUsingTypeScript() ? 'ts' : 'js';
|
|
45
|
+
|
|
43
46
|
if (!originalClientHooksFile) {
|
|
44
47
|
clack.log.info('No client hooks file found, creating a new one.');
|
|
45
|
-
await createNewHooksFile(`${clientHooksPath}
|
|
48
|
+
await createNewHooksFile(`${clientHooksPath}.${fileEnding}`, 'client', dsn);
|
|
46
49
|
}
|
|
47
50
|
if (!originalServerHooksFile) {
|
|
48
51
|
clack.log.info('No server hooks file found, creating a new one.');
|
|
49
|
-
await createNewHooksFile(`${serverHooksPath}
|
|
52
|
+
await createNewHooksFile(`${serverHooksPath}.${fileEnding}`, 'server', dsn);
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
if (originalClientHooksFile) {
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
confirmContinueEvenThoughNoGitRepo,
|
|
10
10
|
ensurePackageIsInstalled,
|
|
11
11
|
getPackageDotJson,
|
|
12
|
-
hasPackageInstalled,
|
|
13
12
|
installPackage,
|
|
14
13
|
printWelcome,
|
|
15
14
|
} from '../utils/clack-utils';
|
|
15
|
+
import { hasPackageInstalled } from '../utils/package-json';
|
|
16
16
|
import { WizardOptions } from '../utils/types';
|
|
17
17
|
import { createExamplePage } from './sdk-example';
|
|
18
18
|
import { createOrMergeSvelteKitFiles, loadSvelteConfig } from './sdk-setup';
|
package/src/telemetry.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
makeNodeTransport,
|
|
7
7
|
NodeClient,
|
|
8
8
|
runWithAsyncContext,
|
|
9
|
+
trace,
|
|
9
10
|
} from '@sentry/node';
|
|
10
11
|
import packageJson from '../package.json';
|
|
11
12
|
|
|
@@ -26,6 +27,7 @@ export async function withTelemetry<F>(
|
|
|
26
27
|
const transaction = sentryHub.startTransaction({
|
|
27
28
|
name: 'sentry-wizard-execution',
|
|
28
29
|
status: 'ok',
|
|
30
|
+
op: 'wizard.flow',
|
|
29
31
|
});
|
|
30
32
|
sentryHub.getScope().setSpan(transaction);
|
|
31
33
|
const sentrySession = sentryHub.startSession();
|
|
@@ -74,6 +76,8 @@ function createSentryInstance(enabled: boolean, integration: string) {
|
|
|
74
76
|
},
|
|
75
77
|
|
|
76
78
|
transport: makeNodeTransport,
|
|
79
|
+
|
|
80
|
+
debug: true,
|
|
77
81
|
});
|
|
78
82
|
|
|
79
83
|
const hub = new Hub(client);
|
|
@@ -84,3 +88,7 @@ function createSentryInstance(enabled: boolean, integration: string) {
|
|
|
84
88
|
|
|
85
89
|
return { sentryHub: hub, sentryClient: client };
|
|
86
90
|
}
|
|
91
|
+
|
|
92
|
+
export function traceStep<T>(step: string, callback: () => T): T {
|
|
93
|
+
return trace({ name: step, op: 'wizard.step' }, () => callback());
|
|
94
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as child_process from 'child_process';
|
|
2
|
+
import * as https from 'https';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
|
|
5
|
+
export function hasSentryCLI(): boolean {
|
|
6
|
+
try {
|
|
7
|
+
child_process.execSync('sentry-cli --version');
|
|
8
|
+
return true;
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function installSentryCLI(): Promise<void> {
|
|
15
|
+
const httpAsync = new Promise((resolve, reject) => {
|
|
16
|
+
const file = fs.createWriteStream('installcli.sh');
|
|
17
|
+
https.get('https://sentry.io/get-cli/', (response) => {
|
|
18
|
+
response.pipe(file);
|
|
19
|
+
file.on('finish', () => {
|
|
20
|
+
file.close();
|
|
21
|
+
try {
|
|
22
|
+
child_process.execSync('bash ./installcli.sh');
|
|
23
|
+
} catch (e) {
|
|
24
|
+
reject(e);
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
fs.unlinkSync('installcli.sh');
|
|
28
|
+
resolve(null);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
file.on('error', (err) => {
|
|
32
|
+
fs.unlinkSync('installcli.sh');
|
|
33
|
+
reject(err);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
await httpAsync;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function execute(command: string): string {
|
|
42
|
+
const output = child_process.execSync(command);
|
|
43
|
+
return output.toString();
|
|
44
|
+
}
|
package/src/utils/clack-utils.ts
CHANGED
|
@@ -10,11 +10,15 @@ import { URL } from 'url';
|
|
|
10
10
|
import { promisify } from 'util';
|
|
11
11
|
import * as Sentry from '@sentry/node';
|
|
12
12
|
import { windowedSelect } from './vendor/clack-custom-select';
|
|
13
|
+
import { hasPackageInstalled, PackageDotJson } from './package-json';
|
|
13
14
|
|
|
14
15
|
const opn = require('opn') as (
|
|
15
16
|
url: string,
|
|
16
17
|
) => Promise<childProcess.ChildProcess>;
|
|
17
18
|
|
|
19
|
+
export const SENTRY_DOT_ENV_FILE = '.env.sentry-build-plugin';
|
|
20
|
+
export const SENTRY_CLI_RC_FILE = '.sentryclirc';
|
|
21
|
+
|
|
18
22
|
const SAAS_URL = 'https://sentry.io/';
|
|
19
23
|
|
|
20
24
|
interface WizardProjectData {
|
|
@@ -24,16 +28,11 @@ interface WizardProjectData {
|
|
|
24
28
|
projects: SentryProjectData[];
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
export type PackageDotJson = {
|
|
28
|
-
scripts?: Record<string, string>;
|
|
29
|
-
dependencies?: Record<string, string>;
|
|
30
|
-
devDependencies?: Record<string, string>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
31
|
export interface SentryProjectData {
|
|
34
32
|
id: string;
|
|
35
33
|
slug: string;
|
|
36
34
|
name: string;
|
|
35
|
+
platform: string;
|
|
37
36
|
organization: {
|
|
38
37
|
slug: string;
|
|
39
38
|
};
|
|
@@ -130,10 +129,19 @@ export async function confirmContinueEvenThoughNoGitRepo(): Promise<void> {
|
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
132
|
+
export async function askToInstallSentryCLI(): Promise<boolean> {
|
|
133
|
+
return await abortIfCancelled(
|
|
134
|
+
clack.confirm({
|
|
135
|
+
message:
|
|
136
|
+
"You don't have Sentry CLI installed. Do you want to install it?",
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
export async function askForWizardLogin(options: {
|
|
134
142
|
url: string;
|
|
135
143
|
promoCode?: string;
|
|
136
|
-
platform?: 'javascript-nextjs' | 'javascript-sveltekit';
|
|
144
|
+
platform?: 'javascript-nextjs' | 'javascript-sveltekit' | 'apple-ios';
|
|
137
145
|
}): Promise<WizardProjectData> {
|
|
138
146
|
Sentry.setTag('has-promo-code', !!options.promoCode);
|
|
139
147
|
|
|
@@ -234,6 +242,27 @@ export async function askForWizardLogin(options: {
|
|
|
234
242
|
return data;
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
export async function askForItemSelection(
|
|
246
|
+
items: string[],
|
|
247
|
+
message: string,
|
|
248
|
+
): Promise<{ value: string; index: number }> {
|
|
249
|
+
const selection: { value: string; index: number } | symbol =
|
|
250
|
+
await abortIfCancelled(
|
|
251
|
+
windowedSelect({
|
|
252
|
+
maxItems: 12,
|
|
253
|
+
message: message,
|
|
254
|
+
options: items.map((item, index) => {
|
|
255
|
+
return {
|
|
256
|
+
value: { value: item, index: index },
|
|
257
|
+
label: item,
|
|
258
|
+
};
|
|
259
|
+
}),
|
|
260
|
+
}),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
return selection;
|
|
264
|
+
}
|
|
265
|
+
|
|
237
266
|
export async function askForProjectSelection(
|
|
238
267
|
projects: SentryProjectData[],
|
|
239
268
|
): Promise<SentryProjectData> {
|
|
@@ -251,6 +280,7 @@ export async function askForProjectSelection(
|
|
|
251
280
|
);
|
|
252
281
|
|
|
253
282
|
Sentry.setTag('project', selection.slug);
|
|
283
|
+
Sentry.setTag('project-platform', selection.platform);
|
|
254
284
|
Sentry.setUser({ id: selection.organization.slug });
|
|
255
285
|
|
|
256
286
|
return selection;
|
|
@@ -390,10 +420,12 @@ export async function askForSelfHosted(urlFromArgs?: string): Promise<{
|
|
|
390
420
|
}
|
|
391
421
|
|
|
392
422
|
export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
393
|
-
const clircExists = fs.existsSync(
|
|
423
|
+
const clircExists = fs.existsSync(
|
|
424
|
+
path.join(process.cwd(), SENTRY_CLI_RC_FILE),
|
|
425
|
+
);
|
|
394
426
|
if (clircExists) {
|
|
395
427
|
const clircContents = fs.readFileSync(
|
|
396
|
-
path.join(process.cwd(),
|
|
428
|
+
path.join(process.cwd(), SENTRY_CLI_RC_FILE),
|
|
397
429
|
'utf8',
|
|
398
430
|
);
|
|
399
431
|
|
|
@@ -404,25 +436,25 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
404
436
|
if (likelyAlreadyHasAuthToken) {
|
|
405
437
|
clack.log.warn(
|
|
406
438
|
`${chalk.bold(
|
|
407
|
-
|
|
439
|
+
SENTRY_CLI_RC_FILE,
|
|
408
440
|
)} already has auth token. Will not add one.`,
|
|
409
441
|
);
|
|
410
442
|
} else {
|
|
411
443
|
try {
|
|
412
444
|
await fs.promises.writeFile(
|
|
413
|
-
path.join(process.cwd(),
|
|
445
|
+
path.join(process.cwd(), SENTRY_CLI_RC_FILE),
|
|
414
446
|
`${clircContents}\n[auth]\ntoken=${authToken}\n`,
|
|
415
447
|
{ encoding: 'utf8', flag: 'w' },
|
|
416
448
|
);
|
|
417
449
|
clack.log.success(
|
|
418
450
|
`Added auth token to ${chalk.bold(
|
|
419
|
-
|
|
451
|
+
SENTRY_CLI_RC_FILE,
|
|
420
452
|
)} for you to test uploading source maps locally.`,
|
|
421
453
|
);
|
|
422
454
|
} catch {
|
|
423
455
|
clack.log.warning(
|
|
424
456
|
`Failed to add auth token to ${chalk.bold(
|
|
425
|
-
|
|
457
|
+
SENTRY_CLI_RC_FILE,
|
|
426
458
|
)}. Uploading source maps during build will likely not work locally.`,
|
|
427
459
|
);
|
|
428
460
|
}
|
|
@@ -430,32 +462,30 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
430
462
|
} else {
|
|
431
463
|
try {
|
|
432
464
|
await fs.promises.writeFile(
|
|
433
|
-
path.join(process.cwd(),
|
|
465
|
+
path.join(process.cwd(), SENTRY_CLI_RC_FILE),
|
|
434
466
|
`[auth]\ntoken=${authToken}\n`,
|
|
435
467
|
{ encoding: 'utf8', flag: 'w' },
|
|
436
468
|
);
|
|
437
469
|
clack.log.success(
|
|
438
470
|
`Created ${chalk.bold(
|
|
439
|
-
|
|
471
|
+
SENTRY_CLI_RC_FILE,
|
|
440
472
|
)} with auth token for you to test uploading source maps locally.`,
|
|
441
473
|
);
|
|
442
474
|
} catch {
|
|
443
475
|
clack.log.warning(
|
|
444
476
|
`Failed to create ${chalk.bold(
|
|
445
|
-
|
|
477
|
+
SENTRY_CLI_RC_FILE,
|
|
446
478
|
)} with auth token. Uploading source maps during build will likely not work locally.`,
|
|
447
479
|
);
|
|
448
480
|
}
|
|
449
481
|
}
|
|
450
482
|
|
|
451
|
-
await addAuthTokenFileToGitIgnore(
|
|
483
|
+
await addAuthTokenFileToGitIgnore(SENTRY_CLI_RC_FILE);
|
|
452
484
|
}
|
|
453
485
|
|
|
454
486
|
export async function addDotEnvSentryBuildPluginFile(
|
|
455
487
|
authToken: string,
|
|
456
488
|
): Promise<void> {
|
|
457
|
-
const DOT_ENV_FILE = '.env.sentry-build-plugin';
|
|
458
|
-
|
|
459
489
|
const envVarContent = `# DO NOT commit this file to your repository!
|
|
460
490
|
# The SENTRY_AUTH_TOKEN variable is picked up by the Sentry Build Plugin.
|
|
461
491
|
# It's used for authentication when uploading source maps.
|
|
@@ -463,7 +493,7 @@ export async function addDotEnvSentryBuildPluginFile(
|
|
|
463
493
|
SENTRY_AUTH_TOKEN="${authToken}"
|
|
464
494
|
`;
|
|
465
495
|
|
|
466
|
-
const dotEnvFilePath = path.join(process.cwd(),
|
|
496
|
+
const dotEnvFilePath = path.join(process.cwd(), SENTRY_DOT_ENV_FILE);
|
|
467
497
|
const dotEnvFileExists = fs.existsSync(dotEnvFilePath);
|
|
468
498
|
|
|
469
499
|
if (dotEnvFileExists) {
|
|
@@ -475,7 +505,9 @@ SENTRY_AUTH_TOKEN="${authToken}"
|
|
|
475
505
|
|
|
476
506
|
if (hasAuthToken) {
|
|
477
507
|
clack.log.warn(
|
|
478
|
-
`${chalk.bold(
|
|
508
|
+
`${chalk.bold(
|
|
509
|
+
SENTRY_DOT_ENV_FILE,
|
|
510
|
+
)} already has auth token. Will not add one.`,
|
|
479
511
|
);
|
|
480
512
|
} else {
|
|
481
513
|
try {
|
|
@@ -487,11 +519,13 @@ SENTRY_AUTH_TOKEN="${authToken}"
|
|
|
487
519
|
flag: 'w',
|
|
488
520
|
},
|
|
489
521
|
);
|
|
490
|
-
clack.log.success(
|
|
522
|
+
clack.log.success(
|
|
523
|
+
`Added auth token to ${chalk.bold(SENTRY_DOT_ENV_FILE)}`,
|
|
524
|
+
);
|
|
491
525
|
} catch {
|
|
492
526
|
clack.log.warning(
|
|
493
527
|
`Failed to add auth token to ${chalk.bold(
|
|
494
|
-
|
|
528
|
+
SENTRY_DOT_ENV_FILE,
|
|
495
529
|
)}. Uploading source maps during build will likely not work locally.`,
|
|
496
530
|
);
|
|
497
531
|
}
|
|
@@ -504,19 +538,19 @@ SENTRY_AUTH_TOKEN="${authToken}"
|
|
|
504
538
|
});
|
|
505
539
|
clack.log.success(
|
|
506
540
|
`Created ${chalk.bold(
|
|
507
|
-
|
|
541
|
+
SENTRY_DOT_ENV_FILE,
|
|
508
542
|
)} with auth token for you to test source map uploading locally.`,
|
|
509
543
|
);
|
|
510
544
|
} catch {
|
|
511
545
|
clack.log.warning(
|
|
512
546
|
`Failed to create ${chalk.bold(
|
|
513
|
-
|
|
547
|
+
SENTRY_DOT_ENV_FILE,
|
|
514
548
|
)} with auth token. Uploading source maps during build will likely not work locally.`,
|
|
515
549
|
);
|
|
516
550
|
}
|
|
517
551
|
}
|
|
518
552
|
|
|
519
|
-
await addAuthTokenFileToGitIgnore(
|
|
553
|
+
await addAuthTokenFileToGitIgnore(SENTRY_DOT_ENV_FILE);
|
|
520
554
|
}
|
|
521
555
|
|
|
522
556
|
async function addAuthTokenFileToGitIgnore(filename: string): Promise<void> {
|
|
@@ -584,32 +618,8 @@ export async function getPackageDotJson(): Promise<PackageDotJson> {
|
|
|
584
618
|
return packageJson || {};
|
|
585
619
|
}
|
|
586
620
|
|
|
587
|
-
export function hasPackageInstalled(
|
|
588
|
-
packageName: string,
|
|
589
|
-
packageJson: PackageDotJson,
|
|
590
|
-
): boolean {
|
|
591
|
-
return getPackageVersion(packageName, packageJson) !== undefined;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
export function getPackageVersion(
|
|
595
|
-
packageName: string,
|
|
596
|
-
packageJson: PackageDotJson,
|
|
597
|
-
): string | undefined {
|
|
598
|
-
return (
|
|
599
|
-
packageJson?.dependencies?.[packageName] ||
|
|
600
|
-
packageJson?.devDependencies?.[packageName]
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
621
|
async function getPackageManager(): Promise<string> {
|
|
605
|
-
|
|
606
|
-
if (fs.existsSync(path.join(process.cwd(), 'yarn.lock'))) {
|
|
607
|
-
detectedPackageManager = 'yarn';
|
|
608
|
-
} else if (fs.existsSync(path.join(process.cwd(), 'package-lock.json'))) {
|
|
609
|
-
detectedPackageManager = 'npm';
|
|
610
|
-
} else if (fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml'))) {
|
|
611
|
-
detectedPackageManager = 'pnpm';
|
|
612
|
-
}
|
|
622
|
+
const detectedPackageManager = detectPackageManager();
|
|
613
623
|
|
|
614
624
|
if (detectedPackageManager) {
|
|
615
625
|
return detectedPackageManager;
|
|
@@ -630,3 +640,24 @@ async function getPackageManager(): Promise<string> {
|
|
|
630
640
|
|
|
631
641
|
return selectedPackageManager;
|
|
632
642
|
}
|
|
643
|
+
|
|
644
|
+
export function detectPackageManager(): 'yarn' | 'npm' | 'pnpm' | undefined {
|
|
645
|
+
if (fs.existsSync(path.join(process.cwd(), 'yarn.lock'))) {
|
|
646
|
+
return 'yarn';
|
|
647
|
+
}
|
|
648
|
+
if (fs.existsSync(path.join(process.cwd(), 'package-lock.json'))) {
|
|
649
|
+
return 'npm';
|
|
650
|
+
}
|
|
651
|
+
if (fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml'))) {
|
|
652
|
+
return 'pnpm';
|
|
653
|
+
}
|
|
654
|
+
return undefined;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export function isUsingTypeScript() {
|
|
658
|
+
try {
|
|
659
|
+
return fs.existsSync(path.join(process.cwd(), 'tsconfig.json'));
|
|
660
|
+
} catch {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type PackageDotJson = {
|
|
2
|
+
scripts?: Record<string, string>;
|
|
3
|
+
dependencies?: Record<string, string>;
|
|
4
|
+
devDependencies?: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
type NpmPackage = {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if @param packageJson has any of the @param packageNamesList package names
|
|
14
|
+
* listed as a dependency or devDependency.
|
|
15
|
+
* If so, it returns the first package name that is found, including the
|
|
16
|
+
* version (range) specified in the package.json.
|
|
17
|
+
*/
|
|
18
|
+
export function findInstalledPackageFromList(
|
|
19
|
+
packageNamesList: string[],
|
|
20
|
+
packageJson: PackageDotJson,
|
|
21
|
+
): NpmPackage | undefined {
|
|
22
|
+
return packageNamesList
|
|
23
|
+
.map((packageName) => ({
|
|
24
|
+
name: packageName,
|
|
25
|
+
version: getPackageVersion(packageName, packageJson),
|
|
26
|
+
}))
|
|
27
|
+
.find((sdkPackage): sdkPackage is NpmPackage => !!sdkPackage.version);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function hasPackageInstalled(
|
|
31
|
+
packageName: string,
|
|
32
|
+
packageJson: PackageDotJson,
|
|
33
|
+
): boolean {
|
|
34
|
+
return getPackageVersion(packageName, packageJson) !== undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getPackageVersion(
|
|
38
|
+
packageName: string,
|
|
39
|
+
packageJson: PackageDotJson,
|
|
40
|
+
): string | undefined {
|
|
41
|
+
return (
|
|
42
|
+
packageJson?.dependencies?.[packageName] ||
|
|
43
|
+
packageJson?.devDependencies?.[packageName]
|
|
44
|
+
);
|
|
45
|
+
}
|
package/src/utils/types.ts
CHANGED