@sentry/wizard 3.31.0 → 3.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +19 -24
  3. package/bin.ts +71 -21
  4. package/dist/bin.js +97 -52
  5. package/dist/bin.js.map +1 -1
  6. package/dist/e2e-tests/jest.config.d.ts +15 -0
  7. package/dist/e2e-tests/jest.config.js +17 -0
  8. package/dist/e2e-tests/jest.config.js.map +1 -0
  9. package/dist/e2e-tests/tests/remix.test.d.ts +1 -0
  10. package/dist/e2e-tests/tests/remix.test.js +187 -0
  11. package/dist/e2e-tests/tests/remix.test.js.map +1 -0
  12. package/dist/e2e-tests/utils/index.d.ts +117 -0
  13. package/dist/e2e-tests/utils/index.js +353 -0
  14. package/dist/e2e-tests/utils/index.js.map +1 -0
  15. package/dist/lib/Steps/SentryProjectSelector.js +1 -1
  16. package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
  17. package/dist/package.json +7 -3
  18. package/dist/src/remix/sdk-example.js +5 -1
  19. package/dist/src/remix/sdk-example.js.map +1 -1
  20. package/dist/src/run.d.ts +13 -1
  21. package/dist/src/run.js +34 -7
  22. package/dist/src/run.js.map +1 -1
  23. package/dist/src/sourcemaps/sourcemaps-wizard.d.ts +2 -2
  24. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  25. package/dist/src/sourcemaps/tools/remix.d.ts +2 -2
  26. package/dist/src/sourcemaps/tools/remix.js.map +1 -1
  27. package/dist/src/telemetry.js +1 -0
  28. package/dist/src/telemetry.js.map +1 -1
  29. package/dist/src/utils/clack-utils.js +29 -19
  30. package/dist/src/utils/clack-utils.js.map +1 -1
  31. package/dist/src/utils/types.d.ts +11 -14
  32. package/dist/src/utils/types.js.map +1 -1
  33. package/e2e-tests/jest.config.ts +14 -0
  34. package/e2e-tests/test-applications/remix-test-app/app/entry.client.tsx +18 -0
  35. package/e2e-tests/test-applications/remix-test-app/app/entry.server.tsx +140 -0
  36. package/e2e-tests/test-applications/remix-test-app/app/root.tsx +30 -0
  37. package/e2e-tests/test-applications/remix-test-app/app/routes/_index.tsx +48 -0
  38. package/e2e-tests/test-applications/remix-test-app/app/tailwind.css +3 -0
  39. package/e2e-tests/test-applications/remix-test-app/package.json +37 -0
  40. package/e2e-tests/test-applications/remix-test-app/postcss.config.js +6 -0
  41. package/e2e-tests/test-applications/remix-test-app/tailwind.config.ts +9 -0
  42. package/e2e-tests/test-applications/remix-test-app/vite.config.ts +16 -0
  43. package/e2e-tests/tests/remix.test.ts +163 -0
  44. package/e2e-tests/utils/index.ts +302 -0
  45. package/lib/Steps/SentryProjectSelector.ts +1 -1
  46. package/package.json +7 -3
  47. package/src/remix/sdk-example.ts +6 -0
  48. package/src/run.ts +53 -11
  49. package/src/sourcemaps/sourcemaps-wizard.ts +4 -3
  50. package/src/sourcemaps/tools/remix.ts +2 -2
  51. package/src/telemetry.ts +1 -0
  52. package/src/utils/clack-utils.ts +28 -10
  53. package/src/utils/types.ts +14 -14
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remix.test.js","sourceRoot":"","sources":["../../../e2e-tests/tests/remix.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,iDAAkD;AAClD,kCAKkB;AAClB,kCAA+C;AAC/C,kCAQkB;AAClB,yCAA6B;AAE7B,QAAQ,CAAC,OAAO,EAAE;IAChB,IAAM,WAAW,GAAG,uBAAW,CAAC,KAAK,CAAC;IACtC,IAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAC7B,SAAS,EACT,qCAAqC,CACtC,CAAC;IAEF,SAAS,CAAC;;;;;oBACF,cAAc,GAAG,IAAA,2BAAmB,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC;oBACrC,qBAAM,cAAc,CAAC,aAAa,CAC/D,qCAAqC,CACtC,EAAA;;oBAFK,sBAAsB,GAAG,SAE9B;oBAED,IAAI,sBAAsB,EAAE;wBAC1B,0CAA0C;wBAC1C,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,IAAI,CAAC,CAAC;wBACpC,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,KAAK,CAAC,CAAC;qBACtC;oBAE6B,qBAAM,cAAc,CAAC,aAAa,CAC9D,+BAA+B,EAC/B;4BACE,OAAO,EAAE,MAAO;yBACjB,CACF,EAAA;;oBALK,qBAAqB,GAAG,SAK7B;oBAED,IAAI,qBAAqB,EAAE;wBACzB,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,KAAK,CAAC,CAAC;qBACtC;oBAE4B,qBAAM,cAAc,CAAC,aAAa,CAC7D,6CAA6C,CAC9C,EAAA;;oBAFK,oBAAoB,GAAG,SAE5B;oBAED,IAAI,oBAAoB,EAAE;wBACxB,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,KAAK,CAAC,CAAC;qBACtC;oBAE2B,qBAAM,cAAc,CAAC,aAAa,CAC5D,uCAAuC,EACvC;4BACE,QAAQ,EAAE,IAAI;yBACf,CACF,EAAA;;oBALK,mBAAmB,GAAG,SAK3B;oBAED,IAAI,mBAAmB,EAAE;wBACvB,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,KAAK,CAAC,CAAC;wBACrC,cAAc,CAAC,SAAS,CAAC,YAAI,CAAC,KAAK,CAAC,CAAC;qBACtC;oBAED,qBAAM,cAAc,CAAC,aAAa,CAChC,gEAAgE,CACjE,EAAA;;oBAFD,SAEC,CAAC;oBAEF,cAAc,CAAC,IAAI,EAAE,CAAC;;;;SACvB,CAAC,CAAC;IAEH,QAAQ,CAAC;QACP,IAAA,0BAAkB,EAAC,UAAU,CAAC,CAAC;QAC/B,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mCAAmC,EAAE;QACxC,IAAA,wBAAgB,EAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE;QACtE,IAAA,2BAAmB,EAAC,UAAU,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qBAAqB,EAAE;QAC1B,IAAA,uBAAe,EAAC,UAAG,UAAU,wCAAqC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oCAAoC,EAAE;QACzC,IAAA,uBAAe,EAAC,UAAG,UAAU,gCAA6B,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kDAAkD,EAAE;QACvD,IAAA,yBAAiB,EAAC,UAAG,UAAU,0BAAuB,EAAE;YACtD,0CAA0C;YAC1C,oCACM,iBAAS,CAAC,WAAW,qUAc9B;SACE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wCAAwC,EAAE;QAC7C,IAAA,yBAAiB,EAAC,UAAG,UAAU,0BAAuB,EAAE;YACtD,0CAA0C;YAC1C,oIAEF;SACC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4DAA4D,EAAE;QACjE,IAAA,yBAAiB,EAAC,UAAG,UAAU,gCAA6B,EAAE;YAC5D,0CAA0C;YAC1C,oCACM,iBAAS,CAAC,WAAW,qEAG9B;SACE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE;QAC9C,IAAA,yBAAiB,EAAC,UAAG,UAAU,kBAAe,EAAE;YAC9C,iEAAiE;YACjE,iKAIH;SACE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kBAAkB,EAAE;;;wBACvB,qBAAM,IAAA,qBAAa,EAAC,UAAU,EAAE,OAAO,CAAC,EAAA;;oBAAxC,SAAwC,CAAC;;;;SAC1C,CAAC,CAAC;IAEH,IAAI,CAAC,4BAA4B,EAAE;;;wBACjC,qBAAM,IAAA,4BAAoB,EAAC,UAAU,EAAE,WAAW,CAAC,EAAA;;oBAAnD,SAAmD,CAAC;;;;SACrD,CAAC,CAAC;IAEH,IAAI,CAAC,6BAA6B,EAAE;;;wBAClC,qBAAM,IAAA,6BAAqB,EAAC,UAAU,EAAE,eAAe,CAAC,EAAA;;oBAAxD,SAAwD,CAAC;;;;SAC1D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/* eslint-disable jest/expect-expect */\nimport { Integration } from '../../lib/Constants';\nimport {\n checkEnvBuildPlugin,\n cleanupGit,\n KEYS,\n revertLocalChanges,\n} from '../utils';\nimport { startWizardInstance } from '../utils';\nimport {\n checkFileContents,\n checkFileExists,\n checkIfBuilds,\n checkIfRunsOnDevMode,\n checkIfRunsOnProdMode,\n checkPackageJson,\n TEST_ARGS,\n} from '../utils';\nimport * as path from 'path';\n\ndescribe('Remix', () => {\n const integration = Integration.remix;\n const projectDir = path.resolve(\n __dirname,\n '../test-applications/remix-test-app',\n );\n\n beforeAll(async () => {\n const wizardInstance = startWizardInstance(integration, projectDir);\n const packageManagerPrompted = await wizardInstance.waitForOutput(\n 'Please select your package manager.',\n );\n\n if (packageManagerPrompted) {\n // Selecting `yarn` as the package manager\n wizardInstance.sendStdin(KEYS.DOWN);\n wizardInstance.sendStdin(KEYS.ENTER);\n }\n\n const tracingOptionPrompted = await wizardInstance.waitForOutput(\n 'Do you want to enable Tracing',\n {\n timeout: 240_000,\n },\n );\n\n if (tracingOptionPrompted) {\n wizardInstance.sendStdin(KEYS.ENTER);\n }\n\n const replayOptionPrompted = await wizardInstance.waitForOutput(\n 'Do you want to enable Sentry Session Replay',\n );\n\n if (replayOptionPrompted) {\n wizardInstance.sendStdin(KEYS.ENTER);\n }\n\n const examplePagePrompted = await wizardInstance.waitForOutput(\n 'Do you want to create an example page',\n {\n optional: true,\n },\n );\n\n if (examplePagePrompted) {\n wizardInstance.sendStdin(KEYS.ENTER);\n wizardInstance.sendStdin(KEYS.ENTER);\n }\n\n await wizardInstance.waitForOutput(\n 'Sentry has been successfully configured for your Remix project',\n );\n\n wizardInstance.kill();\n });\n\n afterAll(() => {\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n });\n\n test('package.json is updated correctly', () => {\n checkPackageJson(projectDir, integration);\n });\n\n test('.env-sentry-build-plugin is created and contains the auth token', () => {\n checkEnvBuildPlugin(projectDir);\n });\n\n test('example page exists', () => {\n checkFileExists(`${projectDir}/app/routes/sentry-example-page.tsx`);\n });\n\n test('instrumentation.server file exists', () => {\n checkFileExists(`${projectDir}/instrumentation.server.mjs`);\n });\n\n test('entry.client file contains Sentry initialization', () => {\n checkFileContents(`${projectDir}/app/entry.client.tsx`, [\n 'import * as Sentry from \"@sentry/remix\";',\n `Sentry.init({\n dsn: \"${TEST_ARGS.PROJECT_DSN}\",\n tracesSampleRate: 1,\n\n integrations: [Sentry.browserTracingIntegration({\n useEffect,\n useLocation,\n useMatches\n }), Sentry.replayIntegration({\n maskAllText: true,\n blockAllMedia: true\n })],\n\n replaysSessionSampleRate: 0.1,\n replaysOnErrorSampleRate: 1\n})`,\n ]);\n });\n\n test('entry.server file contains Sentry code', () => {\n checkFileContents(`${projectDir}/app/entry.server.tsx`, [\n 'import * as Sentry from \"@sentry/remix\";',\n `export const handleError = Sentry.wrapHandleErrorWithSentry((error, { request }) => {\n // Custom handleError implementation\n});`,\n ]);\n });\n\n test('instrumentation.server file contains Sentry initialization', () => {\n checkFileContents(`${projectDir}/instrumentation.server.mjs`, [\n 'import * as Sentry from \"@sentry/remix\";',\n `Sentry.init({\n dsn: \"${TEST_ARGS.PROJECT_DSN}\",\n tracesSampleRate: 1,\n autoInstrumentRemix: true\n})`,\n ]);\n });\n\n test('root file contains Sentry ErrorBoundary', () => {\n checkFileContents(`${projectDir}/app/root.tsx`, [\n 'import { captureRemixErrorBoundaryError } from \"@sentry/remix\";',\n `export const ErrorBoundary = () => {\n const error = useRouteError();\n captureRemixErrorBoundaryError(error);\n return <div>Something went wrong</div>;\n};`,\n ]);\n });\n\n test('builds correctly', async () => {\n await checkIfBuilds(projectDir, 'built');\n });\n\n test('runs on dev mode correctly', async () => {\n await checkIfRunsOnDevMode(projectDir, 'to expose');\n });\n\n test('runs on prod mode correctly', async () => {\n await checkIfRunsOnProdMode(projectDir, '[remix-serve]');\n });\n});\n"]}
@@ -0,0 +1,117 @@
1
+ /// <reference types="node" />
2
+ import type { Integration } from '../../lib/Constants';
3
+ import type { ChildProcess } from 'child_process';
4
+ export declare const KEYS: {
5
+ UP: string;
6
+ DOWN: string;
7
+ LEFT: string;
8
+ RIGHT: string;
9
+ ENTER: string;
10
+ SPACE: string;
11
+ };
12
+ export declare const TEST_ARGS: {
13
+ AUTH_TOKEN: string;
14
+ PROJECT_DSN: string;
15
+ };
16
+ export declare const log: {
17
+ success: (message: string) => void;
18
+ info: (message: string) => void;
19
+ error: (message: string) => void;
20
+ };
21
+ export declare class WizardTestEnv {
22
+ taskHandle: ChildProcess;
23
+ constructor(cmd: string, args: string[], opts?: {
24
+ cwd?: string;
25
+ debug?: boolean;
26
+ });
27
+ sendStdin(input: string): void;
28
+ /**
29
+ * Waits for the provided output with `.includes()` logic.
30
+ *
31
+ * @returns a promise that resolves to `true` if the output was found, `false` if the output was not found within the
32
+ * timeout and `optional: true` is set, or it rejects when the timeout was reached with `optional: false`
33
+ */
34
+ waitForOutput(output: string, options?: {
35
+ /** Timeout in ms */
36
+ timeout?: number;
37
+ /** Whether to always resolve after the timeout, no matter whether the input was actually found or not. */
38
+ optional?: boolean;
39
+ }): Promise<boolean>;
40
+ kill(): void;
41
+ }
42
+ /**
43
+ * Initialize a git repository in the given directory
44
+ * @param projectDir
45
+ */
46
+ export declare function initGit(projectDir: string): void;
47
+ /**
48
+ * Cleanup the git repository in the given directory
49
+ *
50
+ * Caution! Make sure `projectDir` is a test project directory,
51
+ * if in doubt, please commit your local non-test changes first!
52
+ * @param projectDir
53
+ */
54
+ export declare function cleanupGit(projectDir: string): void;
55
+ /**
56
+ * Revert local changes in the given directory
57
+ *
58
+ * Caution! Make sure `projectDir` is a test project directory,
59
+ * if in doubt, please commit your local non-test changes first!
60
+ *
61
+ * @param projectDir
62
+ */
63
+ export declare function revertLocalChanges(projectDir: string): void;
64
+ /**
65
+ * Start the wizard instance with the given integration and project directory
66
+ * @param integration
67
+ * @param projectDir
68
+ *
69
+ * @returns WizardTestEnv
70
+ */
71
+ export declare function startWizardInstance(integration: Integration, projectDir: string): WizardTestEnv;
72
+ /**
73
+ * Read the file contents and check if it contains the given content
74
+ *
75
+ * @param filePath
76
+ * @param content
77
+ */
78
+ export declare function checkFileContents(filePath: string, content: string | string[]): void;
79
+ /**
80
+ * Check if the file exists
81
+ *
82
+ * @param filePath
83
+ */
84
+ export declare function checkFileExists(filePath: string): void;
85
+ /**
86
+ * Check if the package.json contains the given integration
87
+ * @param projectDir
88
+ * @param integration
89
+ */
90
+ export declare function checkPackageJson(projectDir: string, integration: Integration): void;
91
+ /**
92
+ * Check if the .sentryclirc contains the auth token
93
+ * @param projectDir
94
+ */
95
+ export declare function checkSentryCliRc(projectDir: string): void;
96
+ /**
97
+ * Check if the .env.sentry-build-plugin contains the auth token
98
+ * @param projectDir
99
+ */
100
+ export declare function checkEnvBuildPlugin(projectDir: string): void;
101
+ /**
102
+ * Check if the project builds
103
+ * @param projectDir
104
+ */
105
+ export declare function checkIfBuilds(projectDir: string, expectedOutput: string): Promise<void>;
106
+ /**
107
+ * Check if the project runs on dev mode
108
+ * @param projectDir
109
+ * @param expectedOutput
110
+ */
111
+ export declare function checkIfRunsOnDevMode(projectDir: string, expectedOutput: string): Promise<void>;
112
+ /**
113
+ * Check if the project runs on prod mode
114
+ * @param projectDir
115
+ * @param expectedOutput
116
+ */
117
+ export declare function checkIfRunsOnProdMode(projectDir: string, expectedOutput: string): Promise<void>;
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
72
+ Object.defineProperty(exports, "__esModule", { value: true });
73
+ exports.checkIfRunsOnProdMode = exports.checkIfRunsOnDevMode = exports.checkIfBuilds = exports.checkEnvBuildPlugin = exports.checkSentryCliRc = exports.checkPackageJson = exports.checkFileExists = exports.checkFileContents = exports.startWizardInstance = exports.revertLocalChanges = exports.cleanupGit = exports.initGit = exports.WizardTestEnv = exports.log = exports.TEST_ARGS = exports.KEYS = void 0;
74
+ var fs = __importStar(require("fs"));
75
+ var path = __importStar(require("path"));
76
+ var child_process_1 = require("child_process");
77
+ var Logging_1 = require("../../lib/Helper/Logging");
78
+ exports.KEYS = {
79
+ UP: '\u001b[A',
80
+ DOWN: '\u001b[B',
81
+ LEFT: '\u001b[D',
82
+ RIGHT: '\u001b[C',
83
+ ENTER: '\r',
84
+ SPACE: ' ',
85
+ };
86
+ exports.TEST_ARGS = {
87
+ AUTH_TOKEN: 'TEST_AUTH_TOKEN',
88
+ PROJECT_DSN: 'https://public@dsn.ingest.sentry.io/1337',
89
+ };
90
+ exports.log = {
91
+ success: function (message) {
92
+ (0, Logging_1.green)("[SUCCESS] ".concat(message));
93
+ },
94
+ info: function (message) {
95
+ (0, Logging_1.dim)("[INFO] ".concat(message));
96
+ },
97
+ error: function (message) {
98
+ (0, Logging_1.red)("[ERROR] ".concat(message));
99
+ },
100
+ };
101
+ var WizardTestEnv = /** @class */ (function () {
102
+ function WizardTestEnv(cmd, args, opts) {
103
+ this.taskHandle = (0, child_process_1.spawn)(cmd, args, { cwd: opts === null || opts === void 0 ? void 0 : opts.cwd, stdio: 'pipe' });
104
+ if (opts === null || opts === void 0 ? void 0 : opts.debug) {
105
+ this.taskHandle.stdout.pipe(process.stdout);
106
+ this.taskHandle.stderr.pipe(process.stderr);
107
+ }
108
+ }
109
+ WizardTestEnv.prototype.sendStdin = function (input) {
110
+ this.taskHandle.stdin.write(input);
111
+ };
112
+ /**
113
+ * Waits for the provided output with `.includes()` logic.
114
+ *
115
+ * @returns a promise that resolves to `true` if the output was found, `false` if the output was not found within the
116
+ * timeout and `optional: true` is set, or it rejects when the timeout was reached with `optional: false`
117
+ */
118
+ WizardTestEnv.prototype.waitForOutput = function (output, options) {
119
+ var _this = this;
120
+ if (options === void 0) { options = {}; }
121
+ var _a = __assign({ timeout: 30000, optional: false }, options), timeout = _a.timeout, optional = _a.optional;
122
+ return new Promise(function (resolve, reject) {
123
+ var outputBuffer = '';
124
+ var timeoutId = setTimeout(function () {
125
+ if (optional) {
126
+ // The output is not found but it's optional so we can resolve the promise with false
127
+ resolve(false);
128
+ }
129
+ else {
130
+ reject(new Error("Timeout waiting for output: ".concat(output)));
131
+ }
132
+ }, timeout);
133
+ _this.taskHandle.stdout.on('data', function (data) {
134
+ outputBuffer += data;
135
+ if (outputBuffer.includes(output)) {
136
+ clearTimeout(timeoutId);
137
+ // The output is found so we can resolve the promise with true
138
+ resolve(true);
139
+ }
140
+ });
141
+ });
142
+ };
143
+ WizardTestEnv.prototype.kill = function () {
144
+ this.taskHandle.stdin.destroy();
145
+ this.taskHandle.stderr.destroy();
146
+ this.taskHandle.stdout.destroy();
147
+ this.taskHandle.kill('SIGINT');
148
+ this.taskHandle.unref();
149
+ };
150
+ return WizardTestEnv;
151
+ }());
152
+ exports.WizardTestEnv = WizardTestEnv;
153
+ /**
154
+ * Initialize a git repository in the given directory
155
+ * @param projectDir
156
+ */
157
+ function initGit(projectDir) {
158
+ try {
159
+ (0, child_process_1.execSync)('git init', { cwd: projectDir });
160
+ // Add all files to the git repo
161
+ (0, child_process_1.execSync)('git add -A', { cwd: projectDir });
162
+ // Add author info to avoid git commit error
163
+ (0, child_process_1.execSync)('git config user.email test@test.sentry.io', { cwd: projectDir });
164
+ (0, child_process_1.execSync)('git config user.name Test', { cwd: projectDir });
165
+ (0, child_process_1.execSync)('git commit -m init', { cwd: projectDir });
166
+ }
167
+ catch (e) {
168
+ exports.log.error('Error initializing git');
169
+ throw e;
170
+ }
171
+ }
172
+ exports.initGit = initGit;
173
+ /**
174
+ * Cleanup the git repository in the given directory
175
+ *
176
+ * Caution! Make sure `projectDir` is a test project directory,
177
+ * if in doubt, please commit your local non-test changes first!
178
+ * @param projectDir
179
+ */
180
+ function cleanupGit(projectDir) {
181
+ try {
182
+ // Remove the .git directory
183
+ (0, child_process_1.execSync)("rm -rf ".concat(projectDir, "/.git"));
184
+ }
185
+ catch (e) {
186
+ exports.log.error('Error cleaning up git');
187
+ throw e;
188
+ }
189
+ }
190
+ exports.cleanupGit = cleanupGit;
191
+ /**
192
+ * Revert local changes in the given directory
193
+ *
194
+ * Caution! Make sure `projectDir` is a test project directory,
195
+ * if in doubt, please commit your local non-test changes first!
196
+ *
197
+ * @param projectDir
198
+ */
199
+ function revertLocalChanges(projectDir) {
200
+ try {
201
+ // Revert tracked files
202
+ (0, child_process_1.execSync)('git checkout .', { cwd: projectDir });
203
+ // Revert untracked files
204
+ (0, child_process_1.execSync)('git clean -fd .', { cwd: projectDir });
205
+ }
206
+ catch (e) {
207
+ exports.log.error('Error reverting local changes');
208
+ throw e;
209
+ }
210
+ }
211
+ exports.revertLocalChanges = revertLocalChanges;
212
+ /**
213
+ * Start the wizard instance with the given integration and project directory
214
+ * @param integration
215
+ * @param projectDir
216
+ *
217
+ * @returns WizardTestEnv
218
+ */
219
+ function startWizardInstance(integration, projectDir) {
220
+ var binPath = path.join(__dirname, '../../dist/bin.js');
221
+ revertLocalChanges(projectDir);
222
+ cleanupGit(projectDir);
223
+ initGit(projectDir);
224
+ return new WizardTestEnv('node', [
225
+ binPath,
226
+ '--debug',
227
+ '-i',
228
+ integration,
229
+ '--preSelectedProject.authToken',
230
+ exports.TEST_ARGS.AUTH_TOKEN,
231
+ '--preSelectedProject.dsn',
232
+ exports.TEST_ARGS.PROJECT_DSN,
233
+ ], { cwd: projectDir });
234
+ }
235
+ exports.startWizardInstance = startWizardInstance;
236
+ /**
237
+ * Read the file contents and check if it contains the given content
238
+ *
239
+ * @param filePath
240
+ * @param content
241
+ */
242
+ function checkFileContents(filePath, content) {
243
+ var fileContent = fs.readFileSync(filePath, 'utf-8');
244
+ var contentArray = Array.isArray(content) ? content : [content];
245
+ for (var _i = 0, contentArray_1 = contentArray; _i < contentArray_1.length; _i++) {
246
+ var c = contentArray_1[_i];
247
+ expect(fileContent).toContain(c);
248
+ }
249
+ }
250
+ exports.checkFileContents = checkFileContents;
251
+ /**
252
+ * Check if the file exists
253
+ *
254
+ * @param filePath
255
+ */
256
+ function checkFileExists(filePath) {
257
+ expect(fs.existsSync(filePath)).toBe(true);
258
+ }
259
+ exports.checkFileExists = checkFileExists;
260
+ /**
261
+ * Check if the package.json contains the given integration
262
+ * @param projectDir
263
+ * @param integration
264
+ */
265
+ function checkPackageJson(projectDir, integration) {
266
+ checkFileContents("".concat(projectDir, "/package.json"), "@sentry/".concat(integration));
267
+ }
268
+ exports.checkPackageJson = checkPackageJson;
269
+ /**
270
+ * Check if the .sentryclirc contains the auth token
271
+ * @param projectDir
272
+ */
273
+ function checkSentryCliRc(projectDir) {
274
+ checkFileContents("".concat(projectDir, "/.sentryclirc"), "token=".concat(exports.TEST_ARGS.AUTH_TOKEN));
275
+ }
276
+ exports.checkSentryCliRc = checkSentryCliRc;
277
+ /**
278
+ * Check if the .env.sentry-build-plugin contains the auth token
279
+ * @param projectDir
280
+ */
281
+ function checkEnvBuildPlugin(projectDir) {
282
+ checkFileContents("".concat(projectDir, "/.env.sentry-build-plugin"), "SENTRY_AUTH_TOKEN=".concat(exports.TEST_ARGS.AUTH_TOKEN));
283
+ }
284
+ exports.checkEnvBuildPlugin = checkEnvBuildPlugin;
285
+ /**
286
+ * Check if the project builds
287
+ * @param projectDir
288
+ */
289
+ function checkIfBuilds(projectDir, expectedOutput) {
290
+ return __awaiter(this, void 0, void 0, function () {
291
+ var testEnv;
292
+ return __generator(this, function (_a) {
293
+ switch (_a.label) {
294
+ case 0:
295
+ testEnv = new WizardTestEnv('npm', ['run', 'build'], {
296
+ cwd: projectDir,
297
+ });
298
+ return [4 /*yield*/, expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true)];
299
+ case 1:
300
+ _a.sent();
301
+ return [2 /*return*/];
302
+ }
303
+ });
304
+ });
305
+ }
306
+ exports.checkIfBuilds = checkIfBuilds;
307
+ /**
308
+ * Check if the project runs on dev mode
309
+ * @param projectDir
310
+ * @param expectedOutput
311
+ */
312
+ function checkIfRunsOnDevMode(projectDir, expectedOutput) {
313
+ return __awaiter(this, void 0, void 0, function () {
314
+ var testEnv;
315
+ return __generator(this, function (_a) {
316
+ switch (_a.label) {
317
+ case 0:
318
+ testEnv = new WizardTestEnv('npm', ['run', 'dev'], { cwd: projectDir });
319
+ return [4 /*yield*/, expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true)];
320
+ case 1:
321
+ _a.sent();
322
+ testEnv.kill();
323
+ return [2 /*return*/];
324
+ }
325
+ });
326
+ });
327
+ }
328
+ exports.checkIfRunsOnDevMode = checkIfRunsOnDevMode;
329
+ /**
330
+ * Check if the project runs on prod mode
331
+ * @param projectDir
332
+ * @param expectedOutput
333
+ */
334
+ function checkIfRunsOnProdMode(projectDir, expectedOutput) {
335
+ return __awaiter(this, void 0, void 0, function () {
336
+ var testEnv;
337
+ return __generator(this, function (_a) {
338
+ switch (_a.label) {
339
+ case 0:
340
+ testEnv = new WizardTestEnv('npm', ['run', 'start'], {
341
+ cwd: projectDir,
342
+ });
343
+ return [4 /*yield*/, expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true)];
344
+ case 1:
345
+ _a.sent();
346
+ testEnv.kill();
347
+ return [2 /*return*/];
348
+ }
349
+ });
350
+ });
351
+ }
352
+ exports.checkIfRunsOnProdMode = checkIfRunsOnProdMode;
353
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../e2e-tests/utils/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport type { Integration } from '../../lib/Constants';\nimport { spawn, execSync } from 'child_process';\nimport type { ChildProcess } from 'child_process';\nimport { dim, green, red } from '../../lib/Helper/Logging';\n\nexport const KEYS = {\n UP: '\\u001b[A',\n DOWN: '\\u001b[B',\n LEFT: '\\u001b[D',\n RIGHT: '\\u001b[C',\n ENTER: '\\r',\n SPACE: ' ',\n};\n\nexport const TEST_ARGS = {\n AUTH_TOKEN: 'TEST_AUTH_TOKEN',\n PROJECT_DSN: 'https://public@dsn.ingest.sentry.io/1337',\n};\n\nexport const log = {\n success: (message: string) => {\n green(`[SUCCESS] ${message}`);\n },\n info: (message: string) => {\n dim(`[INFO] ${message}`);\n },\n error: (message: string) => {\n red(`[ERROR] ${message}`);\n },\n};\n\nexport class WizardTestEnv {\n taskHandle: ChildProcess;\n\n constructor(\n cmd: string,\n args: string[],\n opts?: {\n cwd?: string;\n debug?: boolean;\n },\n ) {\n this.taskHandle = spawn(cmd, args, { cwd: opts?.cwd, stdio: 'pipe' });\n\n if (opts?.debug) {\n this.taskHandle.stdout.pipe(process.stdout);\n this.taskHandle.stderr.pipe(process.stderr);\n }\n }\n\n sendStdin(input: string) {\n this.taskHandle.stdin.write(input);\n }\n\n /**\n * Waits for the provided output with `.includes()` logic.\n *\n * @returns a promise that resolves to `true` if the output was found, `false` if the output was not found within the\n * timeout and `optional: true` is set, or it rejects when the timeout was reached with `optional: false`\n */\n waitForOutput(\n output: string,\n options: {\n /** Timeout in ms */\n timeout?: number;\n /** Whether to always resolve after the timeout, no matter whether the input was actually found or not. */\n optional?: boolean;\n } = {},\n ) {\n const { timeout, optional } = {\n timeout: 30_000,\n optional: false,\n ...options,\n };\n\n return new Promise<boolean>((resolve, reject) => {\n let outputBuffer = '';\n const timeoutId = setTimeout(() => {\n if (optional) {\n // The output is not found but it's optional so we can resolve the promise with false\n resolve(false);\n } else {\n reject(new Error(`Timeout waiting for output: ${output}`));\n }\n }, timeout);\n\n this.taskHandle.stdout.on('data', (data) => {\n outputBuffer += data;\n if (outputBuffer.includes(output)) {\n clearTimeout(timeoutId);\n // The output is found so we can resolve the promise with true\n resolve(true);\n }\n });\n });\n }\n\n kill() {\n this.taskHandle.stdin.destroy();\n this.taskHandle.stderr.destroy();\n this.taskHandle.stdout.destroy();\n this.taskHandle.kill('SIGINT');\n this.taskHandle.unref();\n }\n}\n\n/**\n * Initialize a git repository in the given directory\n * @param projectDir\n */\nexport function initGit(projectDir: string): void {\n try {\n execSync('git init', { cwd: projectDir });\n // Add all files to the git repo\n execSync('git add -A', { cwd: projectDir });\n // Add author info to avoid git commit error\n execSync('git config user.email test@test.sentry.io', { cwd: projectDir });\n execSync('git config user.name Test', { cwd: projectDir });\n execSync('git commit -m init', { cwd: projectDir });\n } catch (e) {\n log.error('Error initializing git');\n throw e;\n }\n}\n\n/**\n * Cleanup the git repository in the given directory\n *\n * Caution! Make sure `projectDir` is a test project directory,\n * if in doubt, please commit your local non-test changes first!\n * @param projectDir\n */\nexport function cleanupGit(projectDir: string): void {\n try {\n // Remove the .git directory\n execSync(`rm -rf ${projectDir}/.git`);\n } catch (e) {\n log.error('Error cleaning up git');\n throw e;\n }\n}\n\n/**\n * Revert local changes in the given directory\n *\n * Caution! Make sure `projectDir` is a test project directory,\n * if in doubt, please commit your local non-test changes first!\n *\n * @param projectDir\n */\nexport function revertLocalChanges(projectDir: string): void {\n try {\n // Revert tracked files\n execSync('git checkout .', { cwd: projectDir });\n // Revert untracked files\n execSync('git clean -fd .', { cwd: projectDir });\n } catch (e) {\n log.error('Error reverting local changes');\n throw e;\n }\n}\n\n/**\n * Start the wizard instance with the given integration and project directory\n * @param integration\n * @param projectDir\n *\n * @returns WizardTestEnv\n */\nexport function startWizardInstance(\n integration: Integration,\n projectDir: string,\n): WizardTestEnv {\n const binPath = path.join(__dirname, '../../dist/bin.js');\n\n revertLocalChanges(projectDir);\n cleanupGit(projectDir);\n initGit(projectDir);\n\n return new WizardTestEnv(\n 'node',\n [\n binPath,\n '--debug',\n '-i',\n integration,\n '--preSelectedProject.authToken',\n TEST_ARGS.AUTH_TOKEN,\n '--preSelectedProject.dsn',\n TEST_ARGS.PROJECT_DSN,\n ],\n { cwd: projectDir },\n );\n}\n\n/**\n * Read the file contents and check if it contains the given content\n *\n * @param filePath\n * @param content\n */\nexport function checkFileContents(\n filePath: string,\n content: string | string[],\n) {\n const fileContent = fs.readFileSync(filePath, 'utf-8');\n const contentArray = Array.isArray(content) ? content : [content];\n\n for (const c of contentArray) {\n expect(fileContent).toContain(c);\n }\n}\n\n/**\n * Check if the file exists\n *\n * @param filePath\n */\nexport function checkFileExists(filePath: string) {\n expect(fs.existsSync(filePath)).toBe(true);\n}\n\n/**\n * Check if the package.json contains the given integration\n * @param projectDir\n * @param integration\n */\nexport function checkPackageJson(projectDir: string, integration: Integration) {\n checkFileContents(`${projectDir}/package.json`, `@sentry/${integration}`);\n}\n\n/**\n * Check if the .sentryclirc contains the auth token\n * @param projectDir\n */\nexport function checkSentryCliRc(projectDir: string) {\n checkFileContents(\n `${projectDir}/.sentryclirc`,\n `token=${TEST_ARGS.AUTH_TOKEN}`,\n );\n}\n\n/**\n * Check if the .env.sentry-build-plugin contains the auth token\n * @param projectDir\n */\nexport function checkEnvBuildPlugin(projectDir: string) {\n checkFileContents(\n `${projectDir}/.env.sentry-build-plugin`,\n `SENTRY_AUTH_TOKEN=${TEST_ARGS.AUTH_TOKEN}`,\n );\n}\n\n/**\n * Check if the project builds\n * @param projectDir\n */\nexport async function checkIfBuilds(\n projectDir: string,\n expectedOutput: string,\n) {\n const testEnv = new WizardTestEnv('npm', ['run', 'build'], {\n cwd: projectDir,\n });\n\n await expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true);\n}\n\n/**\n * Check if the project runs on dev mode\n * @param projectDir\n * @param expectedOutput\n */\nexport async function checkIfRunsOnDevMode(\n projectDir: string,\n expectedOutput: string,\n) {\n const testEnv = new WizardTestEnv('npm', ['run', 'dev'], { cwd: projectDir });\n\n await expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true);\n testEnv.kill();\n}\n\n/**\n * Check if the project runs on prod mode\n * @param projectDir\n * @param expectedOutput\n */\nexport async function checkIfRunsOnProdMode(\n projectDir: string,\n expectedOutput: string,\n) {\n const testEnv = new WizardTestEnv('npm', ['run', 'start'], {\n cwd: projectDir,\n });\n\n await expect(testEnv.waitForOutput(expectedOutput)).resolves.toBe(true);\n testEnv.kill();\n}\n"]}
@@ -94,7 +94,7 @@ var SentryProjectSelector = /** @class */ (function (_super) {
94
94
  case 0:
95
95
  this.debug(answers);
96
96
  if (!_.has(answers, 'wizard')) {
97
- // we skip this completly because the wizard wasn't running
97
+ // we skip this completely because the wizard wasn't running
98
98
  return [2 /*return*/, {}];
99
99
  }
100
100
  if (_.has(answers, 'wizard.projects') &&
@@ -1 +1 @@
1
- {"version":3,"file":"SentryProjectSelector.js","sourceRoot":"","sources":["../../../lib/Steps/SentryProjectSelector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,qCAAkC;AAClC,wCAA4B;AAE5B,uCAAsC;AAEtC,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,EAAtB,CAAsB,CAAC,CAAC;AAC1D,CAAC;AAED;IAA2C,yCAAQ;IAAnD;;IAuEA,CAAC;IAtEc,oCAAI,GAAjB,UAAkB,OAAgB;;;;;;wBAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBAEpB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE;4BAC7B,2DAA2D;4BAC3D,sBAAO,EAAE,EAAC;yBACX;wBAED,IACE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC;4BACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EACpC;4BACA,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;yBACH;wBAEG,eAAe,GAAG,IAAI,CAAC;6BACvB,CAAA,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA,EAApC,wBAAoC;wBACtC,eAAe,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;wBAClE,4DAA4D;wBAC5D,2EAA2E;wBAC3E,qBAAM,KAAK,CAAC,IAAI,CAAC,EAAA;;wBAFjB,4DAA4D;wBAC5D,2EAA2E;wBAC3E,SAAiB,CAAC;;4BAEA,qBAAM,IAAA,iBAAM,EAAC;4BAC7B;gCACE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAC,OAAY;oCAChD,OAAO;wCACL,IAAI,EAAE,UAAG,OAAO,CAAC,YAAY,CAAC,IAAI,gBAAM,OAAO,CAAC,IAAI,CAAE;wCACtD,KAAK,EAAE,OAAO;qCACf,CAAC;gCACJ,CAAC,CAAC;gCACF,OAAO,EAAE,uCAAuC;gCAChD,IAAI,EAAE,iBAAiB;gCACvB,IAAI,EAAE,MAAM;6BACb;yBACF,CAAC,EAAA;;wBAZF,eAAe,GAAG,SAYhB,CAAC;;4BAGL,sBAAO;4BACL,MAAM,EAAE;gCACN,IAAI,EAAE;oCACJ,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,IAAI,CAAC;iCACpD;gCACD,GAAG,EAAE;oCACH,MAAM,EAAE,CAAC,CAAC,GAAG,CACX,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;oCACD,MAAM,EAAE,CAAC,CAAC,GAAG,CACX,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;iCACF;gCACD,YAAY,EAAE;oCACZ,IAAI,EAAE,CAAC,CAAC,GAAG,CACT,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;iCACF;gCACD,OAAO,EAAE;oCACP,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,oBAAoB,EAAE,IAAI,CAAC;oCACtD,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,sBAAsB,EAAE,IAAI,CAAC;iCAC3D;6BACF;yBACF,EAAC;;;;KACH;IACH,4BAAC;AAAD,CAAC,AAvED,CAA2C,mBAAQ,GAuElD;AAvEY,sDAAqB","sourcesContent":["import type { Answers } from 'inquirer';\nimport { prompt } from 'inquirer';\nimport * as _ from 'lodash';\n\nimport { BaseStep } from './BaseStep';\n\nfunction sleep(n: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, n));\n}\n\nexport class SentryProjectSelector extends BaseStep {\n public async emit(answers: Answers): Promise<any> {\n this.debug(answers);\n\n if (!_.has(answers, 'wizard')) {\n // we skip this completly because the wizard wasn't running\n return {};\n }\n\n if (\n _.has(answers, 'wizard.projects') &&\n answers.wizard.projects.length === 0\n ) {\n throw new Error(\n 'No Projects found. Please create a new Project in Sentry and try again.',\n );\n }\n\n let selectedProject = null;\n if (answers.wizard.projects.length === 1) {\n selectedProject = { selectedProject: answers.wizard.projects[0] };\n // the wizard CLI closes too quickly when we skip the prompt\n // as it will cause the UI to be stuck saying Waiting for wizard to connect\n await sleep(1000);\n } else {\n selectedProject = await prompt([\n {\n choices: answers.wizard.projects.map((project: any) => {\n return {\n name: `${project.organization.name} / ${project.slug}`,\n value: project,\n };\n }),\n message: 'Please select your project in Sentry:',\n name: 'selectedProject',\n type: 'list',\n },\n ]);\n }\n\n return {\n config: {\n auth: {\n token: _.get(answers, 'wizard.apiKeys.token', null),\n },\n dsn: {\n public: _.get(\n selectedProject,\n 'selectedProject.keys.0.dsn.public',\n null,\n ),\n secret: _.get(\n selectedProject,\n 'selectedProject.keys.0.dsn.secret',\n null,\n ),\n },\n organization: {\n slug: _.get(\n selectedProject,\n 'selectedProject.organization.slug',\n null,\n ),\n },\n project: {\n id: _.get(selectedProject, 'selectedProject.id', null),\n slug: _.get(selectedProject, 'selectedProject.slug', null),\n },\n },\n };\n }\n}\n"]}
1
+ {"version":3,"file":"SentryProjectSelector.js","sourceRoot":"","sources":["../../../lib/Steps/SentryProjectSelector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,qCAAkC;AAClC,wCAA4B;AAE5B,uCAAsC;AAEtC,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,EAAtB,CAAsB,CAAC,CAAC;AAC1D,CAAC;AAED;IAA2C,yCAAQ;IAAnD;;IAuEA,CAAC;IAtEc,oCAAI,GAAjB,UAAkB,OAAgB;;;;;;wBAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBAEpB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE;4BAC7B,4DAA4D;4BAC5D,sBAAO,EAAE,EAAC;yBACX;wBAED,IACE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC;4BACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EACpC;4BACA,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;yBACH;wBAEG,eAAe,GAAG,IAAI,CAAC;6BACvB,CAAA,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA,EAApC,wBAAoC;wBACtC,eAAe,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;wBAClE,4DAA4D;wBAC5D,2EAA2E;wBAC3E,qBAAM,KAAK,CAAC,IAAI,CAAC,EAAA;;wBAFjB,4DAA4D;wBAC5D,2EAA2E;wBAC3E,SAAiB,CAAC;;4BAEA,qBAAM,IAAA,iBAAM,EAAC;4BAC7B;gCACE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAC,OAAY;oCAChD,OAAO;wCACL,IAAI,EAAE,UAAG,OAAO,CAAC,YAAY,CAAC,IAAI,gBAAM,OAAO,CAAC,IAAI,CAAE;wCACtD,KAAK,EAAE,OAAO;qCACf,CAAC;gCACJ,CAAC,CAAC;gCACF,OAAO,EAAE,uCAAuC;gCAChD,IAAI,EAAE,iBAAiB;gCACvB,IAAI,EAAE,MAAM;6BACb;yBACF,CAAC,EAAA;;wBAZF,eAAe,GAAG,SAYhB,CAAC;;4BAGL,sBAAO;4BACL,MAAM,EAAE;gCACN,IAAI,EAAE;oCACJ,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,IAAI,CAAC;iCACpD;gCACD,GAAG,EAAE;oCACH,MAAM,EAAE,CAAC,CAAC,GAAG,CACX,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;oCACD,MAAM,EAAE,CAAC,CAAC,GAAG,CACX,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;iCACF;gCACD,YAAY,EAAE;oCACZ,IAAI,EAAE,CAAC,CAAC,GAAG,CACT,eAAe,EACf,mCAAmC,EACnC,IAAI,CACL;iCACF;gCACD,OAAO,EAAE;oCACP,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,oBAAoB,EAAE,IAAI,CAAC;oCACtD,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,sBAAsB,EAAE,IAAI,CAAC;iCAC3D;6BACF;yBACF,EAAC;;;;KACH;IACH,4BAAC;AAAD,CAAC,AAvED,CAA2C,mBAAQ,GAuElD;AAvEY,sDAAqB","sourcesContent":["import type { Answers } from 'inquirer';\nimport { prompt } from 'inquirer';\nimport * as _ from 'lodash';\n\nimport { BaseStep } from './BaseStep';\n\nfunction sleep(n: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, n));\n}\n\nexport class SentryProjectSelector extends BaseStep {\n public async emit(answers: Answers): Promise<any> {\n this.debug(answers);\n\n if (!_.has(answers, 'wizard')) {\n // we skip this completely because the wizard wasn't running\n return {};\n }\n\n if (\n _.has(answers, 'wizard.projects') &&\n answers.wizard.projects.length === 0\n ) {\n throw new Error(\n 'No Projects found. Please create a new Project in Sentry and try again.',\n );\n }\n\n let selectedProject = null;\n if (answers.wizard.projects.length === 1) {\n selectedProject = { selectedProject: answers.wizard.projects[0] };\n // the wizard CLI closes too quickly when we skip the prompt\n // as it will cause the UI to be stuck saying Waiting for wizard to connect\n await sleep(1000);\n } else {\n selectedProject = await prompt([\n {\n choices: answers.wizard.projects.map((project: any) => {\n return {\n name: `${project.organization.name} / ${project.slug}`,\n value: project,\n };\n }),\n message: 'Please select your project in Sentry:',\n name: 'selectedProject',\n type: 'list',\n },\n ]);\n }\n\n return {\n config: {\n auth: {\n token: _.get(answers, 'wizard.apiKeys.token', null),\n },\n dsn: {\n public: _.get(\n selectedProject,\n 'selectedProject.keys.0.dsn.public',\n null,\n ),\n secret: _.get(\n selectedProject,\n 'selectedProject.keys.0.dsn.secret',\n null,\n ),\n },\n organization: {\n slug: _.get(\n selectedProject,\n 'selectedProject.organization.slug',\n null,\n ),\n },\n project: {\n id: _.get(selectedProject, 'selectedProject.id', null),\n slug: _.get(selectedProject, 'selectedProject.slug', null),\n },\n },\n };\n }\n}\n"]}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/wizard",
3
- "version": "3.31.0",
3
+ "version": "3.33.0",
4
4
  "homepage": "https://github.com/getsentry/sentry-wizard",
5
5
  "repository": "https://github.com/getsentry/sentry-wizard",
6
6
  "description": "Sentry wizard helping you to configure your project",
@@ -27,7 +27,7 @@
27
27
  "@clack/prompts": "0.7.0",
28
28
  "@sentry/cli": "^1.72.0",
29
29
  "@sentry/node": "^7.69.0",
30
- "axios": "1.6.0",
30
+ "axios": "1.7.4",
31
31
  "chalk": "^2.4.1",
32
32
  "glob": "^8.1.0",
33
33
  "inquirer": "^6.2.0",
@@ -44,6 +44,7 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@sentry-internal/eslint-config-sdk": "^7.48.0",
47
+ "@types/chai": "^4.3.17",
47
48
  "@types/glob": "^7.2.0",
48
49
  "@types/inquirer": "^0.0.43",
49
50
  "@types/jest": "^29.5.0",
@@ -62,6 +63,7 @@
62
63
  "rimraf": "^3.0.2",
63
64
  "ts-jest": "^29.1.0",
64
65
  "ts-node": "^10.9.1",
66
+ "tsx": "^3.14.0",
65
67
  "typescript": "^5.0.4"
66
68
  },
67
69
  "resolutions": {
@@ -85,6 +87,7 @@
85
87
  "fix:prettier": "prettier --write \"{lib,src,test}/**/*.ts\"",
86
88
  "fix:eslint": "eslint . --format stylish --fix",
87
89
  "test": "yarn build && jest",
90
+ "test:e2e": "yarn build && jest -c=\"./e2e-tests/jest.config.ts\" ./e2e-tests/",
88
91
  "try": "ts-node bin.ts",
89
92
  "try:uninstall": "ts-node bin.ts --uninstall",
90
93
  "test:watch": "jest --watch"
@@ -112,7 +115,8 @@
112
115
  "/dist/",
113
116
  "/node_modules/",
114
117
  "\\.d\\.(jsx?|tsx?)$",
115
- "\\.no-jest\\.(jsx?|tsx?)$"
118
+ "\\.no-jest\\.(jsx?|tsx?)$",
119
+ "/e2e-tests/"
116
120
  ],
117
121
  "testEnvironment": "node"
118
122
  },
@@ -72,10 +72,14 @@ var prompts_1 = __importDefault(require("@clack/prompts"));
72
72
  */
73
73
  function createExamplePage(options) {
74
74
  return __awaiter(this, void 0, void 0, function () {
75
- var exampleRoutePath;
75
+ var routesPath, exampleRoutePath;
76
76
  return __generator(this, function (_a) {
77
77
  switch (_a.label) {
78
78
  case 0:
79
+ routesPath = 'app/routes';
80
+ if (!fs.existsSync(routesPath)) {
81
+ fs.mkdirSync(routesPath, { recursive: true });
82
+ }
79
83
  exampleRoutePath = "app/routes/sentry-example-page.".concat(options.isTS ? 'ts' : 'js', "x");
80
84
  if (fs.existsSync(exampleRoutePath)) {
81
85
  prompts_1.default.log.warn("It seems like a sentry example page already exists (".concat(path.basename(exampleRoutePath), "). Skipping creation of example route."));
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-example.js","sourceRoot":"","sources":["../../../src/remix/sdk-example.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,yCAA6B;AAC7B,yEAAyE;AACzE,2DAAmC;AAEnC;;GAEG;AACH,SAAsB,iBAAiB,CAAC,OAMvC;;;;;;oBACO,gBAAgB,GAAG,yCACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MACzB,CAAC;oBAEJ,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;wBACnC,iBAAK,CAAC,GAAG,CAAC,IAAI,CACZ,8DAAuD,IAAI,CAAC,QAAQ,CAClE,gBAAgB,CACjB,2CAAwC,CAC1C,CAAC;wBACF,sBAAO;qBACR;oBAED,qBAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CACzB,gBAAgB,EAChB,4BAA4B,CAAC,OAAO,CAAC,CACtC,EAAA;;oBAHD,SAGC,CAAC;oBAEF,iBAAK,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAkC,gBAAgB,MAAG,CAAC,CAAC;;;;;CACvE;AA1BD,8CA0BC;AAED,SAAgB,4BAA4B,CAAC,OAM5C;IACC,IAAM,cAAc,GAAG,OAAO,CAAC,UAAU;QACvC,CAAC,CAAC,UAAG,OAAO,CAAC,GAAG,2BAAiB,OAAO,CAAC,OAAO,8BAAoB,OAAO,CAAC,SAAS,CAAE;QACvF,CAAC,CAAC,kBAAW,OAAO,CAAC,OAAO,wCAA8B,OAAO,CAAC,SAAS,CAAE,CAAC;IAEhF,OAAO,85FAqDkB,cAAc,0YAYxC,CAAC;AACF,CAAC;AA7ED,oEA6EC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\n\n/**\n * Creates an example Remix page to test Sentry\n */\nexport async function createExamplePage(options: {\n selfHosted: boolean;\n orgSlug: string;\n projectId: string;\n url: string;\n isTS: boolean;\n}) {\n const exampleRoutePath = `app/routes/sentry-example-page.${\n options.isTS ? 'ts' : 'js'\n }x`;\n\n if (fs.existsSync(exampleRoutePath)) {\n clack.log.warn(\n `It seems like a sentry example page already exists (${path.basename(\n exampleRoutePath,\n )}). Skipping creation of example route.`,\n );\n return;\n }\n\n await fs.promises.writeFile(\n exampleRoutePath,\n getSentryExamplePageContents(options),\n );\n\n clack.log.info(`Created sentry example page at ${exampleRoutePath}.`);\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n orgSlug: string;\n projectId: string;\n url: string;\n isTS?: boolean;\n}) {\n const issuesPageLink = options.selfHosted\n ? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `\nexport default function SentryExamplePage() {\n return (\n <div>\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n />\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={() => {\n throw new Error(\"Sentry Example Frontend Error\");\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"${issuesPageLink}\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/remix/\">\n https://docs.sentry.io/platforms/javascript/guides/remix/\n </a>\n </p>\n </main>\n </div>\n );\n}\n`;\n}\n"]}
1
+ {"version":3,"file":"sdk-example.js","sourceRoot":"","sources":["../../../src/remix/sdk-example.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,yCAA6B;AAC7B,yEAAyE;AACzE,2DAAmC;AAEnC;;GAEG;AACH,SAAsB,iBAAiB,CAAC,OAMvC;;;;;;oBACO,UAAU,GAAG,YAAY,CAAC;oBAEhC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;wBAC9B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;qBAC/C;oBAEK,gBAAgB,GAAG,yCACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MACzB,CAAC;oBAEJ,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;wBACnC,iBAAK,CAAC,GAAG,CAAC,IAAI,CACZ,8DAAuD,IAAI,CAAC,QAAQ,CAClE,gBAAgB,CACjB,2CAAwC,CAC1C,CAAC;wBACF,sBAAO;qBACR;oBAED,qBAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CACzB,gBAAgB,EAChB,4BAA4B,CAAC,OAAO,CAAC,CACtC,EAAA;;oBAHD,SAGC,CAAC;oBAEF,iBAAK,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAkC,gBAAgB,MAAG,CAAC,CAAC;;;;;CACvE;AAhCD,8CAgCC;AAED,SAAgB,4BAA4B,CAAC,OAM5C;IACC,IAAM,cAAc,GAAG,OAAO,CAAC,UAAU;QACvC,CAAC,CAAC,UAAG,OAAO,CAAC,GAAG,2BAAiB,OAAO,CAAC,OAAO,8BAAoB,OAAO,CAAC,SAAS,CAAE;QACvF,CAAC,CAAC,kBAAW,OAAO,CAAC,OAAO,wCAA8B,OAAO,CAAC,SAAS,CAAE,CAAC;IAEhF,OAAO,85FAqDkB,cAAc,0YAYxC,CAAC;AACF,CAAC;AA7ED,oEA6EC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\n\n/**\n * Creates an example Remix page to test Sentry\n */\nexport async function createExamplePage(options: {\n selfHosted: boolean;\n orgSlug: string;\n projectId: string;\n url: string;\n isTS: boolean;\n}) {\n const routesPath = 'app/routes';\n\n if (!fs.existsSync(routesPath)) {\n fs.mkdirSync(routesPath, { recursive: true });\n }\n\n const exampleRoutePath = `app/routes/sentry-example-page.${\n options.isTS ? 'ts' : 'js'\n }x`;\n\n if (fs.existsSync(exampleRoutePath)) {\n clack.log.warn(\n `It seems like a sentry example page already exists (${path.basename(\n exampleRoutePath,\n )}). Skipping creation of example route.`,\n );\n return;\n }\n\n await fs.promises.writeFile(\n exampleRoutePath,\n getSentryExamplePageContents(options),\n );\n\n clack.log.info(`Created sentry example page at ${exampleRoutePath}.`);\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n orgSlug: string;\n projectId: string;\n url: string;\n isTS?: boolean;\n}) {\n const issuesPageLink = options.selfHosted\n ? `${options.url}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `\nexport default function SentryExamplePage() {\n return (\n <div>\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n\n <h1 style={{ fontSize: \"4rem\", margin: \"14px 0\" }}>\n {/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}\n <svg\n style={{\n height: \"1em\",\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 200 44\"\n >\n <path\n fill=\"currentColor\"\n d=\"M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n />\n </svg>\n </h1>\n\n <p>Get started by sending us a sample error:</p>\n\n <button\n type=\"button\"\n style={{\n padding: \"12px\",\n cursor: \"pointer\",\n backgroundColor: \"#AD6CAA\",\n borderRadius: \"4px\",\n border: \"none\",\n color: \"white\",\n fontSize: \"14px\",\n margin: \"18px\",\n }}\n onClick={() => {\n throw new Error(\"Sentry Example Frontend Error\");\n }}\n >\n Throw error!\n </button>\n\n <p>\n Next, look for the error on the{\" \"}\n <a href=\"${issuesPageLink}\">Issues Page</a>.\n </p>\n <p style={{ marginTop: \"24px\" }}>\n For more information, see{\" \"}\n <a href=\"https://docs.sentry.io/platforms/javascript/guides/remix/\">\n https://docs.sentry.io/platforms/javascript/guides/remix/\n </a>\n </p>\n </main>\n </div>\n );\n}\n`;\n}\n"]}