@sentry/wizard 3.11.0 → 3.13.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 +20 -0
- package/dist/lib/Steps/ChooseIntegration.js +1 -0
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/android/android-wizard.js +14 -4
- 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/nextjs/nextjs-wizard.js +5 -2
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.d.ts +1 -1
- package/dist/src/nextjs/templates.js +2 -2
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/remix/remix-wizard.js +8 -4
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/remix/sdk-setup.d.ts +5 -1
- package/dist/src/remix/sdk-setup.js +3 -2
- package/dist/src/remix/sdk-setup.js.map +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.d.ts +9 -0
- package/dist/src/sourcemaps/tools/sentry-cli.js +26 -22
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/tsc.d.ts +6 -0
- package/dist/src/sourcemaps/tools/tsc.js +98 -17
- package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +39 -124
- 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 +280 -25
- package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +123 -49
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.d.ts +1 -0
- package/dist/src/sveltekit/sveltekit-wizard.js +119 -44
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/sveltekit/utils.d.ts +2 -0
- package/dist/src/sveltekit/utils.js +48 -0
- package/dist/src/sveltekit/utils.js.map +1 -0
- package/dist/src/utils/ast-utils.d.ts +77 -3
- package/dist/src/utils/ast-utils.js +172 -6
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +85 -1
- package/dist/src/utils/clack-utils.js +214 -51
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-manager.d.ts +5 -0
- package/dist/src/utils/package-manager.js +11 -7
- package/dist/src/utils/package-manager.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/sentry-cli.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/sentry-cli.test.js +112 -0
- package/dist/test/sourcemaps/tools/sentry-cli.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/tsc.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/tsc.test.js +121 -0
- package/dist/test/sourcemaps/tools/tsc.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 +181 -15
- 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/lib/Steps/ChooseIntegration.ts +1 -0
- package/package.json +1 -1
- package/src/android/android-wizard.ts +16 -5
- package/src/android/code-tools.ts +21 -7
- package/src/android/gradle.ts +6 -1
- package/src/nextjs/nextjs-wizard.ts +15 -3
- package/src/nextjs/templates.ts +3 -2
- package/src/remix/remix-wizard.ts +8 -11
- package/src/remix/sdk-setup.ts +8 -2
- package/src/sourcemaps/tools/sentry-cli.ts +16 -9
- package/src/sourcemaps/tools/tsc.ts +133 -28
- package/src/sourcemaps/tools/vite.ts +37 -127
- package/src/sourcemaps/tools/webpack.ts +343 -27
- package/src/sveltekit/sdk-setup.ts +115 -39
- package/src/sveltekit/sveltekit-wizard.ts +93 -25
- package/src/sveltekit/utils.ts +50 -0
- package/src/utils/ast-utils.ts +203 -7
- package/src/utils/clack-utils.ts +211 -44
- package/src/utils/package-manager.ts +12 -6
- package/test/android/code-tools.test.ts +49 -0
- package/test/sourcemaps/tools/sentry-cli.test.ts +51 -0
- package/test/sourcemaps/tools/tsc.test.ts +181 -0
- package/test/sourcemaps/tools/webpack.test.ts +303 -0
- package/test/utils/ast-utils.test.ts +240 -20
- package/test/utils/clack-utils.test.ts +142 -0
|
@@ -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.13.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
|
}
|
|
@@ -77,10 +79,8 @@ async function runAndroidWizardWithTelemetry(
|
|
|
77
79
|
gradle.selectAppFile(buildGradleFiles),
|
|
78
80
|
);
|
|
79
81
|
|
|
80
|
-
const { selectedProject, authToken } =
|
|
81
|
-
options,
|
|
82
|
-
'android',
|
|
83
|
-
);
|
|
82
|
+
const { selectedProject, selfHosted, sentryUrl, authToken } =
|
|
83
|
+
await getOrAskForProjectData(options, 'android');
|
|
84
84
|
|
|
85
85
|
// ======== STEP 1. Add Sentry Gradle Plugin to build.gradle(.kts) ============
|
|
86
86
|
clack.log.step(
|
|
@@ -100,6 +100,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
100
100
|
"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
101
|
);
|
|
102
102
|
}
|
|
103
|
+
Sentry.setTag('gradle-plugin-added', pluginAdded);
|
|
103
104
|
|
|
104
105
|
// ======== STEP 2. Configure Sentry SDK via AndroidManifest ============
|
|
105
106
|
clack.log.step(
|
|
@@ -119,6 +120,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
119
120
|
"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
121
|
);
|
|
121
122
|
}
|
|
123
|
+
Sentry.setTag('android-manifest-updated', manifestUpdated);
|
|
122
124
|
|
|
123
125
|
// ======== STEP 3. Patch Main Activity with a test error snippet ============
|
|
124
126
|
clack.log.step(
|
|
@@ -133,10 +135,13 @@ async function runAndroidWizardWithTelemetry(
|
|
|
133
135
|
packageName = gradle.getNamespace(appFile);
|
|
134
136
|
}
|
|
135
137
|
const activityName = mainActivity.activityName;
|
|
138
|
+
Sentry.setTag('has-activity-name', !!activityName);
|
|
139
|
+
Sentry.setTag('has-package-name', !!packageName);
|
|
136
140
|
if (!activityName || !packageName) {
|
|
137
141
|
clack.log.warn(
|
|
138
142
|
"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
143
|
);
|
|
144
|
+
Sentry.captureException('Could not find Main Activity');
|
|
140
145
|
} else {
|
|
141
146
|
const packageNameStable = packageName;
|
|
142
147
|
const activityFile = traceStep('Find Main Activity Source File', () =>
|
|
@@ -151,6 +156,7 @@ async function runAndroidWizardWithTelemetry(
|
|
|
151
156
|
"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
157
|
);
|
|
153
158
|
}
|
|
159
|
+
Sentry.setTag('main-activity-patched', activityPatched);
|
|
154
160
|
}
|
|
155
161
|
|
|
156
162
|
// ======== STEP 4. Add sentry-cli config file ============
|
|
@@ -164,11 +170,16 @@ async function runAndroidWizardWithTelemetry(
|
|
|
164
170
|
);
|
|
165
171
|
|
|
166
172
|
// ======== OUTRO ========
|
|
173
|
+
const issuesPageLink = selfHosted
|
|
174
|
+
? `${sentryUrl}organizations/${selectedProject.organization.slug}/issues/?project=${selectedProject.id}`
|
|
175
|
+
: `https://${selectedProject.organization.slug}.sentry.io/issues/?project=${selectedProject.id}`;
|
|
176
|
+
|
|
167
177
|
clack.outro(`
|
|
168
178
|
${chalk.greenBright('Successfully installed the Sentry Android SDK!')}
|
|
169
179
|
|
|
170
180
|
${chalk.cyan(
|
|
171
|
-
|
|
181
|
+
`You can validate your setup by launching your application and checking Sentry issues page afterwards
|
|
182
|
+
${issuesPageLink}`,
|
|
172
183
|
)}
|
|
173
184
|
|
|
174
185
|
Check out the SDK documentation for further configuration:
|
|
@@ -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;
|
|
@@ -118,6 +118,8 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
118
118
|
const sentryWebpackOptionsTemplate = getNextjsWebpackPluginOptionsTemplate(
|
|
119
119
|
selectedProject.organization.slug,
|
|
120
120
|
selectedProject.slug,
|
|
121
|
+
selfHosted,
|
|
122
|
+
sentryUrl,
|
|
121
123
|
);
|
|
122
124
|
const sentryBuildOptionsTemplate = getNextjsSentryBuildOptionsTemplate();
|
|
123
125
|
|
|
@@ -323,6 +325,13 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
323
325
|
useClient: true,
|
|
324
326
|
});
|
|
325
327
|
|
|
328
|
+
fs.mkdirSync(
|
|
329
|
+
path.join(process.cwd(), ...appLocation, 'sentry-example-page'),
|
|
330
|
+
{
|
|
331
|
+
recursive: true,
|
|
332
|
+
},
|
|
333
|
+
);
|
|
334
|
+
|
|
326
335
|
await fs.promises.writeFile(
|
|
327
336
|
path.join(
|
|
328
337
|
process.cwd(),
|
|
@@ -340,9 +349,12 @@ export async function runNextjsWizard(options: WizardOptions): Promise<void> {
|
|
|
340
349
|
)}.`,
|
|
341
350
|
);
|
|
342
351
|
|
|
343
|
-
fs.mkdirSync(
|
|
344
|
-
|
|
345
|
-
|
|
352
|
+
fs.mkdirSync(
|
|
353
|
+
path.join(process.cwd(), ...appLocation, 'api', 'sentry-example-api'),
|
|
354
|
+
{
|
|
355
|
+
recursive: true,
|
|
356
|
+
},
|
|
357
|
+
);
|
|
346
358
|
|
|
347
359
|
await fs.promises.writeFile(
|
|
348
360
|
path.join(
|
package/src/nextjs/templates.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export function getNextjsWebpackPluginOptionsTemplate(
|
|
2
2
|
orgSlug: string,
|
|
3
3
|
projectSlug: string,
|
|
4
|
+
selfHosted: boolean,
|
|
5
|
+
url: string,
|
|
4
6
|
): string {
|
|
5
7
|
return `{
|
|
6
8
|
// For all available options, see:
|
|
@@ -8,9 +10,8 @@ export function getNextjsWebpackPluginOptionsTemplate(
|
|
|
8
10
|
|
|
9
11
|
// Suppresses source map uploading logs during build
|
|
10
12
|
silent: true,
|
|
11
|
-
|
|
12
13
|
org: "${orgSlug}",
|
|
13
|
-
project: "${projectSlug}"
|
|
14
|
+
project: "${projectSlug}",${selfHosted ? `\n url: "${url}"` : ''}
|
|
14
15
|
}`;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -53,10 +53,8 @@ async function runRemixWizardWithTelemetry(
|
|
|
53
53
|
// We expect `@remix-run/dev` to be installed for every Remix project
|
|
54
54
|
await ensurePackageIsInstalled(packageJson, '@remix-run/dev', 'Remix');
|
|
55
55
|
|
|
56
|
-
const { selectedProject, authToken } =
|
|
57
|
-
options,
|
|
58
|
-
'javascript-remix',
|
|
59
|
-
);
|
|
56
|
+
const { selectedProject, authToken, sentryUrl } =
|
|
57
|
+
await getOrAskForProjectData(options, 'javascript-remix');
|
|
60
58
|
|
|
61
59
|
await traceStep('Install Sentry SDK', () =>
|
|
62
60
|
installPackage({
|
|
@@ -70,16 +68,15 @@ async function runRemixWizardWithTelemetry(
|
|
|
70
68
|
const isTS = isUsingTypeScript();
|
|
71
69
|
const isV2 = isRemixV2(remixConfig, packageJson);
|
|
72
70
|
|
|
73
|
-
await addSentryCliConfig(
|
|
74
|
-
authToken,
|
|
75
|
-
sourceMapsCliSetupConfig,
|
|
76
|
-
selectedProject.organization.slug,
|
|
77
|
-
selectedProject.name,
|
|
78
|
-
);
|
|
71
|
+
await addSentryCliConfig(authToken, sourceMapsCliSetupConfig);
|
|
79
72
|
|
|
80
73
|
await traceStep('Update build script for sourcemap uploads', async () => {
|
|
81
74
|
try {
|
|
82
|
-
await updateBuildScript(
|
|
75
|
+
await updateBuildScript({
|
|
76
|
+
org: selectedProject.organization.slug,
|
|
77
|
+
project: selectedProject.name,
|
|
78
|
+
url: sentryUrl,
|
|
79
|
+
});
|
|
83
80
|
} catch (e) {
|
|
84
81
|
clack.log
|
|
85
82
|
.warn(`Could not update build script to generate and upload sourcemaps.
|
package/src/remix/sdk-setup.ts
CHANGED
|
@@ -151,7 +151,11 @@ export async function instrumentRootRoute(
|
|
|
151
151
|
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
export async function updateBuildScript(
|
|
154
|
+
export async function updateBuildScript(args: {
|
|
155
|
+
org: string;
|
|
156
|
+
project: string;
|
|
157
|
+
url?: string;
|
|
158
|
+
}): Promise<void> {
|
|
155
159
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
156
160
|
// Add sourcemaps option to build script
|
|
157
161
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
@@ -166,7 +170,9 @@ export async function updateBuildScript(): Promise<void> {
|
|
|
166
170
|
|
|
167
171
|
if (!packageJson.scripts.build) {
|
|
168
172
|
packageJson.scripts.build =
|
|
169
|
-
|
|
173
|
+
`remix build --sourcemap && sentry-upload-sourcemaps --org ${args.org} --project ${args.project}` +
|
|
174
|
+
(args.url ? ` --url ${args.url}` : '');
|
|
175
|
+
|
|
170
176
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
171
177
|
} else if (packageJson.scripts.build.includes('remix build')) {
|
|
172
178
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
2
|
-
import clack from '@clack/prompts';
|
|
2
|
+
import * as clack from '@clack/prompts';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import * as Sentry from '@sentry/node';
|
|
5
5
|
import * as path from 'path';
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { SourceMapUploadToolConfigurationOptions } from './types';
|
|
15
15
|
import { hasPackageInstalled, PackageDotJson } from '../../utils/package-json';
|
|
16
16
|
import { traceStep } from '../../telemetry';
|
|
17
|
-
import { detectPackageManger } from '../../utils/package-manager';
|
|
17
|
+
import { detectPackageManger, NPM } from '../../utils/package-manager';
|
|
18
18
|
|
|
19
19
|
const SENTRY_NPM_SCRIPT_NAME = 'sentry:sourcemaps';
|
|
20
20
|
|
|
@@ -194,7 +194,7 @@ async function askShouldAddToBuildCommand(): Promise<boolean> {
|
|
|
194
194
|
*
|
|
195
195
|
* @param packageDotJson The package.json which will be modified.
|
|
196
196
|
*/
|
|
197
|
-
async function addSentryCommandToBuildCommand(
|
|
197
|
+
export async function addSentryCommandToBuildCommand(
|
|
198
198
|
packageDotJson: PackageDotJson,
|
|
199
199
|
): Promise<void> {
|
|
200
200
|
// This usually shouldn't happen because earlier we added the
|
|
@@ -205,8 +205,7 @@ async function addSentryCommandToBuildCommand(
|
|
|
205
205
|
(s) => s !== SENTRY_NPM_SCRIPT_NAME,
|
|
206
206
|
);
|
|
207
207
|
|
|
208
|
-
const packageManager = detectPackageManger();
|
|
209
|
-
const packageManagerName = packageManager?.name ?? 'npm';
|
|
208
|
+
const packageManager = detectPackageManger() ?? NPM;
|
|
210
209
|
|
|
211
210
|
// Heuristic to pre-select the build command:
|
|
212
211
|
// Often, 'build' is the prod build command, so we favour it.
|
|
@@ -221,7 +220,7 @@ async function addSentryCommandToBuildCommand(
|
|
|
221
220
|
(await abortIfCancelled(
|
|
222
221
|
clack.confirm({
|
|
223
222
|
message: `Is ${chalk.cyan(
|
|
224
|
-
`${
|
|
223
|
+
`${packageManager.runScriptCommand} ${buildCommand}`,
|
|
225
224
|
)} your production build command?`,
|
|
226
225
|
}),
|
|
227
226
|
));
|
|
@@ -229,7 +228,7 @@ async function addSentryCommandToBuildCommand(
|
|
|
229
228
|
if (allNpmScripts.length && (!buildCommand || !isProdBuildCommand)) {
|
|
230
229
|
buildCommand = await abortIfCancelled(
|
|
231
230
|
clack.select({
|
|
232
|
-
message: `Which ${
|
|
231
|
+
message: `Which ${packageManager.name} command in your ${chalk.cyan(
|
|
233
232
|
'package.json',
|
|
234
233
|
)} builds your application for production?`,
|
|
235
234
|
options: allNpmScripts
|
|
@@ -252,10 +251,18 @@ Please add it manually to your prod build command.`,
|
|
|
252
251
|
return;
|
|
253
252
|
}
|
|
254
253
|
|
|
254
|
+
const oldCommand = packageDotJson.scripts[buildCommand];
|
|
255
|
+
if (!oldCommand) {
|
|
256
|
+
// very unlikely to happen but nevertheless
|
|
257
|
+
clack.log.warn(
|
|
258
|
+
`\`${buildCommand}\` doesn't seem to be part of your package.json scripts`,
|
|
259
|
+
);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
255
263
|
packageDotJson.scripts[
|
|
256
264
|
buildCommand
|
|
257
|
-
|
|
258
|
-
] = `${packageDotJson.scripts[buildCommand]} && ${packageManager} run ${SENTRY_NPM_SCRIPT_NAME}`;
|
|
265
|
+
] = `${oldCommand} && ${packageManager.runScriptCommand} ${SENTRY_NPM_SCRIPT_NAME}`;
|
|
259
266
|
|
|
260
267
|
await fs.promises.writeFile(
|
|
261
268
|
path.join(process.cwd(), 'package.json'),
|