@sentry/wizard 3.1.0-beta.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -2
- package/bin.ts +5 -1
- package/dist/bin.js +6 -1
- package/dist/bin.js.map +1 -1
- package/dist/lib/Constants.d.ts +2 -1
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Helper/File.js +25 -2
- package/dist/lib/Helper/File.js.map +1 -1
- package/dist/lib/Helper/Git.d.ts +7 -0
- package/dist/lib/Helper/Git.js +94 -0
- package/dist/lib/Helper/Git.js.map +1 -0
- package/dist/lib/Helper/Logging.d.ts +1 -0
- package/dist/lib/Helper/Logging.js +9 -2
- package/dist/lib/Helper/Logging.js.map +1 -1
- package/dist/lib/Helper/MergeConfig.js +24 -1
- package/dist/lib/Helper/MergeConfig.js.map +1 -1
- package/dist/lib/Helper/Package.d.ts +9 -0
- package/dist/lib/Helper/Package.js +39 -2
- package/dist/lib/Helper/Package.js.map +1 -1
- package/dist/lib/Helper/PackageManager.d.ts +1 -1
- package/dist/lib/Helper/PackageManager.js +32 -11
- package/dist/lib/Helper/PackageManager.js.map +1 -1
- package/dist/lib/Helper/SentryCli.d.ts +11 -0
- package/dist/lib/Helper/SentryCli.js +141 -2
- package/dist/lib/Helper/SentryCli.js.map +1 -1
- package/dist/lib/Helper/Wizard.js +24 -1
- package/dist/lib/Helper/Wizard.js.map +1 -1
- package/dist/lib/Helper/__tests__/MergeConfig.js +25 -2
- package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
- package/dist/lib/Setup.js +25 -2
- package/dist/lib/Setup.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +28 -1
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Initial.js +25 -2
- package/dist/lib/Steps/Initial.js.map +1 -1
- package/dist/lib/Steps/Integrations/BaseIntegration.js +24 -1
- package/dist/lib/Steps/Integrations/BaseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Cordova.js +25 -2
- package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
- package/dist/lib/Steps/Integrations/Electron.js +26 -3
- package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
- package/dist/lib/Steps/Integrations/MobileProject.js +24 -1
- package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
- package/dist/lib/Steps/Integrations/NextJs.d.ts +5 -11
- package/dist/lib/Steps/Integrations/NextJs.js +14 -343
- package/dist/lib/Steps/Integrations/NextJs.js.map +1 -1
- package/dist/lib/Steps/Integrations/ReactNative.d.ts +1 -0
- package/dist/lib/Steps/Integrations/ReactNative.js +67 -6
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/Integrations/SvelteKit.d.ts +13 -0
- package/dist/lib/Steps/Integrations/SvelteKit.js +95 -0
- package/dist/lib/Steps/Integrations/SvelteKit.js.map +1 -0
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +28 -5
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
- package/dist/lib/Steps/PromptForParameters.js +24 -1
- package/dist/lib/Steps/PromptForParameters.js.map +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js +25 -1
- package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
- package/dist/lib/__tests__/Setup.js +24 -1
- package/dist/lib/__tests__/Setup.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +326 -0
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -0
- package/dist/src/sveltekit/sdk-example.d.ts +10 -0
- package/dist/src/sveltekit/sdk-example.js +106 -0
- package/dist/src/sveltekit/sdk-example.js.map +1 -0
- package/dist/src/sveltekit/sdk-setup.d.ts +13 -0
- package/dist/src/sveltekit/sdk-setup.js +451 -0
- package/dist/src/sveltekit/sdk-setup.js.map +1 -0
- package/dist/src/sveltekit/sentry-cli-setup.d.ts +2 -0
- package/dist/src/sveltekit/sentry-cli-setup.js +71 -0
- package/dist/src/sveltekit/sentry-cli-setup.js.map +1 -0
- package/dist/src/sveltekit/sveltekit-wizard.d.ts +5 -0
- package/dist/src/sveltekit/sveltekit-wizard.js +147 -0
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -0
- 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/dist/src/templates/sveltekit-templates.d.ts +12 -0
- package/dist/src/templates/sveltekit-templates.js +26 -0
- package/dist/src/templates/sveltekit-templates.js.map +1 -0
- package/dist/src/{clack-utils.d.ts → utils/clack-utils.d.ts} +7 -0
- package/dist/src/{clack-utils.js → utils/clack-utils.js} +127 -42
- package/dist/src/utils/clack-utils.js.map +1 -0
- package/lib/Constants.ts +5 -0
- package/lib/Helper/Git.ts +39 -0
- package/lib/Helper/Logging.ts +4 -0
- package/lib/Helper/Package.ts +17 -0
- package/lib/Helper/PackageManager.ts +4 -9
- package/lib/Helper/SentryCli.ts +74 -0
- package/lib/Steps/ChooseIntegration.ts +4 -0
- package/lib/Steps/Integrations/NextJs.ts +7 -397
- package/lib/Steps/Integrations/ReactNative.ts +49 -3
- package/lib/Steps/Integrations/SvelteKit.ts +29 -0
- package/lib/Steps/SentryProjectSelector.ts +1 -0
- package/package.json +1 -1
- package/src/{nextjs-wizard.ts → nextjs/nextjs-wizard.ts} +45 -273
- package/src/sveltekit/sdk-example.ts +56 -0
- package/src/sveltekit/sdk-setup.ts +430 -0
- package/src/sveltekit/sentry-cli-setup.ts +27 -0
- package/src/sveltekit/sveltekit-wizard.ts +116 -0
- package/src/templates/nextjs-templates.ts +252 -0
- package/src/templates/sveltekit-templates.ts +172 -0
- package/src/{clack-utils.ts → utils/clack-utils.ts} +73 -11
- package/dist/src/clack-utils.js.map +0 -1
- package/dist/src/nextjs-wizard.js +0 -346
- package/dist/src/nextjs-wizard.js.map +0 -1
- /package/dist/src/{nextjs-wizard.d.ts → nextjs/nextjs-wizard.d.ts} +0 -0
|
@@ -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
|
+
// Injected 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 Vercel 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
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
export function getClientHooksTemplate(dsn: string) {
|
|
2
|
+
return `import { handleErrorWithSentry, Replay } from "@sentry/sveltekit";
|
|
3
|
+
import * as Sentry from '@sentry/sveltekit';
|
|
4
|
+
|
|
5
|
+
Sentry.init({
|
|
6
|
+
dsn: '${dsn}',
|
|
7
|
+
tracesSampleRate: 1.0,
|
|
8
|
+
|
|
9
|
+
// This sets the sample rate to be 10%. You may want this to be 100% while
|
|
10
|
+
// in development and sample at a lower rate in production
|
|
11
|
+
replaysSessionSampleRate: 0.1,
|
|
12
|
+
|
|
13
|
+
// If the entire session is not sampled, use the below sample rate to sample
|
|
14
|
+
// sessions when an error occurs.
|
|
15
|
+
replaysOnErrorSampleRate: 1.0,
|
|
16
|
+
|
|
17
|
+
// If you don't want to use Session Replay, just remove the line below:
|
|
18
|
+
integrations: [new Replay()],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// If you have a custom error handler, pass it to \`handleErrorWithSentry\`
|
|
22
|
+
export const handleError = handleErrorWithSentry();
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getServerHooksTemplate(dsn: string) {
|
|
27
|
+
return `import { sequence } from "@sveltejs/kit/hooks";
|
|
28
|
+
import { handleErrorWithSentry, sentryHandle } from "@sentry/sveltekit";
|
|
29
|
+
import * as Sentry from '@sentry/sveltekit';
|
|
30
|
+
|
|
31
|
+
Sentry.init({
|
|
32
|
+
dsn: '${dsn}',
|
|
33
|
+
tracesSampleRate: 1.0,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// If you have custom handlers, make sure to place them after \`sentryHandle()\` in the \`sequence\` function.
|
|
37
|
+
export const handle = sequence(sentryHandle());
|
|
38
|
+
|
|
39
|
+
// If you have a custom error handler, pass it to \`handleErrorWithSentry\`
|
|
40
|
+
export const handleError = handleErrorWithSentry();
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* +page.svelte with Sentry example
|
|
46
|
+
*/
|
|
47
|
+
export function getSentryExampleSveltePage(options: {
|
|
48
|
+
selfHosted: boolean;
|
|
49
|
+
url: string;
|
|
50
|
+
orgSlug: string;
|
|
51
|
+
projectId: string;
|
|
52
|
+
}) {
|
|
53
|
+
const issuesPageLink = options.selfHosted
|
|
54
|
+
? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`
|
|
55
|
+
: `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;
|
|
56
|
+
|
|
57
|
+
return `<!--
|
|
58
|
+
This is just a very simple page with a button to throw an example error.
|
|
59
|
+
Feel free to delete this file and the entire sentry route.
|
|
60
|
+
-->
|
|
61
|
+
|
|
62
|
+
<script>
|
|
63
|
+
import * as Sentry from '@sentry/sveltekit';
|
|
64
|
+
|
|
65
|
+
async function getSentryData() {
|
|
66
|
+
const transaction = Sentry.startTransaction({
|
|
67
|
+
name: 'Example Frontend Transaction'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
Sentry.configureScope((scope) => {
|
|
71
|
+
scope.setSpan(transaction);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const res = await fetch('/test-sentry');
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
throw new Error('Sentry Example Frontend Error');
|
|
78
|
+
}
|
|
79
|
+
} finally {
|
|
80
|
+
transaction.finish();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<div>
|
|
86
|
+
<head>
|
|
87
|
+
<title>Sentry Onboarding</title>
|
|
88
|
+
<meta name="description" content="Test Sentry for your SvelteKit app!" />
|
|
89
|
+
</head>
|
|
90
|
+
|
|
91
|
+
<main>
|
|
92
|
+
<h1>
|
|
93
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 44">
|
|
94
|
+
<path
|
|
95
|
+
fill="currentColor"
|
|
96
|
+
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"
|
|
97
|
+
/>
|
|
98
|
+
</svg>
|
|
99
|
+
</h1>
|
|
100
|
+
<p>
|
|
101
|
+
Get Started with this <strong>simple Example:</strong>
|
|
102
|
+
</p>
|
|
103
|
+
|
|
104
|
+
<p>1. Send us a sample error:</p>
|
|
105
|
+
<button
|
|
106
|
+
type="button"
|
|
107
|
+
on:click={getSentryData}>
|
|
108
|
+
Throw error!
|
|
109
|
+
</button>
|
|
110
|
+
|
|
111
|
+
<p>
|
|
112
|
+
2. Look for the error on the
|
|
113
|
+
<a href="${issuesPageLink}">Issues Page</a>.
|
|
114
|
+
</p>
|
|
115
|
+
<p style="margin-top: 24px;">
|
|
116
|
+
For more information, take a look at the
|
|
117
|
+
<a href="https://docs.sentry.io/platforms/javascript/guides/sveltekit/">
|
|
118
|
+
Sentry SvelteKit Documentation
|
|
119
|
+
</a>
|
|
120
|
+
</p>
|
|
121
|
+
</main>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<style>
|
|
125
|
+
main {
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
align-items: center;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
h1 {
|
|
133
|
+
font-size: 4rem;
|
|
134
|
+
margin: 14px 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
svg {
|
|
138
|
+
height: 1em;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
button {
|
|
142
|
+
padding: 12px;
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
background-color: rgb(54, 45, 89);
|
|
145
|
+
border-radius: 4px;
|
|
146
|
+
border: none;
|
|
147
|
+
color: white;
|
|
148
|
+
font-size: 1em;
|
|
149
|
+
margin: 1em;
|
|
150
|
+
transition: all 0.25s ease-in-out;
|
|
151
|
+
}
|
|
152
|
+
button:hover {
|
|
153
|
+
background-color: #8c5393;
|
|
154
|
+
box-shadow: 4px;
|
|
155
|
+
box-shadow: 0px 0px 15px 2px rgba(140, 83, 147, 0.5);
|
|
156
|
+
}
|
|
157
|
+
button:active {
|
|
158
|
+
background-color: #c73852;
|
|
159
|
+
}
|
|
160
|
+
</style>
|
|
161
|
+
`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function getSentryExampleApiRoute() {
|
|
165
|
+
return `// This is just a very simple API route that throws an example error.
|
|
166
|
+
// Feel free to delete this file and the entire sentry route.
|
|
167
|
+
|
|
168
|
+
export const GET = async () => {
|
|
169
|
+
throw new Error("Sentry Example API Route Error");
|
|
170
|
+
};
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
1
2
|
import * as clack from '@clack/prompts';
|
|
2
3
|
import axios from 'axios';
|
|
3
4
|
import chalk from 'chalk';
|
|
@@ -15,6 +16,11 @@ interface WizardProjectData {
|
|
|
15
16
|
projects: SentryProjectData[];
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
export type PackageDotJson = {
|
|
20
|
+
dependencies?: Record<string, string>;
|
|
21
|
+
devDependencies?: Record<string, string>;
|
|
22
|
+
};
|
|
23
|
+
|
|
18
24
|
export interface SentryProjectData {
|
|
19
25
|
id: string;
|
|
20
26
|
slug: string;
|
|
@@ -35,9 +41,7 @@ export function abortIfCancelled<T>(
|
|
|
35
41
|
): asserts input is Exclude<T, symbol> {
|
|
36
42
|
if (clack.isCancel(input)) {
|
|
37
43
|
clack.cancel('Wizard setup cancelled.');
|
|
38
|
-
|
|
39
|
-
} else {
|
|
40
|
-
return;
|
|
44
|
+
process.exit(0);
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -81,7 +85,7 @@ export async function confirmContinueEvenThoughNoGitRepo(): Promise<void> {
|
|
|
81
85
|
childProcess.execSync('git rev-parse --is-inside-work-tree', {
|
|
82
86
|
stdio: 'ignore',
|
|
83
87
|
});
|
|
84
|
-
} catch
|
|
88
|
+
} catch {
|
|
85
89
|
const continueWithoutGit = await clack.confirm({
|
|
86
90
|
message:
|
|
87
91
|
'You are not inside a git repository. The wizard will create and update files. Do you still want to continue?',
|
|
@@ -110,7 +114,7 @@ export async function askForWizardLogin(options: {
|
|
|
110
114
|
wizardHash = (
|
|
111
115
|
await axios.get<{ hash: string }>(`${options.url}api/0/wizard/`)
|
|
112
116
|
).data.hash;
|
|
113
|
-
} catch
|
|
117
|
+
} catch {
|
|
114
118
|
clack.log.error('Loading Wizard failed.');
|
|
115
119
|
clack.outro(
|
|
116
120
|
chalk.red(
|
|
@@ -148,11 +152,11 @@ export async function askForWizardLogin(options: {
|
|
|
148
152
|
'Waiting for you to click the link above 👆. Take your time.',
|
|
149
153
|
);
|
|
150
154
|
|
|
151
|
-
const data = await new Promise<WizardProjectData>(resolve => {
|
|
155
|
+
const data = await new Promise<WizardProjectData>((resolve) => {
|
|
152
156
|
const pollingInterval = setInterval(() => {
|
|
153
157
|
axios
|
|
154
158
|
.get<WizardProjectData>(`${options.url}api/0/wizard/${wizardHash}/`)
|
|
155
|
-
.then(result => {
|
|
159
|
+
.then((result) => {
|
|
156
160
|
resolve(result.data);
|
|
157
161
|
clearTimeout(timeout);
|
|
158
162
|
clearInterval(pollingInterval);
|
|
@@ -195,7 +199,10 @@ export async function installPackage({
|
|
|
195
199
|
});
|
|
196
200
|
|
|
197
201
|
abortIfCancelled(shouldUpdatePackage);
|
|
198
|
-
|
|
202
|
+
|
|
203
|
+
if (!shouldUpdatePackage) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
const sdkInstallSpinner = clack.spinner();
|
|
@@ -300,7 +307,7 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
300
307
|
{ encoding: 'utf8', flag: 'w' },
|
|
301
308
|
);
|
|
302
309
|
clack.log.success(`Added auth token to ${chalk.bold('.sentryclirc')}`);
|
|
303
|
-
} catch
|
|
310
|
+
} catch {
|
|
304
311
|
clack.log.warning(
|
|
305
312
|
`Failed to add auth token to ${chalk.bold(
|
|
306
313
|
'.sentryclirc',
|
|
@@ -318,7 +325,7 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
318
325
|
clack.log.success(
|
|
319
326
|
`Created ${chalk.bold('.sentryclirc')} with auth token.`,
|
|
320
327
|
);
|
|
321
|
-
} catch
|
|
328
|
+
} catch {
|
|
322
329
|
clack.log.warning(
|
|
323
330
|
`Failed to create ${chalk.bold(
|
|
324
331
|
'.sentryclirc',
|
|
@@ -336,7 +343,7 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
336
343
|
clack.log.success(
|
|
337
344
|
`Added ${chalk.bold('.sentryclirc')} to ${chalk.bold('.gitignore')}.`,
|
|
338
345
|
);
|
|
339
|
-
} catch
|
|
346
|
+
} catch {
|
|
340
347
|
clack.log.error(
|
|
341
348
|
`Failed adding ${chalk.bold('.sentryclirc')} to ${chalk.bold(
|
|
342
349
|
'.gitignore',
|
|
@@ -344,3 +351,58 @@ export async function addSentryCliRc(authToken: string): Promise<void> {
|
|
|
344
351
|
);
|
|
345
352
|
}
|
|
346
353
|
}
|
|
354
|
+
|
|
355
|
+
export async function ensurePackageIsInstalled(
|
|
356
|
+
packageJson: PackageDotJson,
|
|
357
|
+
packageId: string,
|
|
358
|
+
packageName: string,
|
|
359
|
+
) {
|
|
360
|
+
if (!hasPackageInstalled(packageId, packageJson)) {
|
|
361
|
+
const continueWithoutPackage = await clack.confirm({
|
|
362
|
+
message: `${packageName} does not seem to be installed. Do you still want to continue?`,
|
|
363
|
+
initialValue: false,
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
abortIfCancelled(continueWithoutPackage);
|
|
367
|
+
|
|
368
|
+
if (!continueWithoutPackage) {
|
|
369
|
+
abort();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export async function getPackageDotJson(): Promise<PackageDotJson> {
|
|
375
|
+
const packageJsonFileContents = await fs.promises
|
|
376
|
+
.readFile(path.join(process.cwd(), 'package.json'), 'utf8')
|
|
377
|
+
.catch(() => {
|
|
378
|
+
clack.log.error(
|
|
379
|
+
'Could not find package.json. Make sure to run the wizard in the root of your app!',
|
|
380
|
+
);
|
|
381
|
+
abort();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
let packageJson: PackageDotJson | undefined = undefined;
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
388
|
+
packageJson = JSON.parse(packageJsonFileContents);
|
|
389
|
+
} catch {
|
|
390
|
+
clack.log.error(
|
|
391
|
+
'Unable to parse your package.json. Make sure it has a valid format!',
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
abort();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return packageJson || {};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function hasPackageInstalled(
|
|
401
|
+
packageName: string,
|
|
402
|
+
packageJson: PackageDotJson,
|
|
403
|
+
): boolean {
|
|
404
|
+
return (
|
|
405
|
+
!!packageJson?.dependencies?.[packageName] ||
|
|
406
|
+
!!packageJson?.devDependencies?.[packageName]
|
|
407
|
+
);
|
|
408
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"clack-utils.js","sourceRoot":"","sources":["../../src/clack-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as clack from '@clack/prompts';\nimport axios from 'axios';\nimport chalk from 'chalk';\nimport * as childProcess from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { setInterval } from 'timers';\nimport { URL } from 'url';\nimport { promisify } from 'util';\n\ninterface WizardProjectData {\n apiKeys: {\n token: string;\n };\n projects: SentryProjectData[];\n}\n\nexport interface SentryProjectData {\n id: string;\n slug: string;\n name: string;\n organization: {\n slug: string;\n };\n keys: [{ dsn: { public: string } }];\n}\n\nexport function abort(): never {\n clack.outro('Wizard setup cancelled.');\n return process.exit(0);\n}\n\nexport function abortIfCancelled<T>(\n input: T,\n): asserts input is Exclude<T, symbol> {\n if (clack.isCancel(input)) {\n clack.cancel('Wizard setup cancelled.');\n return process.exit(0);\n } else {\n return;\n }\n}\n\nexport function printWelcome(options: {\n wizardName: string;\n promoCode?: string;\n}): void {\n let wizardPackage: { version?: string } = {};\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n wizardPackage = require(path.join(\n path.dirname(require.resolve('@sentry/wizard')),\n '..',\n 'package.json',\n ));\n } catch {\n // We don't need to have this\n }\n\n // eslint-disable-next-line no-console\n console.log('');\n clack.intro(chalk.inverse(` ${options.wizardName} `));\n\n let welcomeText =\n 'This Wizard will help you to set up Sentry for your application.\\nThank you for using Sentry :)';\n\n if (options.promoCode) {\n welcomeText += `\\n\\nUsing promo-code: ${options.promoCode}`;\n }\n\n if (wizardPackage.version) {\n welcomeText += `\\n\\nVersion: ${wizardPackage.version}`;\n }\n\n clack.note(welcomeText);\n}\n\nexport async function confirmContinueEvenThoughNoGitRepo(): Promise<void> {\n try {\n childProcess.execSync('git rev-parse --is-inside-work-tree', {\n stdio: 'ignore',\n });\n } catch (e) {\n const continueWithoutGit = await clack.confirm({\n message:\n 'You are not inside a git repository. The wizard will create and update files. Do you still want to continue?',\n });\n\n abortIfCancelled(continueWithoutGit);\n\n if (!continueWithoutGit) {\n abort();\n }\n }\n}\n\nexport async function askForWizardLogin(options: {\n url: string;\n promoCode?: string;\n}): Promise<WizardProjectData> {\n const hasSentryAccount = await clack.confirm({\n message: 'Do you already have a Sentry account?',\n });\n\n abortIfCancelled(hasSentryAccount);\n\n let wizardHash: string;\n try {\n wizardHash = (\n await axios.get<{ hash: string }>(`${options.url}api/0/wizard/`)\n ).data.hash;\n } catch (e) {\n clack.log.error('Loading Wizard failed.');\n clack.outro(\n chalk.red(\n 'Please try again in a few minutes and let us know if this issue persists: https://github.com/getsentry/sentry-wizard/issues',\n ),\n );\n\n return process.exit(1);\n }\n\n const loginUrl = new URL(\n `${options.url}account/settings/wizard/${wizardHash}/`,\n );\n\n if (!hasSentryAccount) {\n loginUrl.searchParams.set('signup', '1');\n loginUrl.searchParams.set('project_platform', 'javascript-nextjs');\n }\n\n if (options.promoCode) {\n loginUrl.searchParams.set('code', options.promoCode);\n }\n\n clack.log.info(\n `${chalk.bold(\n `Please open the following link in your browser to ${\n hasSentryAccount ? 'log' : 'sign'\n } into Sentry:`,\n )}\\n\\n${chalk.cyan(loginUrl.toString())}`,\n );\n\n const loginSpinner = clack.spinner();\n\n loginSpinner.start(\n 'Waiting for you to click the link above 👆. Take your time.',\n );\n\n const data = await new Promise<WizardProjectData>(resolve => {\n const pollingInterval = setInterval(() => {\n axios\n .get<WizardProjectData>(`${options.url}api/0/wizard/${wizardHash}/`)\n .then(result => {\n resolve(result.data);\n clearTimeout(timeout);\n clearInterval(pollingInterval);\n void axios.delete(`${options.url}api/0/wizard/${wizardHash}/`);\n })\n .catch(() => {\n // noop - just try again\n });\n }, 500);\n\n const timeout = setTimeout(() => {\n clearInterval(pollingInterval);\n loginSpinner.stop(\n 'Login timed out. No worries - it happens to the best of us.',\n );\n clack.outro(\n 'Please restart the Wizard and log in to complete the setup.',\n );\n return process.exit(0);\n }, 180_000);\n });\n\n loginSpinner.stop('Login complete.');\n\n return data;\n}\n\nexport async function installPackage({\n packageName,\n alreadyInstalled,\n}: {\n packageName: string;\n alreadyInstalled: boolean;\n}): Promise<void> {\n if (alreadyInstalled) {\n const shouldUpdatePackage = await clack.confirm({\n message: `The ${chalk.bold.cyan(\n packageName,\n )} package is already installed. Do you want to update it to the latest version?`,\n });\n\n abortIfCancelled(shouldUpdatePackage);\n return;\n }\n\n const sdkInstallSpinner = clack.spinner();\n\n let detectedPackageManager;\n if (fs.existsSync(path.join(process.cwd(), 'yarn.lock'))) {\n detectedPackageManager = 'yarn';\n } else if (fs.existsSync(path.join(process.cwd(), 'package-lock.json'))) {\n detectedPackageManager = 'npm';\n } else if (fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml'))) {\n detectedPackageManager = 'pnpm';\n } else {\n detectedPackageManager = 'npm';\n }\n\n sdkInstallSpinner.start(\n `${alreadyInstalled ? 'Updating' : 'Installing'} ${chalk.bold.cyan(\n packageName,\n )} with ${chalk.bold(detectedPackageManager)}.`,\n );\n\n try {\n if (detectedPackageManager === 'yarn') {\n await promisify(childProcess.exec)(`yarn add ${packageName}@latest`);\n } else if (detectedPackageManager === 'pnpm') {\n await promisify(childProcess.exec)(`pnpm add ${packageName}@latest`);\n } else if (detectedPackageManager === 'npm') {\n await promisify(childProcess.exec)(`npm install ${packageName}@latest`);\n }\n } catch (e) {\n sdkInstallSpinner.stop('Installation failed.');\n clack.log.error(\n `${chalk.red(\n 'Encountered the following error during installation:',\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n )}\\n\\n${e}\\n\\n${chalk.dim(\n 'If you think this issue is caused by the Sentry wizard, let us know here:\\nhttps://github.com/getsentry/sentry-wizard/issues',\n )}`,\n );\n clack.outro('Wizard setup cancelled.');\n return process.exit(1);\n }\n\n sdkInstallSpinner.stop(\n `${alreadyInstalled ? 'Updated' : 'Installed'} ${chalk.bold.cyan(\n packageName,\n )} with ${chalk.bold(detectedPackageManager)}.`,\n );\n}\n\nexport async function askForSelfHosted(): Promise<{\n url: string;\n selfHosted: boolean;\n}> {\n const choice: 'saas' | 'self-hosted' | symbol = await clack.select({\n message: 'Are you using Sentry SaaS or self-hosted Sentry?',\n options: [\n { value: 'saas', label: 'Sentry SaaS (sentry.io)' },\n { value: 'self-hosted', label: 'Self-hosted/on-premise' },\n ],\n });\n\n abortIfCancelled(choice);\n\n if (choice === 'saas') {\n return { url: 'https://sentry.io/', selfHosted: false };\n }\n\n const url = await clack.text({\n message: 'Please enter the URL of your self-hosted Sentry instance.',\n placeholder: 'https://sentry.io/',\n });\n\n abortIfCancelled(url);\n\n return { url, selfHosted: true };\n}\n\nexport async function addSentryCliRc(authToken: string): Promise<void> {\n const clircExists = fs.existsSync(path.join(process.cwd(), '.sentryclirc'));\n if (clircExists) {\n const clircContents = fs.readFileSync(\n path.join(process.cwd(), '.sentryclirc'),\n 'utf8',\n );\n\n const likelyAlreadyHasAuthToken = !!(\n clircContents.includes('[auth]') && clircContents.match(/token=./g)\n );\n\n if (likelyAlreadyHasAuthToken) {\n clack.log.warn(\n `${chalk.bold(\n '.sentryclirc',\n )} already has auth token. Will not add one.`,\n );\n } else {\n try {\n await fs.promises.writeFile(\n path.join(process.cwd(), '.sentryclirc'),\n `${clircContents}\\n[auth]\\ntoken=${authToken}\\n`,\n { encoding: 'utf8', flag: 'w' },\n );\n clack.log.success(`Added auth token to ${chalk.bold('.sentryclirc')}`);\n } catch (e) {\n clack.log.warning(\n `Failed to add auth token to ${chalk.bold(\n '.sentryclirc',\n )}. Uploading source maps during build will likely not work.`,\n );\n }\n }\n } else {\n try {\n await fs.promises.writeFile(\n path.join(process.cwd(), '.sentryclirc'),\n `[auth]\\ntoken=${authToken}\\n`,\n { encoding: 'utf8', flag: 'w' },\n );\n clack.log.success(\n `Created ${chalk.bold('.sentryclirc')} with auth token.`,\n );\n } catch (e) {\n clack.log.warning(\n `Failed to create ${chalk.bold(\n '.sentryclirc',\n )} with auth token. Uploading source maps during build will likely not work.`,\n );\n }\n }\n\n try {\n await fs.promises.appendFile(\n path.join(process.cwd(), '.gitignore'),\n '\\n# Sentry Auth Token\\n.sentryclirc\\n',\n { encoding: 'utf8' },\n );\n clack.log.success(\n `Added ${chalk.bold('.sentryclirc')} to ${chalk.bold('.gitignore')}.`,\n );\n } catch (e) {\n clack.log.error(\n `Failed adding ${chalk.bold('.sentryclirc')} to ${chalk.bold(\n '.gitignore',\n )}. Please add it manually!`,\n );\n }\n}\n"]}
|