@sentry/wizard 3.10.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 +54 -7
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Steps/ChooseIntegration.js +8 -4
- package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
- package/dist/lib/Steps/Integrations/Android.d.ts +9 -0
- package/dist/lib/Steps/Integrations/Android.js +86 -0
- package/dist/lib/Steps/Integrations/Android.js.map +1 -0
- package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/PromptForParameters.js +36 -3
- package/dist/lib/Steps/PromptForParameters.js.map +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js +1 -1
- package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
- package/dist/package.json +4 -3
- package/dist/src/android/android-wizard.d.ts +2 -0
- package/dist/src/android/android-wizard.js +225 -0
- package/dist/src/android/android-wizard.js.map +1 -0
- package/dist/src/android/code-tools.d.ts +47 -0
- package/dist/src/android/code-tools.js +173 -0
- package/dist/src/android/code-tools.js.map +1 -0
- package/dist/src/android/gradle.d.ts +62 -0
- package/dist/src/android/gradle.js +286 -0
- package/dist/src/android/gradle.js.map +1 -0
- package/dist/src/android/manifest.d.ts +57 -0
- package/dist/src/android/manifest.js +183 -0
- package/dist/src/android/manifest.js.map +1 -0
- package/dist/src/android/templates.d.ts +11 -0
- package/dist/src/android/templates.js +34 -0
- package/dist/src/android/templates.js.map +1 -0
- package/dist/src/apple/apple-wizard.js +123 -64
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/cocoapod.js +4 -3
- package/dist/src/apple/cocoapod.js.map +1 -1
- package/dist/src/apple/code-tools.d.ts +1 -1
- package/dist/src/apple/code-tools.js +43 -19
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/fastlane.d.ts +1 -1
- package/dist/src/apple/fastlane.js +12 -6
- package/dist/src/apple/fastlane.js.map +1 -1
- package/dist/src/apple/templates.d.ts +2 -2
- package/dist/src/apple/templates.js +4 -4
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +19 -3
- package/dist/src/apple/xcode-manager.js +126 -24
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +49 -11
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.d.ts +2 -0
- package/dist/src/nextjs/templates.js +6 -2
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/remix/remix-wizard.js +10 -20
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +26 -13
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js +1 -1
- package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
- package/dist/src/sourcemaps/tools/sentry-cli.js +19 -16
- package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.d.ts +2 -1
- package/dist/src/sourcemaps/tools/vite.js +123 -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/sourcemaps/utils/detect-tool.d.ts +1 -1
- package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup.js +5 -5
- package/dist/src/sveltekit/sdk-setup.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +34 -44
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/telemetry.js +1 -0
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +9 -5
- package/dist/src/utils/ast-utils.js +26 -11
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +74 -28
- package/dist/src/utils/clack-utils.js +427 -264
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-manager.d.ts +10 -0
- package/dist/{lib/Helper/PackageManager.js → src/utils/package-manager.js} +42 -74
- package/dist/src/utils/package-manager.js.map +1 -0
- package/dist/src/utils/release-registry.d.ts +1 -0
- package/dist/src/utils/release-registry.js +68 -0
- package/dist/src/utils/release-registry.js.map +1 -0
- package/dist/src/utils/sentrycli-utils.d.ts +4 -0
- package/dist/src/utils/sentrycli-utils.js +41 -0
- package/dist/src/utils/sentrycli-utils.js.map +1 -0
- 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/vite.test.d.ts +1 -0
- package/dist/test/sourcemaps/tools/vite.test.js +132 -0
- package/dist/test/sourcemaps/tools/vite.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/lib/Constants.ts +5 -0
- package/lib/Steps/ChooseIntegration.ts +7 -3
- package/lib/Steps/Integrations/Android.ts +23 -0
- package/lib/Steps/Integrations/ReactNative.ts +9 -3
- package/lib/Steps/PromptForParameters.ts +48 -3
- package/lib/Steps/SentryProjectSelector.ts +3 -1
- package/package.json +4 -3
- package/src/android/android-wizard.ts +204 -0
- package/src/android/code-tools.ts +170 -0
- package/src/android/gradle.ts +250 -0
- package/src/android/manifest.ts +180 -0
- package/src/android/templates.ts +88 -0
- package/src/apple/apple-wizard.ts +113 -35
- package/src/apple/cocoapod.ts +6 -3
- package/src/apple/code-tools.ts +46 -18
- package/src/apple/fastlane.ts +6 -12
- package/src/apple/templates.ts +2 -8
- package/src/apple/xcode-manager.ts +167 -25
- package/src/nextjs/nextjs-wizard.ts +72 -8
- package/src/nextjs/templates.ts +16 -2
- package/src/remix/remix-wizard.ts +10 -15
- package/src/sourcemaps/sourcemaps-wizard.ts +19 -5
- package/src/sourcemaps/tools/nextjs.ts +2 -2
- package/src/sourcemaps/tools/sentry-cli.ts +8 -7
- package/src/sourcemaps/tools/vite.ts +143 -79
- package/src/sourcemaps/tools/webpack.ts +369 -30
- package/src/sourcemaps/utils/detect-tool.ts +2 -1
- package/src/sveltekit/sdk-setup.ts +10 -6
- package/src/sveltekit/sveltekit-wizard.ts +5 -14
- package/src/telemetry.ts +2 -0
- package/src/utils/ast-utils.ts +29 -11
- package/src/utils/clack-utils.ts +485 -283
- package/src/utils/package-manager.ts +61 -0
- package/src/utils/release-registry.ts +19 -0
- package/src/utils/sentrycli-utils.ts +22 -0
- package/test/android/code-tools.test.ts +49 -0
- package/test/sourcemaps/tools/vite.test.ts +149 -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
- package/dist/lib/Helper/PackageManager.d.ts +0 -22
- package/dist/lib/Helper/PackageManager.js.map +0 -1
- package/dist/src/utils/vendor/clack-custom-select.d.ts +0 -21
- package/dist/src/utils/vendor/clack-custom-select.js +0 -137
- package/dist/src/utils/vendor/clack-custom-select.js.map +0 -1
- package/lib/Helper/PackageManager.ts +0 -59
- package/src/utils/vendor/clack-custom-select.ts +0 -160
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/typedef */
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
|
|
7
|
+
export interface PackageManager {
|
|
8
|
+
name: string;
|
|
9
|
+
label: string;
|
|
10
|
+
lockFile: string;
|
|
11
|
+
installCommand: string;
|
|
12
|
+
buildCommand: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const bun: PackageManager = {
|
|
16
|
+
name: 'bun',
|
|
17
|
+
label: 'Bun',
|
|
18
|
+
lockFile: 'bun.lockb',
|
|
19
|
+
installCommand: 'bun add',
|
|
20
|
+
buildCommand: 'bun build',
|
|
21
|
+
};
|
|
22
|
+
const yarn: PackageManager = {
|
|
23
|
+
name: 'yarn',
|
|
24
|
+
label: 'Yarn',
|
|
25
|
+
lockFile: 'yarn.lock',
|
|
26
|
+
installCommand: 'yarn add',
|
|
27
|
+
buildCommand: 'yarn build',
|
|
28
|
+
};
|
|
29
|
+
const pnpm: PackageManager = {
|
|
30
|
+
name: 'pnpm',
|
|
31
|
+
label: 'PNPM',
|
|
32
|
+
lockFile: 'pnpm-lock.yaml',
|
|
33
|
+
installCommand: 'pnpm add',
|
|
34
|
+
buildCommand: 'pnpm build',
|
|
35
|
+
};
|
|
36
|
+
const npm: PackageManager = {
|
|
37
|
+
name: 'npm',
|
|
38
|
+
label: 'NPM',
|
|
39
|
+
lockFile: 'package-lock.json',
|
|
40
|
+
installCommand: 'npm add',
|
|
41
|
+
buildCommand: 'npm run build',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const packageManagers = [bun, yarn, pnpm, npm];
|
|
45
|
+
|
|
46
|
+
export function detectPackageManger(): PackageManager | null {
|
|
47
|
+
for (const packageManager of packageManagers) {
|
|
48
|
+
if (fs.existsSync(path.join(process.cwd(), packageManager.lockFile))) {
|
|
49
|
+
return packageManager;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// We make the default NPM - it's weird if we don't find any lock file
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function installPackageWithPackageManager(
|
|
57
|
+
packageManager: PackageManager,
|
|
58
|
+
packageName: string,
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
await promisify(exec)(`${packageManager.installCommand} ${packageName}`);
|
|
61
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { debug } from './debug';
|
|
3
|
+
const registryUrl = 'https://release-registry.services.sentry.io/';
|
|
4
|
+
|
|
5
|
+
export async function fetchSdkVersion(
|
|
6
|
+
sdk: string,
|
|
7
|
+
): Promise<string | undefined> {
|
|
8
|
+
try {
|
|
9
|
+
const data = (
|
|
10
|
+
await axios.get<Record<string, { version: string }>>(
|
|
11
|
+
`${registryUrl}/sdks`,
|
|
12
|
+
)
|
|
13
|
+
).data;
|
|
14
|
+
return data[sdk]?.version;
|
|
15
|
+
} catch {
|
|
16
|
+
debug('Failed to fetch latest version from release registry.');
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
export interface SentryCLIConfiguration {
|
|
6
|
+
auth_token: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createSentryCLIRC(
|
|
10
|
+
directory: string,
|
|
11
|
+
params: SentryCLIConfiguration,
|
|
12
|
+
) {
|
|
13
|
+
const rcPath = path.join(directory, '.sentryclirc');
|
|
14
|
+
fs.writeFileSync(rcPath, '[auth]\ntoken=' + params.auth_token);
|
|
15
|
+
|
|
16
|
+
if (fs.existsSync('.gitignore')) {
|
|
17
|
+
const gitIgnore = fs.readFileSync('.gitignore').toString();
|
|
18
|
+
if (!gitIgnore.includes('.sentryclirc')) {
|
|
19
|
+
fs.appendFileSync('.gitignore', '\n.sentryclirc');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//@ts-ignore
|
|
2
|
+
import { getLastImportLineLocation } from '../../src/android/code-tools';
|
|
3
|
+
|
|
4
|
+
describe('code-tools', () => {
|
|
5
|
+
describe('getLastImportLineLocation', () => {
|
|
6
|
+
it('returns proper line index', () => {
|
|
7
|
+
const code = `import a.b.c;\n` + `//<insert-location>\n` + `class X {}`;
|
|
8
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
9
|
+
code.indexOf('//<insert-location>'),
|
|
10
|
+
);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('returns proper line index when static import is used', () => {
|
|
14
|
+
const code =
|
|
15
|
+
`import static a.b.c;\n` + `//<insert-location>\n` + `class X {}`;
|
|
16
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
17
|
+
code.indexOf('//<insert-location>'),
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('returns proper line index when wildcard import is used', () => {
|
|
22
|
+
const code = `import a.b.*\n` + `//<insert-location>\n` + `class X {}`;
|
|
23
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
24
|
+
code.indexOf('//<insert-location>'),
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('returns proper line index when alias import is used', () => {
|
|
29
|
+
const code =
|
|
30
|
+
`import static a.b.c as d\n` + `//<insert-location>\n` + `class X {}`;
|
|
31
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
32
|
+
code.indexOf('//<insert-location>'),
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('returns proper line index when multiple imports are present', () => {
|
|
37
|
+
const code =
|
|
38
|
+
`import static a.b.c as d\n` +
|
|
39
|
+
`import a.b.*\n` +
|
|
40
|
+
`import static a.b.c;\n` +
|
|
41
|
+
`import a.b.c;\n` +
|
|
42
|
+
`//<insert-location>\n` +
|
|
43
|
+
`class X {}`;
|
|
44
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
45
|
+
code.indexOf('//<insert-location>'),
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { addVitePluginToConfig } from '../../../src/sourcemaps/tools/vite';
|
|
3
|
+
|
|
4
|
+
function updateFileContent(content: string): void {
|
|
5
|
+
fileContent = content;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let fileContent = '';
|
|
9
|
+
|
|
10
|
+
jest.mock('@clack/prompts', () => {
|
|
11
|
+
return {
|
|
12
|
+
log: {
|
|
13
|
+
info: jest.fn(),
|
|
14
|
+
success: jest.fn(),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
jest
|
|
20
|
+
.spyOn(fs.promises, 'readFile')
|
|
21
|
+
.mockImplementation(() => Promise.resolve(fileContent));
|
|
22
|
+
|
|
23
|
+
const writeFileSpy = jest
|
|
24
|
+
.spyOn(fs.promises, 'writeFile')
|
|
25
|
+
.mockImplementation(() => Promise.resolve(void 0));
|
|
26
|
+
|
|
27
|
+
describe('addVitePluginToConfig', () => {
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
fileContent = '';
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it.each([
|
|
34
|
+
[
|
|
35
|
+
'no build options',
|
|
36
|
+
`
|
|
37
|
+
export default defineConfig({
|
|
38
|
+
plugins: [
|
|
39
|
+
vue(),
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
`,
|
|
43
|
+
`import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
44
|
+
export default defineConfig({
|
|
45
|
+
plugins: [vue(), sentryVitePlugin({
|
|
46
|
+
org: "my-org",
|
|
47
|
+
project: "my-project"
|
|
48
|
+
})],
|
|
49
|
+
|
|
50
|
+
build: {
|
|
51
|
+
sourcemap: true
|
|
52
|
+
}
|
|
53
|
+
})`,
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
'no build.sourcemap options',
|
|
57
|
+
`
|
|
58
|
+
export default defineConfig({
|
|
59
|
+
plugins: [
|
|
60
|
+
vue(),
|
|
61
|
+
],
|
|
62
|
+
build: {
|
|
63
|
+
test: 1,
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
`,
|
|
67
|
+
`import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
plugins: [vue(), sentryVitePlugin({
|
|
70
|
+
org: "my-org",
|
|
71
|
+
project: "my-project"
|
|
72
|
+
})],
|
|
73
|
+
build: {
|
|
74
|
+
test: 1,
|
|
75
|
+
sourcemap: true
|
|
76
|
+
}
|
|
77
|
+
})`,
|
|
78
|
+
],
|
|
79
|
+
[
|
|
80
|
+
'keep sourcemap: "hidden"',
|
|
81
|
+
`
|
|
82
|
+
export default {
|
|
83
|
+
plugins: [
|
|
84
|
+
vue(),
|
|
85
|
+
],
|
|
86
|
+
build: {
|
|
87
|
+
sourcemap: "hidden",
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`,
|
|
91
|
+
`import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
92
|
+
export default {
|
|
93
|
+
plugins: [vue(), sentryVitePlugin({
|
|
94
|
+
org: "my-org",
|
|
95
|
+
project: "my-project"
|
|
96
|
+
})],
|
|
97
|
+
build: {
|
|
98
|
+
sourcemap: "hidden",
|
|
99
|
+
}
|
|
100
|
+
}`,
|
|
101
|
+
],
|
|
102
|
+
[
|
|
103
|
+
'rewrite sourcemap: false to true',
|
|
104
|
+
`
|
|
105
|
+
const cfg = {
|
|
106
|
+
plugins: [
|
|
107
|
+
vue(),
|
|
108
|
+
],
|
|
109
|
+
build: {
|
|
110
|
+
sourcemap: false,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export default cfg;
|
|
115
|
+
`,
|
|
116
|
+
`import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
117
|
+
const cfg = {
|
|
118
|
+
plugins: [vue(), sentryVitePlugin({
|
|
119
|
+
org: "my-org",
|
|
120
|
+
project: "my-project"
|
|
121
|
+
})],
|
|
122
|
+
|
|
123
|
+
build: {
|
|
124
|
+
sourcemap: true,
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default cfg;`,
|
|
129
|
+
],
|
|
130
|
+
])(
|
|
131
|
+
'adds the plugin and enables source maps generation (%s)',
|
|
132
|
+
async (_, originalCode, expectedCode) => {
|
|
133
|
+
updateFileContent(originalCode);
|
|
134
|
+
|
|
135
|
+
const addedCode = await addVitePluginToConfig('', {
|
|
136
|
+
authToken: '',
|
|
137
|
+
orgSlug: 'my-org',
|
|
138
|
+
projectSlug: 'my-project',
|
|
139
|
+
selfHosted: false,
|
|
140
|
+
url: 'https://sentry.io/',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(writeFileSpy).toHaveBeenCalledTimes(1);
|
|
144
|
+
const [[, fileContent]] = writeFileSpy.mock.calls;
|
|
145
|
+
expect(fileContent).toBe(expectedCode);
|
|
146
|
+
expect(addedCode).toBe(true);
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
});
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
|
|
3
|
+
import { modifyWebpackConfig } from '../../../src/sourcemaps/tools/webpack';
|
|
4
|
+
|
|
5
|
+
function updateFileContent(content: string): void {
|
|
6
|
+
fileContent = content;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let fileContent = '';
|
|
10
|
+
|
|
11
|
+
jest.mock('@clack/prompts', () => {
|
|
12
|
+
return {
|
|
13
|
+
log: {
|
|
14
|
+
info: jest.fn(),
|
|
15
|
+
success: jest.fn(),
|
|
16
|
+
},
|
|
17
|
+
select: jest.fn().mockImplementation(() => Promise.resolve(true)),
|
|
18
|
+
isCancel: jest.fn().mockReturnValue(false),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
jest
|
|
23
|
+
.spyOn(fs.promises, 'readFile')
|
|
24
|
+
.mockImplementation(() => Promise.resolve(fileContent));
|
|
25
|
+
|
|
26
|
+
const writeFileSpy = jest
|
|
27
|
+
.spyOn(fs.promises, 'writeFile')
|
|
28
|
+
.mockImplementation(() => Promise.resolve(void 0));
|
|
29
|
+
|
|
30
|
+
const noSourcemapNoPluginsPojo = `module.exports = {
|
|
31
|
+
entry: "./src/index.js",
|
|
32
|
+
output: {
|
|
33
|
+
filename: "main.js",
|
|
34
|
+
path: path.resolve(__dirname, "build"),
|
|
35
|
+
},
|
|
36
|
+
};`;
|
|
37
|
+
|
|
38
|
+
const noSourcemapNoPluginsPojoResult = `const {
|
|
39
|
+
sentryWebpackPlugin
|
|
40
|
+
} = require("@sentry/webpack-plugin");
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
entry: "./src/index.js",
|
|
44
|
+
|
|
45
|
+
output: {
|
|
46
|
+
filename: "main.js",
|
|
47
|
+
path: path.resolve(__dirname, "build"),
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
devtool: "source-map",
|
|
51
|
+
|
|
52
|
+
plugins: [sentryWebpackPlugin({
|
|
53
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
54
|
+
org: "my-org",
|
|
55
|
+
project: "my-project"
|
|
56
|
+
})]
|
|
57
|
+
};`;
|
|
58
|
+
|
|
59
|
+
const noSourcemapsNoPluginsId = `const config = {
|
|
60
|
+
entry: "./src/index.js",
|
|
61
|
+
|
|
62
|
+
output: {
|
|
63
|
+
filename: "main.js",
|
|
64
|
+
path: path.resolve(__dirname, "build"),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
module.exports = config;`;
|
|
69
|
+
|
|
70
|
+
const noSourcemapsNoPluginsIdResult = `const {
|
|
71
|
+
sentryWebpackPlugin
|
|
72
|
+
} = require("@sentry/webpack-plugin");
|
|
73
|
+
|
|
74
|
+
const config = {
|
|
75
|
+
entry: "./src/index.js",
|
|
76
|
+
|
|
77
|
+
output: {
|
|
78
|
+
filename: "main.js",
|
|
79
|
+
path: path.resolve(__dirname, "build"),
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
devtool: "source-map",
|
|
83
|
+
|
|
84
|
+
plugins: [sentryWebpackPlugin({
|
|
85
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
86
|
+
org: "my-org",
|
|
87
|
+
project: "my-project"
|
|
88
|
+
})]
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
module.exports = config;`;
|
|
92
|
+
|
|
93
|
+
const hiddenSourcemapNoPluginsId = `const config = {
|
|
94
|
+
entry: "./src/index.js",
|
|
95
|
+
|
|
96
|
+
output: {
|
|
97
|
+
filename: "main.js",
|
|
98
|
+
path: path.resolve(__dirname, "build"),
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
devtool: "hidden-cheap-source-map",
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
module.exports = config;
|
|
105
|
+
`;
|
|
106
|
+
const hiddenSourcemapNoPluginsIdResult = `const {
|
|
107
|
+
sentryWebpackPlugin
|
|
108
|
+
} = require("@sentry/webpack-plugin");
|
|
109
|
+
|
|
110
|
+
const config = {
|
|
111
|
+
entry: "./src/index.js",
|
|
112
|
+
|
|
113
|
+
output: {
|
|
114
|
+
filename: "main.js",
|
|
115
|
+
path: path.resolve(__dirname, "build"),
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
devtool: "hidden-source-map",
|
|
119
|
+
|
|
120
|
+
plugins: [sentryWebpackPlugin({
|
|
121
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
122
|
+
org: "my-org",
|
|
123
|
+
project: "my-project"
|
|
124
|
+
})]
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
module.exports = config;`;
|
|
128
|
+
|
|
129
|
+
const arbitrarySourcemapNoPluginsId = `
|
|
130
|
+
const config = {
|
|
131
|
+
entry: "./src/index.js",
|
|
132
|
+
|
|
133
|
+
output: {
|
|
134
|
+
filename: "main.js",
|
|
135
|
+
path: path.resolve(__dirname, "build"),
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
devtool: getSourcemapSetting(),
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
module.exports = config;
|
|
142
|
+
`;
|
|
143
|
+
const arbitrarySourcemapNoPluginsIdResult = `const {
|
|
144
|
+
sentryWebpackPlugin
|
|
145
|
+
} = require("@sentry/webpack-plugin");
|
|
146
|
+
|
|
147
|
+
const config = {
|
|
148
|
+
entry: "./src/index.js",
|
|
149
|
+
|
|
150
|
+
output: {
|
|
151
|
+
filename: "main.js",
|
|
152
|
+
path: path.resolve(__dirname, "build"),
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
devtool: "source-map",
|
|
156
|
+
|
|
157
|
+
plugins: [sentryWebpackPlugin({
|
|
158
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
159
|
+
org: "my-org",
|
|
160
|
+
project: "my-project"
|
|
161
|
+
})]
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
module.exports = config;`;
|
|
165
|
+
|
|
166
|
+
const noSourcemapUndefinedPluginsPojo = `module.exports = {
|
|
167
|
+
entry: "./src/index.js",
|
|
168
|
+
plugins: undefined,
|
|
169
|
+
output: {
|
|
170
|
+
filename: "main.js",
|
|
171
|
+
path: path.resolve(__dirname, "build"),
|
|
172
|
+
},
|
|
173
|
+
};`;
|
|
174
|
+
|
|
175
|
+
const noSourcemapUndefinedPluginsPojoResult = `const {
|
|
176
|
+
sentryWebpackPlugin
|
|
177
|
+
} = require("@sentry/webpack-plugin");
|
|
178
|
+
|
|
179
|
+
module.exports = {
|
|
180
|
+
entry: "./src/index.js",
|
|
181
|
+
|
|
182
|
+
plugins: [sentryWebpackPlugin({
|
|
183
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
184
|
+
org: "my-org",
|
|
185
|
+
project: "my-project"
|
|
186
|
+
})],
|
|
187
|
+
|
|
188
|
+
output: {
|
|
189
|
+
filename: "main.js",
|
|
190
|
+
path: path.resolve(__dirname, "build"),
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
devtool: "source-map"
|
|
194
|
+
};`;
|
|
195
|
+
|
|
196
|
+
const noSourcemapPluginsPojo = `module.exports = {
|
|
197
|
+
entry: "./src/index.js",
|
|
198
|
+
plugins: [
|
|
199
|
+
new HtmlWebpackPlugin(),
|
|
200
|
+
new MiniCssExtractPlugin(),
|
|
201
|
+
],
|
|
202
|
+
output: {
|
|
203
|
+
filename: "main.js",
|
|
204
|
+
path: path.resolve(__dirname, "build"),
|
|
205
|
+
},
|
|
206
|
+
};`;
|
|
207
|
+
|
|
208
|
+
const noSourcemapPluginsPojoResult = `const {
|
|
209
|
+
sentryWebpackPlugin
|
|
210
|
+
} = require("@sentry/webpack-plugin");
|
|
211
|
+
|
|
212
|
+
module.exports = {
|
|
213
|
+
entry: "./src/index.js",
|
|
214
|
+
|
|
215
|
+
plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin(), sentryWebpackPlugin({
|
|
216
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
217
|
+
org: "my-org",
|
|
218
|
+
project: "my-project"
|
|
219
|
+
})],
|
|
220
|
+
|
|
221
|
+
output: {
|
|
222
|
+
filename: "main.js",
|
|
223
|
+
path: path.resolve(__dirname, "build"),
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
devtool: "source-map"
|
|
227
|
+
};`;
|
|
228
|
+
|
|
229
|
+
describe('modifyWebpackConfig', () => {
|
|
230
|
+
afterEach(() => {
|
|
231
|
+
fileContent = '';
|
|
232
|
+
jest.clearAllMocks();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it.each([
|
|
236
|
+
[
|
|
237
|
+
'no sourcemap option, no plugins, object',
|
|
238
|
+
noSourcemapNoPluginsPojo,
|
|
239
|
+
noSourcemapNoPluginsPojoResult,
|
|
240
|
+
],
|
|
241
|
+
[
|
|
242
|
+
'no sourcemap option, no plugins, identifier',
|
|
243
|
+
noSourcemapsNoPluginsId,
|
|
244
|
+
noSourcemapsNoPluginsIdResult,
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
'hidden sourcemap option, no plugins, identifier',
|
|
248
|
+
hiddenSourcemapNoPluginsId,
|
|
249
|
+
hiddenSourcemapNoPluginsIdResult,
|
|
250
|
+
],
|
|
251
|
+
[
|
|
252
|
+
'arbitrary sourcemap option, no plugins, identifier',
|
|
253
|
+
arbitrarySourcemapNoPluginsId,
|
|
254
|
+
arbitrarySourcemapNoPluginsIdResult,
|
|
255
|
+
],
|
|
256
|
+
[
|
|
257
|
+
'no sourcemap option, plugins, object',
|
|
258
|
+
noSourcemapUndefinedPluginsPojo,
|
|
259
|
+
noSourcemapUndefinedPluginsPojoResult,
|
|
260
|
+
],
|
|
261
|
+
[
|
|
262
|
+
'no sourcemap option, plugins, object',
|
|
263
|
+
noSourcemapPluginsPojo,
|
|
264
|
+
noSourcemapPluginsPojoResult,
|
|
265
|
+
],
|
|
266
|
+
])(
|
|
267
|
+
'adds plugin and source maps emission to the webpack config (%s)',
|
|
268
|
+
async (_, originalCode, expectedCode) => {
|
|
269
|
+
updateFileContent(originalCode);
|
|
270
|
+
|
|
271
|
+
// updateFileContent(originalCode);
|
|
272
|
+
const addedCode = await modifyWebpackConfig('', {
|
|
273
|
+
authToken: '',
|
|
274
|
+
orgSlug: 'my-org',
|
|
275
|
+
projectSlug: 'my-project',
|
|
276
|
+
selfHosted: false,
|
|
277
|
+
url: 'https://sentry.io/',
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
expect(writeFileSpy).toHaveBeenCalledTimes(1);
|
|
281
|
+
const [[, fileContent]] = writeFileSpy.mock.calls;
|
|
282
|
+
expect(fileContent).toBe(expectedCode);
|
|
283
|
+
expect(addedCode).toBe(true);
|
|
284
|
+
},
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
it('adds the url parameter to the webpack plugin options if self-hosted', async () => {
|
|
288
|
+
updateFileContent(noSourcemapNoPluginsPojo);
|
|
289
|
+
|
|
290
|
+
const addedCode = await modifyWebpackConfig('', {
|
|
291
|
+
authToken: '',
|
|
292
|
+
orgSlug: 'my-org',
|
|
293
|
+
projectSlug: 'my-project',
|
|
294
|
+
selfHosted: true,
|
|
295
|
+
url: 'https://santry.io/',
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(writeFileSpy).toHaveBeenCalledTimes(1);
|
|
299
|
+
const [[, fileContent]] = writeFileSpy.mock.calls;
|
|
300
|
+
expect(fileContent).toContain('url: "https://santry.io/"');
|
|
301
|
+
expect(addedCode).toBe(true);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
@@ -1,22 +1,37 @@
|
|
|
1
|
-
//@ts-ignore
|
|
2
|
-
import { parseModule } from 'magicast';
|
|
3
1
|
import { hasSentryContent } from '../../src/utils/ast-utils';
|
|
4
2
|
|
|
3
|
+
import * as recast from 'recast';
|
|
4
|
+
|
|
5
5
|
describe('AST utils', () => {
|
|
6
6
|
describe('hasSentryContent', () => {
|
|
7
|
-
it(
|
|
8
|
-
|
|
7
|
+
it.each([
|
|
8
|
+
`
|
|
9
|
+
const { sentryVitePlugin } = require("@sentry/vite-plugin");
|
|
10
|
+
const somethingelse = require('gs');
|
|
11
|
+
`,
|
|
12
|
+
`
|
|
9
13
|
import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
10
14
|
import * as somethingelse from 'gs';
|
|
11
15
|
|
|
12
16
|
export default {
|
|
13
17
|
plugins: [sentryVitePlugin()]
|
|
14
18
|
}
|
|
15
|
-
|
|
19
|
+
`,
|
|
20
|
+
])(
|
|
21
|
+
"returns true if a require('@sentry/') call was found in the parsed module",
|
|
22
|
+
(code) => {
|
|
23
|
+
// recast.parse returns a Program node (or fails) but it's badly typed as any
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
25
|
+
const program = recast.parse(code)
|
|
26
|
+
.program as recast.types.namedTypes.Program;
|
|
27
|
+
expect(hasSentryContent(program)).toBe(true);
|
|
28
|
+
},
|
|
29
|
+
);
|
|
16
30
|
|
|
17
|
-
expect(hasSentryContent(parseModule(code))).toBe(true);
|
|
18
|
-
});
|
|
19
31
|
it.each([
|
|
32
|
+
`const whatever = require('something')`,
|
|
33
|
+
`// const {sentryWebpackPlugin} = require('@sentry/webpack-plugin')`,
|
|
34
|
+
`const {sAntryWebpackPlugin} = require('webpack-plugin-@sentry')`,
|
|
20
35
|
`
|
|
21
36
|
import * as somethingelse from 'gs';
|
|
22
37
|
export default {
|
|
@@ -35,9 +50,13 @@ describe('AST utils', () => {
|
|
|
35
50
|
}
|
|
36
51
|
`,
|
|
37
52
|
])(
|
|
38
|
-
"
|
|
53
|
+
"returns false if the file doesn't contain any require('@sentry/') calls",
|
|
39
54
|
(code) => {
|
|
40
|
-
|
|
55
|
+
// recast.parse returns a Program node (or fails) but it's badly typed as any
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
57
|
+
const program = recast.parse(code)
|
|
58
|
+
.program as recast.types.namedTypes.Program;
|
|
59
|
+
expect(hasSentryContent(program)).toBe(false);
|
|
41
60
|
},
|
|
42
61
|
);
|
|
43
62
|
});
|