@sentry/wizard 3.11.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/package.json +1 -1
- package/dist/src/android/android-wizard.js +8 -0
- package/dist/src/android/android-wizard.js.map +1 -1
- package/dist/src/android/code-tools.d.ts +8 -0
- package/dist/src/android/code-tools.js +20 -8
- package/dist/src/android/code-tools.js.map +1 -1
- package/dist/src/android/gradle.js +6 -1
- package/dist/src/android/gradle.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +36 -111
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sourcemaps/tools/webpack.d.ts +6 -1
- package/dist/src/sourcemaps/tools/webpack.js +290 -25
- package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +2 -2
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +7 -3
- package/dist/src/utils/ast-utils.js +20 -5
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +52 -0
- package/dist/src/utils/clack-utils.js +169 -12
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/test/android/code-tools.test.d.ts +1 -0
- package/dist/test/android/code-tools.test.js +34 -0
- package/dist/test/android/code-tools.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/webpack.test.js +179 -0
- package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -0
- package/dist/test/utils/ast-utils.test.js +42 -7
- package/dist/test/utils/ast-utils.test.js.map +1 -1
- package/dist/test/utils/clack-utils.test.d.ts +1 -0
- package/dist/test/utils/clack-utils.test.js +200 -0
- package/dist/test/utils/clack-utils.test.js.map +1 -0
- package/package.json +1 -1
- package/src/android/android-wizard.ts +8 -0
- package/src/android/code-tools.ts +21 -7
- package/src/android/gradle.ts +6 -1
- package/src/sourcemaps/tools/vite.ts +22 -88
- package/src/sourcemaps/tools/webpack.ts +369 -30
- package/src/sveltekit/sdk-setup.ts +6 -2
- package/src/utils/ast-utils.ts +23 -7
- package/src/utils/clack-utils.ts +150 -2
- package/test/android/code-tools.test.ts +49 -0
- package/test/sourcemaps/tools/webpack.test.ts +303 -0
- package/test/utils/ast-utils.test.ts +28 -9
- package/test/utils/clack-utils.test.ts +142 -0
|
@@ -0,0 +1,179 @@
|
|
|
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
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;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
var fs = __importStar(require("fs"));
|
|
63
|
+
var webpack_1 = require("../../../src/sourcemaps/tools/webpack");
|
|
64
|
+
function updateFileContent(content) {
|
|
65
|
+
fileContent = content;
|
|
66
|
+
}
|
|
67
|
+
var fileContent = '';
|
|
68
|
+
jest.mock('@clack/prompts', function () {
|
|
69
|
+
return {
|
|
70
|
+
log: {
|
|
71
|
+
info: jest.fn(),
|
|
72
|
+
success: jest.fn(),
|
|
73
|
+
},
|
|
74
|
+
select: jest.fn().mockImplementation(function () { return Promise.resolve(true); }),
|
|
75
|
+
isCancel: jest.fn().mockReturnValue(false),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
jest
|
|
79
|
+
.spyOn(fs.promises, 'readFile')
|
|
80
|
+
.mockImplementation(function () { return Promise.resolve(fileContent); });
|
|
81
|
+
var writeFileSpy = jest
|
|
82
|
+
.spyOn(fs.promises, 'writeFile')
|
|
83
|
+
.mockImplementation(function () { return Promise.resolve(void 0); });
|
|
84
|
+
var noSourcemapNoPluginsPojo = "module.exports = {\n entry: \"./src/index.js\",\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};";
|
|
85
|
+
var noSourcemapNoPluginsPojoResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};";
|
|
86
|
+
var noSourcemapsNoPluginsId = "const config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};\n\nmodule.exports = config;";
|
|
87
|
+
var noSourcemapsNoPluginsIdResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;";
|
|
88
|
+
var hiddenSourcemapNoPluginsId = "const config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"hidden-cheap-source-map\",\n};\n\nmodule.exports = config;\n ";
|
|
89
|
+
var hiddenSourcemapNoPluginsIdResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"hidden-source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;";
|
|
90
|
+
var arbitrarySourcemapNoPluginsId = "\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: getSourcemapSetting(),\n};\n\nmodule.exports = config;\n ";
|
|
91
|
+
var arbitrarySourcemapNoPluginsIdResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;";
|
|
92
|
+
var noSourcemapUndefinedPluginsPojo = "module.exports = {\n entry: \"./src/index.js\",\n plugins: undefined,\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};";
|
|
93
|
+
var noSourcemapUndefinedPluginsPojoResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })],\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\"\n};";
|
|
94
|
+
var noSourcemapPluginsPojo = "module.exports = {\n entry: \"./src/index.js\",\n plugins: [\n new HtmlWebpackPlugin(),\n new MiniCssExtractPlugin(),\n ],\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};";
|
|
95
|
+
var noSourcemapPluginsPojoResult = "const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin(), sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })],\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\"\n};";
|
|
96
|
+
describe('modifyWebpackConfig', function () {
|
|
97
|
+
afterEach(function () {
|
|
98
|
+
fileContent = '';
|
|
99
|
+
jest.clearAllMocks();
|
|
100
|
+
});
|
|
101
|
+
it.each([
|
|
102
|
+
[
|
|
103
|
+
'no sourcemap option, no plugins, object',
|
|
104
|
+
noSourcemapNoPluginsPojo,
|
|
105
|
+
noSourcemapNoPluginsPojoResult,
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
'no sourcemap option, no plugins, identifier',
|
|
109
|
+
noSourcemapsNoPluginsId,
|
|
110
|
+
noSourcemapsNoPluginsIdResult,
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
'hidden sourcemap option, no plugins, identifier',
|
|
114
|
+
hiddenSourcemapNoPluginsId,
|
|
115
|
+
hiddenSourcemapNoPluginsIdResult,
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
'arbitrary sourcemap option, no plugins, identifier',
|
|
119
|
+
arbitrarySourcemapNoPluginsId,
|
|
120
|
+
arbitrarySourcemapNoPluginsIdResult,
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
'no sourcemap option, plugins, object',
|
|
124
|
+
noSourcemapUndefinedPluginsPojo,
|
|
125
|
+
noSourcemapUndefinedPluginsPojoResult,
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
'no sourcemap option, plugins, object',
|
|
129
|
+
noSourcemapPluginsPojo,
|
|
130
|
+
noSourcemapPluginsPojoResult,
|
|
131
|
+
],
|
|
132
|
+
])('adds plugin and source maps emission to the webpack config (%s)', function (_, originalCode, expectedCode) { return __awaiter(void 0, void 0, void 0, function () {
|
|
133
|
+
var addedCode, _a, fileContent;
|
|
134
|
+
return __generator(this, function (_b) {
|
|
135
|
+
switch (_b.label) {
|
|
136
|
+
case 0:
|
|
137
|
+
updateFileContent(originalCode);
|
|
138
|
+
return [4 /*yield*/, (0, webpack_1.modifyWebpackConfig)('', {
|
|
139
|
+
authToken: '',
|
|
140
|
+
orgSlug: 'my-org',
|
|
141
|
+
projectSlug: 'my-project',
|
|
142
|
+
selfHosted: false,
|
|
143
|
+
url: 'https://sentry.io/',
|
|
144
|
+
})];
|
|
145
|
+
case 1:
|
|
146
|
+
addedCode = _b.sent();
|
|
147
|
+
expect(writeFileSpy).toHaveBeenCalledTimes(1);
|
|
148
|
+
_a = writeFileSpy.mock.calls[0], fileContent = _a[1];
|
|
149
|
+
expect(fileContent).toBe(expectedCode);
|
|
150
|
+
expect(addedCode).toBe(true);
|
|
151
|
+
return [2 /*return*/];
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}); });
|
|
155
|
+
it('adds the url parameter to the webpack plugin options if self-hosted', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
156
|
+
var addedCode, _a, fileContent;
|
|
157
|
+
return __generator(this, function (_b) {
|
|
158
|
+
switch (_b.label) {
|
|
159
|
+
case 0:
|
|
160
|
+
updateFileContent(noSourcemapNoPluginsPojo);
|
|
161
|
+
return [4 /*yield*/, (0, webpack_1.modifyWebpackConfig)('', {
|
|
162
|
+
authToken: '',
|
|
163
|
+
orgSlug: 'my-org',
|
|
164
|
+
projectSlug: 'my-project',
|
|
165
|
+
selfHosted: true,
|
|
166
|
+
url: 'https://santry.io/',
|
|
167
|
+
})];
|
|
168
|
+
case 1:
|
|
169
|
+
addedCode = _b.sent();
|
|
170
|
+
expect(writeFileSpy).toHaveBeenCalledTimes(1);
|
|
171
|
+
_a = writeFileSpy.mock.calls[0], fileContent = _a[1];
|
|
172
|
+
expect(fileContent).toContain('url: "https://santry.io/"');
|
|
173
|
+
expect(addedCode).toBe(true);
|
|
174
|
+
return [2 /*return*/];
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}); });
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=webpack.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack.test.js","sourceRoot":"","sources":["../../../../test/sourcemaps/tools/webpack.test.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\n\nimport { modifyWebpackConfig } from '../../../src/sourcemaps/tools/webpack';\n\nfunction updateFileContent(content: string): void {\n fileContent = content;\n}\n\nlet fileContent = '';\n\njest.mock('@clack/prompts', () => {\n return {\n log: {\n info: jest.fn(),\n success: jest.fn(),\n },\n select: jest.fn().mockImplementation(() => Promise.resolve(true)),\n isCancel: jest.fn().mockReturnValue(false),\n };\n});\n\njest\n .spyOn(fs.promises, 'readFile')\n .mockImplementation(() => Promise.resolve(fileContent));\n\nconst writeFileSpy = jest\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.resolve(void 0));\n\nconst noSourcemapNoPluginsPojo = `module.exports = {\n entry: \"./src/index.js\",\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};`;\n\nconst noSourcemapNoPluginsPojoResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};`;\n\nconst noSourcemapsNoPluginsId = `const config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};\n\nmodule.exports = config;`;\n\nconst noSourcemapsNoPluginsIdResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;`;\n\nconst hiddenSourcemapNoPluginsId = `const config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"hidden-cheap-source-map\",\n};\n\nmodule.exports = config;\n `;\nconst hiddenSourcemapNoPluginsIdResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"hidden-source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;`;\n\nconst arbitrarySourcemapNoPluginsId = `\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: getSourcemapSetting(),\n};\n\nmodule.exports = config;\n `;\nconst arbitrarySourcemapNoPluginsIdResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nconst config = {\n entry: \"./src/index.js\",\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })]\n};\n\nmodule.exports = config;`;\n\nconst noSourcemapUndefinedPluginsPojo = `module.exports = {\n entry: \"./src/index.js\",\n plugins: undefined,\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};`;\n\nconst noSourcemapUndefinedPluginsPojoResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n plugins: [sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })],\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\"\n};`;\n\nconst noSourcemapPluginsPojo = `module.exports = {\n entry: \"./src/index.js\",\n plugins: [\n new HtmlWebpackPlugin(),\n new MiniCssExtractPlugin(),\n ],\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n};`;\n\nconst noSourcemapPluginsPojoResult = `const {\n sentryWebpackPlugin\n} = require(\"@sentry/webpack-plugin\");\n\nmodule.exports = {\n entry: \"./src/index.js\",\n\n plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin(), sentryWebpackPlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"my-org\",\n project: \"my-project\"\n })],\n\n output: {\n filename: \"main.js\",\n path: path.resolve(__dirname, \"build\"),\n },\n\n devtool: \"source-map\"\n};`;\n\ndescribe('modifyWebpackConfig', () => {\n afterEach(() => {\n fileContent = '';\n jest.clearAllMocks();\n });\n\n it.each([\n [\n 'no sourcemap option, no plugins, object',\n noSourcemapNoPluginsPojo,\n noSourcemapNoPluginsPojoResult,\n ],\n [\n 'no sourcemap option, no plugins, identifier',\n noSourcemapsNoPluginsId,\n noSourcemapsNoPluginsIdResult,\n ],\n [\n 'hidden sourcemap option, no plugins, identifier',\n hiddenSourcemapNoPluginsId,\n hiddenSourcemapNoPluginsIdResult,\n ],\n [\n 'arbitrary sourcemap option, no plugins, identifier',\n arbitrarySourcemapNoPluginsId,\n arbitrarySourcemapNoPluginsIdResult,\n ],\n [\n 'no sourcemap option, plugins, object',\n noSourcemapUndefinedPluginsPojo,\n noSourcemapUndefinedPluginsPojoResult,\n ],\n [\n 'no sourcemap option, plugins, object',\n noSourcemapPluginsPojo,\n noSourcemapPluginsPojoResult,\n ],\n ])(\n 'adds plugin and source maps emission to the webpack config (%s)',\n async (_, originalCode, expectedCode) => {\n updateFileContent(originalCode);\n\n // updateFileContent(originalCode);\n const addedCode = await modifyWebpackConfig('', {\n authToken: '',\n orgSlug: 'my-org',\n projectSlug: 'my-project',\n selfHosted: false,\n url: 'https://sentry.io/',\n });\n\n expect(writeFileSpy).toHaveBeenCalledTimes(1);\n const [[, fileContent]] = writeFileSpy.mock.calls;\n expect(fileContent).toBe(expectedCode);\n expect(addedCode).toBe(true);\n },\n );\n\n it('adds the url parameter to the webpack plugin options if self-hosted', async () => {\n updateFileContent(noSourcemapNoPluginsPojo);\n\n const addedCode = await modifyWebpackConfig('', {\n authToken: '',\n orgSlug: 'my-org',\n projectSlug: 'my-project',\n selfHosted: true,\n url: 'https://santry.io/',\n });\n\n expect(writeFileSpy).toHaveBeenCalledTimes(1);\n const [[, fileContent]] = writeFileSpy.mock.calls;\n expect(fileContent).toContain('url: \"https://santry.io/\"');\n expect(addedCode).toBe(true);\n });\n});\n"]}
|
|
@@ -1,20 +1,55 @@
|
|
|
1
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
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//@ts-ignore
|
|
4
|
-
var magicast_1 = require("magicast");
|
|
5
26
|
var ast_utils_1 = require("../../src/utils/ast-utils");
|
|
27
|
+
var recast = __importStar(require("recast"));
|
|
6
28
|
describe('AST utils', function () {
|
|
7
29
|
describe('hasSentryContent', function () {
|
|
8
|
-
it(
|
|
9
|
-
|
|
10
|
-
|
|
30
|
+
it.each([
|
|
31
|
+
"\n const { sentryVitePlugin } = require(\"@sentry/vite-plugin\");\n const somethingelse = require('gs');\n ",
|
|
32
|
+
"\n import { sentryVitePlugin } from \"@sentry/vite-plugin\";\n import * as somethingelse from 'gs';\n\n export default {\n plugins: [sentryVitePlugin()]\n }\n ",
|
|
33
|
+
])("returns true if a require('@sentry/') call was found in the parsed module", function (code) {
|
|
34
|
+
// recast.parse returns a Program node (or fails) but it's badly typed as any
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
36
|
+
var program = recast.parse(code)
|
|
37
|
+
.program;
|
|
38
|
+
expect((0, ast_utils_1.hasSentryContent)(program)).toBe(true);
|
|
11
39
|
});
|
|
12
40
|
it.each([
|
|
41
|
+
"const whatever = require('something')",
|
|
42
|
+
"// const {sentryWebpackPlugin} = require('@sentry/webpack-plugin')",
|
|
43
|
+
"const {sAntryWebpackPlugin} = require('webpack-plugin-@sentry')",
|
|
13
44
|
"\n import * as somethingelse from 'gs';\n export default {\n plugins: []\n }\n ",
|
|
14
45
|
"import * as somethingelse from 'gs';\n // import { sentryVitePlugin } from \"@sentry/vite-plugin\"\n export default {\n plugins: []\n }\n ",
|
|
15
46
|
"import * as thirdPartyVitePlugin from \"vite-plugin-@sentry\"\n export default {\n plugins: [thirdPartyVitePlugin()]\n }\n ",
|
|
16
|
-
])("
|
|
17
|
-
|
|
47
|
+
])("returns false if the file doesn't contain any require('@sentry/') calls", function (code) {
|
|
48
|
+
// recast.parse returns a Program node (or fails) but it's badly typed as any
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
50
|
+
var program = recast.parse(code)
|
|
51
|
+
.program;
|
|
52
|
+
expect((0, ast_utils_1.hasSentryContent)(program)).toBe(false);
|
|
18
53
|
});
|
|
19
54
|
});
|
|
20
55
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.test.js","sourceRoot":"","sources":["../../../test/utils/ast-utils.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ast-utils.test.js","sourceRoot":"","sources":["../../../test/utils/ast-utils.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uDAA6D;AAE7D,6CAAiC;AAEjC,QAAQ,CAAC,WAAW,EAAE;IACpB,QAAQ,CAAC,kBAAkB,EAAE;QAC3B,EAAE,CAAC,IAAI,CAAC;YACN,0HAGD;YACC,6MAOC;SACF,CAAC,CACA,2EAA2E,EAC3E,UAAC,IAAI;YACH,6EAA6E;YAC7E,sEAAsE;YACtE,IAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;iBAC/B,OAA0C,CAAC;YAC9C,MAAM,CAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC,CACF,CAAC;QAEF,EAAE,CAAC,IAAI,CAAC;YACN,uCAAuC;YACvC,oEAAoE;YACpE,iEAAiE;YACjE,8GAKC;YACD,0KAKC;YACD,mJAIC;SACF,CAAC,CACA,yEAAyE,EACzE,UAAC,IAAI;YACH,6EAA6E;YAC7E,sEAAsE;YACtE,IAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;iBAC/B,OAA0C,CAAC;YAC9C,MAAM,CAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { hasSentryContent } from '../../src/utils/ast-utils';\n\nimport * as recast from 'recast';\n\ndescribe('AST utils', () => {\n describe('hasSentryContent', () => {\n it.each([\n `\n const { sentryVitePlugin } = require(\"@sentry/vite-plugin\");\n const somethingelse = require('gs');\n `,\n `\n import { sentryVitePlugin } from \"@sentry/vite-plugin\";\n import * as somethingelse from 'gs';\n\n export default {\n plugins: [sentryVitePlugin()]\n }\n `,\n ])(\n \"returns true if a require('@sentry/') call was found in the parsed module\",\n (code) => {\n // recast.parse returns a Program node (or fails) but it's badly typed as any\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const program = recast.parse(code)\n .program as recast.types.namedTypes.Program;\n expect(hasSentryContent(program)).toBe(true);\n },\n );\n\n it.each([\n `const whatever = require('something')`,\n `// const {sentryWebpackPlugin} = require('@sentry/webpack-plugin')`,\n `const {sAntryWebpackPlugin} = require('webpack-plugin-@sentry')`,\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 \"returns false if the file doesn't contain any require('@sentry/') calls\",\n (code) => {\n // recast.parse returns a Program node (or fails) but it's badly typed as any\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const program = recast.parse(code)\n .program as recast.types.namedTypes.Program;\n expect(hasSentryContent(program)).toBe(false);\n },\n );\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,200 @@
|
|
|
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
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;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
var clack_utils_1 = require("../../src/utils/clack-utils");
|
|
63
|
+
var fs = __importStar(require("fs"));
|
|
64
|
+
var clackMock;
|
|
65
|
+
jest.mock('@clack/prompts', function () {
|
|
66
|
+
clackMock = {
|
|
67
|
+
log: {
|
|
68
|
+
info: jest.fn(),
|
|
69
|
+
success: jest.fn(),
|
|
70
|
+
warn: jest.fn(),
|
|
71
|
+
},
|
|
72
|
+
text: jest.fn(),
|
|
73
|
+
confirm: jest.fn(),
|
|
74
|
+
cancel: jest.fn(),
|
|
75
|
+
// passthrough for abortIfCancelled
|
|
76
|
+
isCancel: jest.fn().mockReturnValue(false),
|
|
77
|
+
};
|
|
78
|
+
return clackMock;
|
|
79
|
+
});
|
|
80
|
+
function mockUserResponse(fn, response) {
|
|
81
|
+
fn.mockReturnValueOnce(response);
|
|
82
|
+
}
|
|
83
|
+
describe('askForToolConfigPath', function () {
|
|
84
|
+
afterEach(function () {
|
|
85
|
+
jest.clearAllMocks();
|
|
86
|
+
});
|
|
87
|
+
it('returns undefined if users have no config file', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
88
|
+
var result;
|
|
89
|
+
return __generator(this, function (_a) {
|
|
90
|
+
switch (_a.label) {
|
|
91
|
+
case 0:
|
|
92
|
+
mockUserResponse(clackMock.confirm, false);
|
|
93
|
+
return [4 /*yield*/, (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js')];
|
|
94
|
+
case 1:
|
|
95
|
+
result = _a.sent();
|
|
96
|
+
expect(clackMock.confirm).toHaveBeenCalledWith(expect.objectContaining({
|
|
97
|
+
message: expect.stringContaining('have a Webpack config file'),
|
|
98
|
+
}));
|
|
99
|
+
expect(result).toBeUndefined();
|
|
100
|
+
return [2 /*return*/];
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}); });
|
|
104
|
+
it('returns the path if users have a config file and the entered path is valid', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
105
|
+
var result;
|
|
106
|
+
return __generator(this, function (_a) {
|
|
107
|
+
switch (_a.label) {
|
|
108
|
+
case 0:
|
|
109
|
+
mockUserResponse(clackMock.confirm, true);
|
|
110
|
+
mockUserResponse(clackMock.text, 'my.webpack.config.js');
|
|
111
|
+
return [4 /*yield*/, (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js')];
|
|
112
|
+
case 1:
|
|
113
|
+
result = _a.sent();
|
|
114
|
+
expect(clackMock.confirm).toHaveBeenCalledWith(expect.objectContaining({
|
|
115
|
+
message: expect.stringContaining('have a Webpack config file'),
|
|
116
|
+
}));
|
|
117
|
+
expect(clackMock.text).toHaveBeenCalledWith(expect.objectContaining({
|
|
118
|
+
message: expect.stringContaining('enter the path to your Webpack config file'),
|
|
119
|
+
}));
|
|
120
|
+
expect(result).toBe('my.webpack.config.js');
|
|
121
|
+
return [2 /*return*/];
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}); });
|
|
125
|
+
});
|
|
126
|
+
describe('createNewConfigFile', function () {
|
|
127
|
+
afterEach(function () {
|
|
128
|
+
jest.clearAllMocks();
|
|
129
|
+
});
|
|
130
|
+
it('writes the file to disk and returns true if the file was created successfully', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
131
|
+
var writeFileSpy, filename, code, result;
|
|
132
|
+
return __generator(this, function (_a) {
|
|
133
|
+
switch (_a.label) {
|
|
134
|
+
case 0:
|
|
135
|
+
writeFileSpy = jest
|
|
136
|
+
.spyOn(fs.promises, 'writeFile')
|
|
137
|
+
.mockImplementation(jest.fn());
|
|
138
|
+
filename = '/weboack.config.js';
|
|
139
|
+
code = "module.exports = {/*config...*/}";
|
|
140
|
+
return [4 /*yield*/, (0, clack_utils_1.createNewConfigFile)(filename, code)];
|
|
141
|
+
case 1:
|
|
142
|
+
result = _a.sent();
|
|
143
|
+
expect(result).toBe(true);
|
|
144
|
+
expect(writeFileSpy).toHaveBeenCalledWith(filename, code);
|
|
145
|
+
return [2 /*return*/];
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}); });
|
|
149
|
+
it('logs more information if provided as an argument', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
150
|
+
var filename, code, moreInfo;
|
|
151
|
+
return __generator(this, function (_a) {
|
|
152
|
+
switch (_a.label) {
|
|
153
|
+
case 0:
|
|
154
|
+
jest.spyOn(fs.promises, 'writeFile').mockImplementation(jest.fn());
|
|
155
|
+
filename = '/weboack.config.js';
|
|
156
|
+
code = "module.exports = {/*config...*/}";
|
|
157
|
+
moreInfo = 'More information...';
|
|
158
|
+
return [4 /*yield*/, (0, clack_utils_1.createNewConfigFile)(filename, code, moreInfo)];
|
|
159
|
+
case 1:
|
|
160
|
+
_a.sent();
|
|
161
|
+
expect(clackMock.log.info).toHaveBeenCalledTimes(1);
|
|
162
|
+
expect(clackMock.log.info).toHaveBeenCalledWith(expect.stringContaining(moreInfo));
|
|
163
|
+
return [2 /*return*/];
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}); });
|
|
167
|
+
it('returns false and logs a warning if the file could not be created', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
168
|
+
var writeFileSpy, filename, code, result;
|
|
169
|
+
return __generator(this, function (_a) {
|
|
170
|
+
switch (_a.label) {
|
|
171
|
+
case 0:
|
|
172
|
+
writeFileSpy = jest
|
|
173
|
+
.spyOn(fs.promises, 'writeFile')
|
|
174
|
+
.mockImplementation(function () { return Promise.reject(new Error('Could not write')); });
|
|
175
|
+
filename = '/webpack.config.js';
|
|
176
|
+
code = "module.exports = {/*config...*/}";
|
|
177
|
+
return [4 /*yield*/, (0, clack_utils_1.createNewConfigFile)(filename, code)];
|
|
178
|
+
case 1:
|
|
179
|
+
result = _a.sent();
|
|
180
|
+
expect(result).toBe(false);
|
|
181
|
+
expect(writeFileSpy).toHaveBeenCalledWith(filename, code);
|
|
182
|
+
expect(clackMock.log.warn).toHaveBeenCalledTimes(1);
|
|
183
|
+
return [2 /*return*/];
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}); });
|
|
187
|
+
it('returns false if the passed path is not absolute', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
188
|
+
var result;
|
|
189
|
+
return __generator(this, function (_a) {
|
|
190
|
+
switch (_a.label) {
|
|
191
|
+
case 0: return [4 /*yield*/, (0, clack_utils_1.createNewConfigFile)('./relative/webpack.config.js', '')];
|
|
192
|
+
case 1:
|
|
193
|
+
result = _a.sent();
|
|
194
|
+
expect(result).toBe(false);
|
|
195
|
+
return [2 /*return*/];
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}); });
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=clack-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clack-utils.test.js","sourceRoot":"","sources":["../../../test/utils/clack-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n askForToolConfigPath,\n createNewConfigFile,\n} from '../../src/utils/clack-utils';\n\nimport * as fs from 'fs';\n\ntype ClackMock = {\n confirm: jest.Mock;\n text: jest.Mock;\n isCancel: jest.Mock;\n cancel: jest.Mock;\n log: {\n info: jest.Mock;\n success: jest.Mock;\n warn: jest.Mock;\n };\n};\n\nlet clackMock: ClackMock;\n\njest.mock('@clack/prompts', () => {\n clackMock = {\n log: {\n info: jest.fn(),\n success: jest.fn(),\n warn: jest.fn(),\n },\n text: jest.fn(),\n confirm: jest.fn(),\n cancel: jest.fn(),\n // passthrough for abortIfCancelled\n isCancel: jest.fn().mockReturnValue(false),\n };\n return clackMock;\n});\n\nfunction mockUserResponse(fn: jest.Mock, response: any) {\n fn.mockReturnValueOnce(response);\n}\n\ndescribe('askForToolConfigPath', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n it('returns undefined if users have no config file', async () => {\n mockUserResponse(clackMock.confirm, false);\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clackMock.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(result).toBeUndefined();\n });\n\n it('returns the path if users have a config file and the entered path is valid', async () => {\n mockUserResponse(clackMock.confirm, true);\n mockUserResponse(clackMock.text, 'my.webpack.config.js');\n\n const result = await askForToolConfigPath('Webpack', 'webpack.config.js');\n\n expect(clackMock.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n message: expect.stringContaining('have a Webpack config file'),\n }),\n );\n\n expect(clackMock.text).toHaveBeenCalledWith(\n expect.objectContaining({\n message: expect.stringContaining(\n 'enter the path to your Webpack config file',\n ),\n }),\n );\n\n expect(result).toBe('my.webpack.config.js');\n });\n});\n\ndescribe('createNewConfigFile', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n it('writes the file to disk and returns true if the file was created successfully', async () => {\n const writeFileSpy = jest\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(jest.fn());\n\n const filename = '/weboack.config.js';\n const code = `module.exports = {/*config...*/}`;\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(true);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n });\n\n it('logs more information if provided as an argument', async () => {\n jest.spyOn(fs.promises, 'writeFile').mockImplementation(jest.fn());\n\n const filename = '/weboack.config.js';\n const code = `module.exports = {/*config...*/}`;\n const moreInfo = 'More information...';\n\n await createNewConfigFile(filename, code, moreInfo);\n\n expect(clackMock.log.info).toHaveBeenCalledTimes(1);\n expect(clackMock.log.info).toHaveBeenCalledWith(\n expect.stringContaining(moreInfo),\n );\n });\n\n it('returns false and logs a warning if the file could not be created', async () => {\n const writeFileSpy = jest\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.reject(new Error('Could not write')));\n\n const filename = '/webpack.config.js';\n const code = `module.exports = {/*config...*/}`;\n\n const result = await createNewConfigFile(filename, code);\n\n expect(result).toBe(false);\n expect(writeFileSpy).toHaveBeenCalledWith(filename, code);\n expect(clackMock.log.warn).toHaveBeenCalledTimes(1);\n });\n\n it('returns false if the passed path is not absolute', async () => {\n const result = await createNewConfigFile(\n './relative/webpack.config.js',\n '',\n );\n\n expect(result).toBe(false);\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.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",
|
|
@@ -3,6 +3,7 @@ import * as fs from 'fs';
|
|
|
3
3
|
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
import * as path from 'path';
|
|
6
|
+
import * as Sentry from '@sentry/node';
|
|
6
7
|
import * as gradle from './gradle';
|
|
7
8
|
import * as manifest from './manifest';
|
|
8
9
|
import * as codetools from './code-tools';
|
|
@@ -69,6 +70,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
69
70
|
clack.log.error(
|
|
70
71
|
'No Gradle project found. Please run this command from the root of your project.',
|
|
71
72
|
);
|
|
73
|
+
Sentry.captureException('No Gradle project found');
|
|
72
74
|
await abort();
|
|
73
75
|
return;
|
|
74
76
|
}
|
|
@@ -100,6 +102,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
100
102
|
"Could not add Sentry Gradle plugin to your app's build.gradle file. You'll have to add it manually.\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#install",
|
|
101
103
|
);
|
|
102
104
|
}
|
|
105
|
+
Sentry.setTag('gradle-plugin-added', pluginAdded);
|
|
103
106
|
|
|
104
107
|
// ======== STEP 2. Configure Sentry SDK via AndroidManifest ============
|
|
105
108
|
clack.log.step(
|
|
@@ -119,6 +122,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
119
122
|
"Could not configure the Sentry SDK. You'll have to do it manually.\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#configure",
|
|
120
123
|
);
|
|
121
124
|
}
|
|
125
|
+
Sentry.setTag('android-manifest-updated', manifestUpdated);
|
|
122
126
|
|
|
123
127
|
// ======== STEP 3. Patch Main Activity with a test error snippet ============
|
|
124
128
|
clack.log.step(
|
|
@@ -133,10 +137,13 @@ async function runAndroidWizardWithTelemetry(
|
|
|
133
137
|
packageName = gradle.getNamespace(appFile);
|
|
134
138
|
}
|
|
135
139
|
const activityName = mainActivity.activityName;
|
|
140
|
+
Sentry.setTag('has-activity-name', !!activityName);
|
|
141
|
+
Sentry.setTag('has-package-name', !!packageName);
|
|
136
142
|
if (!activityName || !packageName) {
|
|
137
143
|
clack.log.warn(
|
|
138
144
|
"Could not find Activity with intent action MAIN. You'll have to manually verify the setup.\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify",
|
|
139
145
|
);
|
|
146
|
+
Sentry.captureException('Could not find Main Activity');
|
|
140
147
|
} else {
|
|
141
148
|
const packageNameStable = packageName;
|
|
142
149
|
const activityFile = traceStep('Find Main Activity Source File', () =>
|
|
@@ -151,6 +158,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
151
158
|
"Could not patch main activity. You'll have to manually verify the setup.\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify",
|
|
152
159
|
);
|
|
153
160
|
}
|
|
161
|
+
Sentry.setTag('main-activity-patched', activityPatched);
|
|
154
162
|
}
|
|
155
163
|
|
|
156
164
|
// ======== STEP 4. Add sentry-cli config file ============
|
|
@@ -103,13 +103,8 @@ export function patchMainActivity(activityFile: string | undefined): boolean {
|
|
|
103
103
|
return true;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
let importIndex = 0;
|
|
109
|
-
while (importsMatch) {
|
|
110
|
-
importIndex = importsMatch.index + importsMatch[0].length + 1;
|
|
111
|
-
importsMatch = importRegex.exec(activityContent);
|
|
112
|
-
}
|
|
106
|
+
const importIndex = getLastImportLineLocation(activityContent);
|
|
107
|
+
|
|
113
108
|
let newActivityContent;
|
|
114
109
|
if (activityFile.endsWith('.kt')) {
|
|
115
110
|
newActivityContent =
|
|
@@ -154,3 +149,22 @@ export function patchMainActivity(activityFile: string | undefined): boolean {
|
|
|
154
149
|
|
|
155
150
|
return true;
|
|
156
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns the string index of the last import statement in the given code file.
|
|
155
|
+
* Works for both Java and Kotlin import statements.
|
|
156
|
+
*
|
|
157
|
+
* @param sourceCode
|
|
158
|
+
* @returns the insert index, or 0 if none found.
|
|
159
|
+
*/
|
|
160
|
+
export function getLastImportLineLocation(sourceCode: string): number {
|
|
161
|
+
const importRegex = /import(?:\sstatic)?\s+[\w.*]+(?: as [\w.]+)?;?/gim;
|
|
162
|
+
|
|
163
|
+
let importsMatch = importRegex.exec(sourceCode);
|
|
164
|
+
let importIndex = 0;
|
|
165
|
+
while (importsMatch) {
|
|
166
|
+
importIndex = importsMatch.index + importsMatch[0].length + 1;
|
|
167
|
+
importsMatch = importRegex.exec(sourceCode);
|
|
168
|
+
}
|
|
169
|
+
return importIndex;
|
|
170
|
+
}
|
package/src/android/gradle.ts
CHANGED
|
@@ -48,7 +48,12 @@ export async function selectAppFile(
|
|
|
48
48
|
const appFile = await abortIfCancelled(
|
|
49
49
|
clack.text({
|
|
50
50
|
message: `Unable to find your app's directory.
|
|
51
|
-
Please enter the relative path to your app's build.gradle file from the root project
|
|
51
|
+
Please enter the relative path to your app's build.gradle file from the root project`,
|
|
52
|
+
placeholder: 'app/build.gradle.kts',
|
|
53
|
+
validate(value) {
|
|
54
|
+
if (!value.includes('.gradle') || !fs.existsSync(value))
|
|
55
|
+
return `Not a valid gradle file.`;
|
|
56
|
+
},
|
|
52
57
|
}),
|
|
53
58
|
);
|
|
54
59
|
return appFile;
|