@sentry/wizard 3.8.0 → 3.9.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 +10 -0
- package/bin.ts +14 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -1
- package/dist/lib/Helper/Logging.d.ts +1 -0
- package/dist/lib/Helper/Logging.js +2 -1
- package/dist/lib/Helper/Logging.js.map +1 -1
- package/dist/lib/Setup.js +4 -0
- package/dist/lib/Setup.js.map +1 -1
- package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/package.json +11 -7
- package/dist/src/sourcemaps/tools/sentry-cli.js +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +102 -12
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.d.ts +9 -1
- package/dist/src/sveltekit/sdk-setup.js +73 -29
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +9 -5
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +8 -0
- package/dist/src/utils/ast-utils.js +45 -0
- package/dist/src/utils/ast-utils.js.map +1 -0
- package/dist/src/utils/debug.d.ts +2 -0
- package/dist/src/utils/debug.js +51 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/test/utils/ast-utils.test.d.ts +1 -0
- package/dist/test/utils/ast-utils.test.js +21 -0
- package/dist/test/utils/ast-utils.test.js.map +1 -0
- package/lib/Helper/Logging.ts +1 -1
- package/lib/Setup.ts +5 -0
- package/lib/Steps/Integrations/ReactNative.ts +7 -3
- package/package.json +11 -7
- package/src/sourcemaps/tools/sentry-cli.ts +1 -1
- package/src/sourcemaps/tools/vite.ts +101 -12
- package/src/sveltekit/sdk-setup.ts +122 -43
- package/src/sveltekit/sveltekit-wizard.ts +12 -6
- package/src/utils/ast-utils.ts +20 -0
- package/src/utils/debug.ts +20 -0
- package/test/utils/ast-utils.test.ts +44 -0
- package/dist/src/sveltekit/sentry-cli-setup.d.ts +0 -2
- package/dist/src/sveltekit/sentry-cli-setup.js +0 -71
- package/dist/src/sveltekit/sentry-cli-setup.js.map +0 -1
- package/package-lock.json +0 -8910
- package/src/sveltekit/sentry-cli-setup.ts +0 -27
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.hasSentryContent = exports.findScriptFile = void 0;
|
|
27
|
+
var fs = __importStar(require("fs"));
|
|
28
|
+
/**
|
|
29
|
+
* Checks if a JS/TS file where we don't know its concrete file type yet exists
|
|
30
|
+
* and returns the full path to the file with the correct file type.
|
|
31
|
+
*/
|
|
32
|
+
function findScriptFile(hooksFile) {
|
|
33
|
+
var possibleFileTypes = ['.js', '.ts', '.mjs'];
|
|
34
|
+
return possibleFileTypes
|
|
35
|
+
.map(function (type) { return "".concat(hooksFile).concat(type); })
|
|
36
|
+
.find(function (file) { return fs.existsSync(file); });
|
|
37
|
+
}
|
|
38
|
+
exports.findScriptFile = findScriptFile;
|
|
39
|
+
/** Checks if a Sentry package is already mentioned in the file */
|
|
40
|
+
function hasSentryContent(mod) {
|
|
41
|
+
var imports = mod.imports.$items.map(function (i) { return i.from; });
|
|
42
|
+
return !!imports.find(function (i) { return i.startsWith('@sentry/'); });
|
|
43
|
+
}
|
|
44
|
+
exports.hasSentryContent = hasSentryContent;
|
|
45
|
+
//# sourceMappingURL=ast-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../src/utils/ast-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AAIzB;;;GAGG;AACH,SAAgB,cAAc,CAAC,SAAiB;IAC9C,IAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,iBAAiB;SACrB,GAAG,CAAC,UAAC,IAAI,IAAK,OAAA,UAAG,SAAS,SAAG,IAAI,CAAE,EAArB,CAAqB,CAAC;SACpC,IAAI,CAAC,UAAC,IAAI,IAAK,OAAA,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAnB,CAAmB,CAAC,CAAC;AACzC,CAAC;AALD,wCAKC;AAED,kEAAkE;AAClE,SAAgB,gBAAgB,CAAC,GAA4B;IAC3D,IAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAxB,CAAwB,CAAC,CAAC;AACzD,CAAC;AAHD,4CAGC","sourcesContent":["import * as fs from 'fs';\n// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { ProxifiedModule } from 'magicast';\n\n/**\n * Checks if a JS/TS file where we don't know its concrete file type yet exists\n * and returns the full path to the file with the correct file type.\n */\nexport function findScriptFile(hooksFile: string): string | undefined {\n const possibleFileTypes = ['.js', '.ts', '.mjs'];\n return possibleFileTypes\n .map((type) => `${hooksFile}${type}`)\n .find((file) => fs.existsSync(file));\n}\n\n/** Checks if a Sentry package is already mentioned in the file */\nexport function hasSentryContent(mod: ProxifiedModule<object>): boolean {\n const imports = mod.imports.$items.map((i) => i.from);\n return !!imports.find((i) => i.startsWith('@sentry/'));\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.enableDebugLogs = exports.debug = void 0;
|
|
30
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
31
|
+
var clack = __importStar(require("@clack/prompts"));
|
|
32
|
+
var chalk_1 = __importDefault(require("chalk"));
|
|
33
|
+
var Logging_1 = require("../../lib/Helper/Logging");
|
|
34
|
+
var debugEnabled = false;
|
|
35
|
+
function debug() {
|
|
36
|
+
var args = [];
|
|
37
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
38
|
+
args[_i] = arguments[_i];
|
|
39
|
+
}
|
|
40
|
+
if (!debugEnabled) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
var msg = args.map(function (a) { return (0, Logging_1.prepareMessage)(a); }).join(' ');
|
|
44
|
+
clack.log.info(chalk_1.default.dim(msg));
|
|
45
|
+
}
|
|
46
|
+
exports.debug = debug;
|
|
47
|
+
function enableDebugLogs() {
|
|
48
|
+
debugEnabled = true;
|
|
49
|
+
}
|
|
50
|
+
exports.enableDebugLogs = enableDebugLogs;
|
|
51
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../src/utils/debug.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yEAAyE;AACzE,oDAAwC;AACxC,gDAA0B;AAC1B,oDAA0D;AAE1D,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,SAAgB,KAAK;IAAC,cAAkB;SAAlB,UAAkB,EAAlB,qBAAkB,EAAlB,IAAkB;QAAlB,yBAAkB;;IACtC,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO;KACR;IAED,IAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,IAAA,wBAAc,EAAC,CAAC,CAAC,EAAjB,CAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AARD,sBAQC;AAED,SAAgB,eAAe;IAC7B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAFD,0CAEC","sourcesContent":["// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport { prepareMessage } from '../../lib/Helper/Logging';\n\nlet debugEnabled = false;\n\nexport function debug(...args: unknown[]) {\n if (!debugEnabled) {\n return;\n }\n\n const msg = args.map((a) => prepareMessage(a)).join(' ');\n\n clack.log.info(chalk.dim(msg));\n}\n\nexport function enableDebugLogs() {\n debugEnabled = true;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//@ts-ignore
|
|
4
|
+
var magicast_1 = require("magicast");
|
|
5
|
+
var ast_utils_1 = require("../../src/utils/ast-utils");
|
|
6
|
+
describe('AST utils', function () {
|
|
7
|
+
describe('hasSentryContent', function () {
|
|
8
|
+
it("returns true if a '@sentry/' import was found in the parsed module", function () {
|
|
9
|
+
var code = "\n import { sentryVitePlugin } from \"@sentry/vite-plugin\";\n import * as somethingelse from 'gs';\n\n export default {\n plugins: [sentryVitePlugin()]\n }\n ";
|
|
10
|
+
expect((0, ast_utils_1.hasSentryContent)((0, magicast_1.parseModule)(code))).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
it.each([
|
|
13
|
+
"\n import * as somethingelse from 'gs';\n export default {\n plugins: []\n }\n ",
|
|
14
|
+
"import * as somethingelse from 'gs';\n // import { sentryVitePlugin } from \"@sentry/vite-plugin\"\n export default {\n plugins: []\n }\n ",
|
|
15
|
+
"import * as thirdPartyVitePlugin from \"vite-plugin-@sentry\"\n export default {\n plugins: [thirdPartyVitePlugin()]\n }\n ",
|
|
16
|
+
])("reutrns false for modules without a valid '@sentry/' import", function (code) {
|
|
17
|
+
expect((0, ast_utils_1.hasSentryContent)((0, magicast_1.parseModule)(code))).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=ast-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-utils.test.js","sourceRoot":"","sources":["../../../test/utils/ast-utils.test.ts"],"names":[],"mappings":";;AAAA,YAAY;AACZ,qCAAuC;AACvC,uDAA6D;AAE7D,QAAQ,CAAC,WAAW,EAAE;IACpB,QAAQ,CAAC,kBAAkB,EAAE;QAC3B,EAAE,CAAC,oEAAoE,EAAE;YACvE,IAAM,IAAI,GAAG,6MAOZ,CAAC;YAEF,MAAM,CAAC,IAAA,4BAAgB,EAAC,IAAA,sBAAW,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,IAAI,CAAC;YACN,8GAKC;YACD,0KAKC;YACD,mJAIC;SACF,CAAC,CACA,6DAA6D,EAC7D,UAAC,IAAI;YACH,MAAM,CAAC,IAAA,4BAAgB,EAAC,IAAA,sBAAW,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["//@ts-ignore\nimport { parseModule } from 'magicast';\nimport { hasSentryContent } from '../../src/utils/ast-utils';\n\ndescribe('AST utils', () => {\n describe('hasSentryContent', () => {\n it(\"returns true if a '@sentry/' import was found in the parsed module\", () => {\n const code = `\n import { sentryVitePlugin } from \"@sentry/vite-plugin\";\n import * as somethingelse from 'gs';\n\n export default {\n plugins: [sentryVitePlugin()]\n }\n `;\n\n expect(hasSentryContent(parseModule(code))).toBe(true);\n });\n it.each([\n `\n import * as somethingelse from 'gs';\n export default {\n plugins: []\n }\n `,\n `import * as somethingelse from 'gs';\n // import { sentryVitePlugin } from \"@sentry/vite-plugin\"\n export default {\n plugins: []\n }\n `,\n `import * as thirdPartyVitePlugin from \"vite-plugin-@sentry\"\n export default {\n plugins: [thirdPartyVitePlugin()]\n }\n `,\n ])(\n \"reutrns false for modules without a valid '@sentry/' import\",\n (code) => {\n expect(hasSentryContent(parseModule(code))).toBe(false);\n },\n );\n });\n});\n"]}
|
package/lib/Helper/Logging.ts
CHANGED
package/lib/Setup.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as _ from 'lodash';
|
|
2
|
+
import { enableDebugLogs } from '../src/utils/debug';
|
|
2
3
|
|
|
3
4
|
import { readEnvironment } from './Helper/Env';
|
|
4
5
|
import { startWizard } from './Helper/Wizard';
|
|
@@ -7,6 +8,10 @@ import * as Step from './Steps';
|
|
|
7
8
|
export async function run(argv: any): Promise<any> {
|
|
8
9
|
const args = { ...argv, ...readEnvironment() };
|
|
9
10
|
|
|
11
|
+
if (argv.debug) {
|
|
12
|
+
enableDebugLogs();
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
if (args.uninstall === undefined) {
|
|
11
16
|
args.uninstall = false;
|
|
12
17
|
}
|
|
@@ -398,7 +398,7 @@ The snippet will create a button that, when tapped, sends a test event to Sentry
|
|
|
398
398
|
// eslint-disable-next-line no-useless-escape
|
|
399
399
|
'\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\"',
|
|
400
400
|
) +
|
|
401
|
-
'\n/bin/sh ../node_modules/@sentry/react-native/scripts/collect-modules.sh\n';
|
|
401
|
+
'\n/bin/sh -c "$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh"\n';
|
|
402
402
|
script.shellScript = JSON.stringify(code);
|
|
403
403
|
}
|
|
404
404
|
}
|
|
@@ -422,8 +422,12 @@ The snippet will create a button that, when tapped, sends a test event to Sentry
|
|
|
422
422
|
{
|
|
423
423
|
shellPath: '/bin/sh',
|
|
424
424
|
shellScript: `
|
|
425
|
+
WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
|
|
426
|
+
if [ -f "$WITH_ENVIRONMENT" ]; then
|
|
427
|
+
. "$WITH_ENVIRONMENT"
|
|
428
|
+
fi
|
|
425
429
|
export SENTRY_PROPERTIES=sentry.properties
|
|
426
|
-
[
|
|
430
|
+
[ "$SENTRY_INCLUDE_NATIVE_SOURCES" = "true" ] && INCLUDE_SOURCES_FLAG="--include-sources" || INCLUDE_SOURCES_FLAG=""
|
|
427
431
|
../node_modules/@sentry/cli/bin/sentry-cli debug-files upload "$INCLUDE_SOURCES_FLAG" "$DWARF_DSYM_FOLDER_PATH"
|
|
428
432
|
`,
|
|
429
433
|
},
|
|
@@ -509,7 +513,7 @@ export SENTRY_PROPERTIES=sentry.properties
|
|
|
509
513
|
// remove sentry properties export
|
|
510
514
|
.replace(/^export SENTRY_PROPERTIES=sentry.properties\r?\n/m, '')
|
|
511
515
|
.replace(
|
|
512
|
-
/^\/bin\/sh
|
|
516
|
+
/^\/bin\/sh .*?..\/node_modules\/@sentry\/react-native\/scripts\/collect-modules.sh"?\r?\n/m,
|
|
513
517
|
'',
|
|
514
518
|
)
|
|
515
519
|
// unwrap react-native-xcode.sh command. In case someone replaced it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.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",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"glob": "^7.1.3",
|
|
33
33
|
"inquirer": "^6.2.0",
|
|
34
34
|
"lodash": "^4.17.15",
|
|
35
|
-
"magicast": "^0.2.
|
|
35
|
+
"magicast": "^0.2.10",
|
|
36
36
|
"opn": "^5.4.0",
|
|
37
37
|
"r2": "^2.0.1",
|
|
38
38
|
"read-env": "^1.3.0",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"**/xmldom": "^0.6.0"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|
|
68
|
-
"node": ">=14.
|
|
68
|
+
"node": ">=14.18.0",
|
|
69
69
|
"npm": ">=3.10.7",
|
|
70
70
|
"yarn": ">=1.0.2"
|
|
71
71
|
},
|
|
@@ -76,15 +76,15 @@
|
|
|
76
76
|
"build": "yarn tsc",
|
|
77
77
|
"postbuild": "chmod +x ./dist/bin.js && cp -r scripts/** dist",
|
|
78
78
|
"lint": "yarn lint:prettier && yarn lint:eslint",
|
|
79
|
-
"lint:prettier": "prettier --check \"{lib,src}/**/*.ts\"",
|
|
79
|
+
"lint:prettier": "prettier --check \"{lib,src,test}/**/*.ts\"",
|
|
80
80
|
"lint:eslint": "eslint . --cache --format stylish",
|
|
81
81
|
"fix": "yarn fix:eslint && yarn fix:prettier",
|
|
82
|
-
"fix:prettier": "prettier --write \"{lib,src}/**/*.ts\"",
|
|
82
|
+
"fix:prettier": "prettier --write \"{lib,src,test}/**/*.ts\"",
|
|
83
83
|
"fix:eslint": "eslint . --format stylish --fix",
|
|
84
84
|
"test": "yarn build && jest",
|
|
85
85
|
"try": "ts-node bin.ts",
|
|
86
86
|
"try:uninstall": "ts-node bin.ts --uninstall",
|
|
87
|
-
"test:watch": "jest --watch
|
|
87
|
+
"test:watch": "jest --watch"
|
|
88
88
|
},
|
|
89
89
|
"jest": {
|
|
90
90
|
"collectCoverage": true,
|
|
@@ -114,5 +114,9 @@
|
|
|
114
114
|
"testEnvironment": "node"
|
|
115
115
|
},
|
|
116
116
|
"author": "Sentry",
|
|
117
|
-
"license": "MIT"
|
|
117
|
+
"license": "MIT",
|
|
118
|
+
"volta": {
|
|
119
|
+
"node": "14.18.3",
|
|
120
|
+
"yarn": "1.22.19"
|
|
121
|
+
}
|
|
118
122
|
}
|
|
@@ -174,7 +174,7 @@ async function askShouldAddToBuildCommand(): Promise<boolean> {
|
|
|
174
174
|
{
|
|
175
175
|
label: 'Yes',
|
|
176
176
|
value: true,
|
|
177
|
-
hint: 'This will modify your prod build
|
|
177
|
+
hint: 'This will modify your prod build command',
|
|
178
178
|
},
|
|
179
179
|
{ label: 'No', value: false },
|
|
180
180
|
],
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
2
2
|
import clack, { select } from '@clack/prompts';
|
|
3
|
+
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
4
|
+
import { generateCode, parseModule } from 'magicast';
|
|
5
|
+
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
6
|
+
import { addVitePlugin } from 'magicast/helpers';
|
|
7
|
+
|
|
8
|
+
import * as Sentry from '@sentry/node';
|
|
9
|
+
|
|
3
10
|
import chalk from 'chalk';
|
|
4
11
|
import {
|
|
5
12
|
abortIfCancelled,
|
|
@@ -13,6 +20,11 @@ import {
|
|
|
13
20
|
SourceMapUploadToolConfigurationFunction,
|
|
14
21
|
SourceMapUploadToolConfigurationOptions,
|
|
15
22
|
} from './types';
|
|
23
|
+
import { findScriptFile, hasSentryContent } from '../../utils/ast-utils';
|
|
24
|
+
|
|
25
|
+
import * as path from 'path';
|
|
26
|
+
import * as fs from 'fs';
|
|
27
|
+
import { debug } from '../../utils/debug';
|
|
16
28
|
|
|
17
29
|
const getCodeSnippet = (options: SourceMapUploadToolConfigurationOptions) =>
|
|
18
30
|
chalk.gray(`
|
|
@@ -48,21 +60,98 @@ export const configureVitePlugin: SourceMapUploadToolConfigurationFunction =
|
|
|
48
60
|
),
|
|
49
61
|
});
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
const viteConfigPath = findScriptFile(
|
|
64
|
+
path.resolve(process.cwd(), 'vite.config'),
|
|
53
65
|
);
|
|
54
66
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
let successfullyAdded = false;
|
|
68
|
+
if (viteConfigPath) {
|
|
69
|
+
successfullyAdded = await addVitePluginToConfig(viteConfigPath, options);
|
|
70
|
+
} else {
|
|
71
|
+
Sentry.setTag('ast-mod-fail-reason', 'config-not-found');
|
|
72
|
+
}
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
if (successfullyAdded) {
|
|
75
|
+
Sentry.setTag('ast-mod', 'success');
|
|
76
|
+
} else {
|
|
77
|
+
Sentry.setTag('ast-mod', 'fail');
|
|
78
|
+
await showCopyPasteInstructions(
|
|
79
|
+
path.basename(viteConfigPath || 'vite.config.js'),
|
|
80
|
+
options,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
66
83
|
|
|
67
84
|
await addDotEnvSentryBuildPluginFile(options.authToken);
|
|
68
85
|
};
|
|
86
|
+
|
|
87
|
+
async function addVitePluginToConfig(
|
|
88
|
+
viteConfigPath: string,
|
|
89
|
+
options: SourceMapUploadToolConfigurationOptions,
|
|
90
|
+
): Promise<boolean> {
|
|
91
|
+
try {
|
|
92
|
+
const prettyViteConfigFilename = chalk.cyan(path.basename(viteConfigPath));
|
|
93
|
+
|
|
94
|
+
const viteConfigContent = (
|
|
95
|
+
await fs.promises.readFile(viteConfigPath)
|
|
96
|
+
).toString();
|
|
97
|
+
|
|
98
|
+
const mod = parseModule(viteConfigContent);
|
|
99
|
+
|
|
100
|
+
if (hasSentryContent(mod)) {
|
|
101
|
+
clack.log.warn(
|
|
102
|
+
`File ${prettyViteConfigFilename} already contains Sentry code.
|
|
103
|
+
Please follow the instruction below`,
|
|
104
|
+
);
|
|
105
|
+
Sentry.setTag('ast-mod-fail-reason', 'has-sentry-content');
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const { orgSlug: org, projectSlug: project, selfHosted, url } = options;
|
|
110
|
+
|
|
111
|
+
addVitePlugin(mod, {
|
|
112
|
+
imported: 'sentryVitePlugin',
|
|
113
|
+
from: '@sentry/vite-plugin',
|
|
114
|
+
constructor: 'sentryVitePlugin',
|
|
115
|
+
options: {
|
|
116
|
+
org,
|
|
117
|
+
project,
|
|
118
|
+
...(selfHosted && { url }),
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const code = generateCode(mod.$ast).code;
|
|
123
|
+
|
|
124
|
+
await fs.promises.writeFile(viteConfigPath, code);
|
|
125
|
+
|
|
126
|
+
clack.log.success(
|
|
127
|
+
`Added the Sentry Vite plugin to ${prettyViteConfigFilename}`,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return true;
|
|
131
|
+
} catch (e) {
|
|
132
|
+
debug(e);
|
|
133
|
+
Sentry.setTag('ast-mod-fail-reason', 'insertion-fail');
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function showCopyPasteInstructions(
|
|
139
|
+
viteConfigFilename: string,
|
|
140
|
+
options: SourceMapUploadToolConfigurationOptions,
|
|
141
|
+
) {
|
|
142
|
+
clack.log.step(
|
|
143
|
+
`Add the following code to your ${chalk.cyan(viteConfigFilename)} file:`,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Intentionally logging directly to console here so that the code can be copied/pasted directly
|
|
147
|
+
// eslint-disable-next-line no-console
|
|
148
|
+
console.log(getCodeSnippet(options));
|
|
149
|
+
|
|
150
|
+
await abortIfCancelled(
|
|
151
|
+
select({
|
|
152
|
+
message: 'Did you copy the snippet above?',
|
|
153
|
+
options: [{ label: 'Yes, continue!', value: true }],
|
|
154
|
+
initialValue: true,
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
@@ -13,7 +13,9 @@ import { builders, generateCode, loadFile, parseModule } from 'magicast';
|
|
|
13
13
|
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
14
14
|
import { addVitePlugin } from 'magicast/helpers';
|
|
15
15
|
import { getClientHooksTemplate, getServerHooksTemplate } from './templates';
|
|
16
|
-
import { isUsingTypeScript } from '../utils/clack-utils';
|
|
16
|
+
import { abortIfCancelled, isUsingTypeScript } from '../utils/clack-utils';
|
|
17
|
+
import { debug } from '../utils/debug';
|
|
18
|
+
import { findScriptFile, hasSentryContent } from '../utils/ast-utils';
|
|
17
19
|
|
|
18
20
|
const SVELTE_CONFIG_FILE = 'svelte.config.js';
|
|
19
21
|
|
|
@@ -29,20 +31,30 @@ export type PartialSvelteConfig = {
|
|
|
29
31
|
};
|
|
30
32
|
};
|
|
31
33
|
|
|
34
|
+
type ProjectInfo = {
|
|
35
|
+
dsn: string;
|
|
36
|
+
org: string;
|
|
37
|
+
project: string;
|
|
38
|
+
selfHosted: boolean;
|
|
39
|
+
url: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
32
42
|
export async function createOrMergeSvelteKitFiles(
|
|
33
|
-
|
|
43
|
+
projectInfo: ProjectInfo,
|
|
34
44
|
svelteConfig: PartialSvelteConfig,
|
|
35
45
|
): Promise<void> {
|
|
36
46
|
const { clientHooksPath, serverHooksPath } = getHooksConfigDirs(svelteConfig);
|
|
37
47
|
|
|
38
48
|
// full file paths with correct file ending (or undefined if not found)
|
|
39
|
-
const originalClientHooksFile =
|
|
40
|
-
const originalServerHooksFile =
|
|
49
|
+
const originalClientHooksFile = findScriptFile(clientHooksPath);
|
|
50
|
+
const originalServerHooksFile = findScriptFile(serverHooksPath);
|
|
41
51
|
|
|
42
|
-
const viteConfig =
|
|
52
|
+
const viteConfig = findScriptFile(path.resolve(process.cwd(), 'vite.config'));
|
|
43
53
|
|
|
44
54
|
const fileEnding = isUsingTypeScript() ? 'ts' : 'js';
|
|
45
55
|
|
|
56
|
+
const { dsn } = projectInfo;
|
|
57
|
+
|
|
46
58
|
if (!originalClientHooksFile) {
|
|
47
59
|
clack.log.info('No client hooks file found, creating a new one.');
|
|
48
60
|
await createNewHooksFile(`${clientHooksPath}.${fileEnding}`, 'client', dsn);
|
|
@@ -60,7 +72,7 @@ export async function createOrMergeSvelteKitFiles(
|
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
if (viteConfig) {
|
|
63
|
-
await modifyViteConfig(viteConfig);
|
|
75
|
+
await modifyViteConfig(viteConfig, projectInfo);
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
|
|
@@ -91,16 +103,6 @@ function getHooksConfigDirs(svelteConfig: PartialSvelteConfig): {
|
|
|
91
103
|
};
|
|
92
104
|
}
|
|
93
105
|
|
|
94
|
-
/**
|
|
95
|
-
* Checks if a hooks file exists and returns the full path to the file with the correct file type.
|
|
96
|
-
*/
|
|
97
|
-
function findHooksFile(hooksFile: string): string | undefined {
|
|
98
|
-
const possibleFileTypes = ['.js', '.ts', '.mjs'];
|
|
99
|
-
return possibleFileTypes
|
|
100
|
-
.map((type) => `${hooksFile}${type}`)
|
|
101
|
-
.find((file) => fs.existsSync(file));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
106
|
/**
|
|
105
107
|
* Reads the template, replaces the dsn placeholder with the actual dsn and writes the file to @param hooksFileDest
|
|
106
108
|
*/
|
|
@@ -137,9 +139,15 @@ async function mergeHooksFile(
|
|
|
137
139
|
dsn: string,
|
|
138
140
|
): Promise<void> {
|
|
139
141
|
const originalHooksMod = await loadFile(hooksFile);
|
|
140
|
-
if (hasSentryContent(
|
|
142
|
+
if (hasSentryContent(originalHooksMod)) {
|
|
141
143
|
// We don't want to mess with files that already have Sentry content.
|
|
142
144
|
// Let's just bail out at this point.
|
|
145
|
+
clack.log.warn(
|
|
146
|
+
`File ${chalk.cyan(
|
|
147
|
+
path.basename(hooksFile),
|
|
148
|
+
)} already contains Sentry code.
|
|
149
|
+
Skipping adding Sentry functionality to.`,
|
|
150
|
+
);
|
|
143
151
|
return;
|
|
144
152
|
}
|
|
145
153
|
|
|
@@ -347,20 +355,6 @@ function wrapHandle(mod: ProxifiedModule<any>): void {
|
|
|
347
355
|
}
|
|
348
356
|
}
|
|
349
357
|
|
|
350
|
-
/** Checks if the Sentry SvelteKit SDK is already mentioned in the file */
|
|
351
|
-
function hasSentryContent(fileName: string, fileContent: string): boolean {
|
|
352
|
-
if (fileContent.includes('@sentry/sveltekit')) {
|
|
353
|
-
clack.log.warn(
|
|
354
|
-
`File ${chalk.cyan(path.basename(fileName))} already contains Sentry code.
|
|
355
|
-
Skipping adding Sentry functionality to ${chalk.cyan(
|
|
356
|
-
path.basename(fileName),
|
|
357
|
-
)}.`,
|
|
358
|
-
);
|
|
359
|
-
return true;
|
|
360
|
-
}
|
|
361
|
-
return false;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
358
|
export async function loadSvelteConfig(): Promise<PartialSvelteConfig> {
|
|
365
359
|
const configFilePath = path.join(process.cwd(), SVELTE_CONFIG_FILE);
|
|
366
360
|
|
|
@@ -392,28 +386,113 @@ Please make sure, you're running this wizard with Node 16 or newer`);
|
|
|
392
386
|
}
|
|
393
387
|
}
|
|
394
388
|
|
|
395
|
-
async function modifyViteConfig(
|
|
389
|
+
async function modifyViteConfig(
|
|
390
|
+
viteConfigPath: string,
|
|
391
|
+
projectInfo: ProjectInfo,
|
|
392
|
+
): Promise<void> {
|
|
396
393
|
const viteConfigContent = (
|
|
397
394
|
await fs.promises.readFile(viteConfigPath, 'utf-8')
|
|
398
395
|
).toString();
|
|
399
396
|
|
|
400
|
-
|
|
401
|
-
|
|
397
|
+
const { org, project, url, selfHosted } = projectInfo;
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
const viteModule = parseModule(viteConfigContent);
|
|
401
|
+
|
|
402
|
+
if (hasSentryContent(viteModule)) {
|
|
403
|
+
clack.log.warn(
|
|
404
|
+
`File ${chalk.cyan(
|
|
405
|
+
path.basename(viteConfigPath),
|
|
406
|
+
)} already contains Sentry code.
|
|
407
|
+
Skipping adding Sentry functionality to.`,
|
|
408
|
+
);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
addVitePlugin(viteModule, {
|
|
413
|
+
imported: 'sentrySvelteKit',
|
|
414
|
+
from: '@sentry/sveltekit',
|
|
415
|
+
constructor: 'sentrySvelteKit',
|
|
416
|
+
options: {
|
|
417
|
+
sourceMapsUploadOptions: {
|
|
418
|
+
org,
|
|
419
|
+
project,
|
|
420
|
+
...(selfHosted && { url }),
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
index: 0,
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
const code = generateCode(viteModule.$ast).code;
|
|
427
|
+
|
|
428
|
+
await fs.promises.writeFile(viteConfigPath, code);
|
|
429
|
+
} catch (e) {
|
|
430
|
+
debug(e);
|
|
431
|
+
await showFallbackViteCopyPasteSnippet(
|
|
432
|
+
viteConfigPath,
|
|
433
|
+
getViteConfigCodeSnippet(org, project, selfHosted, url),
|
|
434
|
+
);
|
|
402
435
|
}
|
|
436
|
+
}
|
|
403
437
|
|
|
404
|
-
|
|
438
|
+
async function showFallbackViteCopyPasteSnippet(
|
|
439
|
+
viteConfigPath: string,
|
|
440
|
+
codeSnippet: string,
|
|
441
|
+
) {
|
|
442
|
+
const viteConfigFilename = path.basename(viteConfigPath);
|
|
405
443
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
444
|
+
clack.log.warning(
|
|
445
|
+
`Couldn't automatically modify your ${chalk.cyan(viteConfigFilename)}
|
|
446
|
+
${chalk.dim(`This sometimes happens when we encounter more complex vite configs.
|
|
447
|
+
It may not seem like it but sometimes our magical powers are limited ;)`)}`,
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
clack.log.info("But don't worry - it's super easy to do this yourself!");
|
|
412
451
|
|
|
413
|
-
|
|
414
|
-
|
|
452
|
+
clack.log.step(
|
|
453
|
+
`Add the following code to your ${chalk.cyan(viteConfigFilename)}:`,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
// Intentionally logging to console here for easier copy/pasting
|
|
457
|
+
// eslint-disable-next-line no-console
|
|
458
|
+
console.log(codeSnippet);
|
|
459
|
+
|
|
460
|
+
await abortIfCancelled(
|
|
461
|
+
clack.select({
|
|
462
|
+
message: 'Did you copy the snippet above?',
|
|
463
|
+
options: [
|
|
464
|
+
{ label: 'Yes!', value: true, hint: "Great, that's already it!" },
|
|
465
|
+
],
|
|
466
|
+
initialValue: true,
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
415
469
|
}
|
|
416
470
|
|
|
471
|
+
const getViteConfigCodeSnippet = (
|
|
472
|
+
org: string,
|
|
473
|
+
project: string,
|
|
474
|
+
selfHosted: boolean,
|
|
475
|
+
url: string,
|
|
476
|
+
) =>
|
|
477
|
+
chalk.gray(`
|
|
478
|
+
import { sveltekit } from '@sveltejs/kit/vite';
|
|
479
|
+
import { defineConfig } from 'vite';
|
|
480
|
+
${chalk.greenBright("import { sentrySvelteKit } from '@sentry/sveltekit'")}
|
|
481
|
+
|
|
482
|
+
export default defineConfig({
|
|
483
|
+
plugins: [
|
|
484
|
+
// Make sure \`sentrySvelteKit\` is registered before \`sveltekit\`
|
|
485
|
+
${chalk.greenBright(`sentrySvelteKit({
|
|
486
|
+
sourceMapsUploadOptions: {
|
|
487
|
+
org: '${org}',
|
|
488
|
+
project: '${project}',${selfHosted ? `\n url: '${url}',` : ''}
|
|
489
|
+
}
|
|
490
|
+
}),`)}
|
|
491
|
+
sveltekit(),
|
|
492
|
+
]
|
|
493
|
+
});
|
|
494
|
+
`);
|
|
495
|
+
|
|
417
496
|
/**
|
|
418
497
|
* We want to insert the init call on top of the file but after all import statements
|
|
419
498
|
*/
|