@sentry/wizard 2.6.0 → 2.7.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 +12 -0
- package/dist/lib/Helper/Package.d.ts +1 -0
- package/dist/lib/Helper/Package.js +46 -0
- package/dist/lib/Helper/Package.js.map +1 -0
- package/dist/lib/Helper/PackageManager.d.ts +22 -0
- package/dist/lib/Helper/PackageManager.js +135 -0
- package/dist/lib/Helper/PackageManager.js.map +1 -0
- package/dist/lib/Helper/Wizard.js +2 -1
- package/dist/lib/Helper/Wizard.js.map +1 -1
- package/dist/lib/Helper/__tests__/MergeConfig.js +25 -14
- package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
- package/dist/lib/Steps/Integrations/NextJs.d.ts +0 -5
- package/dist/lib/Steps/Integrations/NextJs.js +6 -85
- package/dist/lib/Steps/Integrations/NextJs.js.map +1 -1
- package/dist/lib/Steps/Integrations/ReactNative.d.ts +7 -0
- package/dist/lib/Steps/Integrations/ReactNative.js +120 -51
- package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +42 -0
- package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
- package/dist/lib/__tests__/Setup.js +15 -0
- package/dist/lib/__tests__/Setup.js.map +1 -1
- package/lib/Helper/Package.ts +61 -0
- package/lib/Helper/PackageManager.ts +64 -0
- package/lib/Helper/Wizard.ts +1 -1
- package/lib/Helper/__tests__/MergeConfig.ts +36 -20
- package/lib/Steps/Integrations/NextJs.ts +8 -108
- package/lib/Steps/Integrations/ReactNative.ts +108 -37
- package/lib/Steps/Integrations/__tests__/ReactNative.ts +34 -0
- package/lib/__tests__/Setup.ts +23 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactNative.js","sourceRoot":"","sources":["../../../../../lib/Steps/Integrations/__tests__/ReactNative.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC,4CAA4C;AACrF,uBAAyB;AAEzB,2BAA6B;AAC7B,iCAAmC;AACnC,+BAAiC;AAEjC,gDAAiE;AACjE,8CAA6C;AAE7C,IAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,IAAM,UAAU,GAAG,cAAc,CAAC;AAClC,IAAM,MAAM,GAAG,aAAa,CAAC;AAC7B,IAAM,cAAc,GAAG,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ReactNative.js","sourceRoot":"","sources":["../../../../../lib/Steps/Integrations/__tests__/ReactNative.ts"],"names":[],"mappings":"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","sourcesContent":["jest.mock('../../../Helper/Logging.ts'); // We mock logging to not pollute the output\njest.mock('child_process');\nimport * as child_process from 'child_process';\nimport * as fs from 'fs';\nimport { Answers } from 'inquirer';\nimport * as path from 'path';\nimport * as process from 'process';\nimport * as rimraf from 'rimraf';\n\nimport { Args, Integration, Platform } from '../../../Constants';\nimport { ReactNative } from '../ReactNative';\n\nconst testDir = 'rn-test';\nconst iosIndexJs = 'index.ios.js';\nconst appTsx = 'src/App.tsx';\nconst appBuildGradle = 'android/app/build.gradle';\nconst yarnLock = 'yarn.lock';\n\nconst dummyJsContent = 'import React from \"react\";\\n';\nconst dummyAppBuildGradleContent = 'apply plugin: \"com.facebook.react\"\\n\\nandroid {\\n}\\n';\n\nconst testArgs = {\n debug: false,\n integration: Integration.reactNative,\n platform: [Platform.ios],\n quiet: true,\n skipConnect: true,\n uninstall: false,\n url: 'https://not.used',\n};\n\nconst mockIosAnswers: Answers = {\n shouldConfigurePlatforms: { 'ios': true },\n config: {\n dsn: {\n public: 'dns.public.com',\n },\n },\n};\n\nconst mockAndroidAnswers: Answers = {\n shouldConfigurePlatforms: { 'android': true },\n config: {\n dsn: {\n public: 'dns.public.com',\n },\n },\n};\n\nconst originalExec = child_process.exec;\n\nconst restoreExec = (): void => {\n (child_process as any).exec = originalExec;\n}\n\nconst mockExec = (): void => {\n (child_process.exec as unknown as jest.Mock)\n .mockImplementation((_command, callback) => callback(null, { stdout: '' }));\n}\n\ndescribe('ReactNative', () => {\n\n const defaultCwd = process.cwd();\n\n beforeEach(() => {\n rimraf.sync(testDir);\n fs.mkdirSync(testDir);\n process.chdir(testDir);\n fs.writeFileSync(iosIndexJs, dummyJsContent);\n fs.mkdirSync(path.dirname(appTsx), { recursive: true });\n fs.writeFileSync(appTsx, dummyJsContent);\n fs.mkdirSync(path.dirname(appBuildGradle), { recursive: true });\n fs.writeFileSync(appBuildGradle, dummyAppBuildGradleContent);\n fs.writeFileSync(yarnLock, '');\n mockExec();\n });\n\n afterEach(() => {\n restoreExec();\n process.chdir(defaultCwd);\n rimraf.sync(testDir);\n });\n\n test('patches js files', async () => {\n const project = new ReactNative(testArgs as Args);\n await project.emit(mockIosAnswers);\n\n const patchedIosIndexJs = fs.readFileSync(iosIndexJs, 'utf8');\n const patchedAppTsx = fs.readFileSync(appTsx, 'utf8');\n const expectedPatch = 'import React from \"react\";\\n\\n' +\n 'import * as Sentry from \\'@sentry/react-native\\';\\n\\n' +\n 'Sentry.init({ \\n' +\n ' dsn: \\'dns.public.com\\', \\n' +\n '});\\n\\n';\n expect(patchedIosIndexJs).toEqual(expectedPatch);\n expect(patchedAppTsx).toEqual(expectedPatch);\n });\n\n test('patches android app build gradle file', async () => {\n const project = new ReactNative(testArgs as Args);\n\n await project.emit(mockAndroidAnswers);\n\n const patchedAppBuildGradle = fs.readFileSync(appBuildGradle, 'utf8');\n const expectedPatch = 'apply plugin: \"com.facebook.react\"\\n\\n' +\n 'apply from: \"../../node_modules/@sentry/react-native/sentry.gradle\"\\n' +\n 'android {\\n}\\n';\n expect(patchedAppBuildGradle).toEqual(expectedPatch);\n });\n\n test('does install sentry sdk', async () => {\n const project = new ReactNative(testArgs as Args);\n\n await project.emit(mockIosAnswers);\n\n expect(child_process.exec).toHaveBeenCalledWith('yarn add @sentry/react-native', expect.anything());\n });\n\n test('executes pod install', async () => {\n const project = new ReactNative(testArgs as Args);\n\n await project.emit(mockIosAnswers);\n\n expect(child_process.exec).toHaveBeenCalledWith('npx --yes pod-install --non-interactive --quiet', expect.anything());\n });\n});\n"]}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
jest.mock('../Helper/Logging'); // We mock logging to not pollute the output
|
|
4
|
+
jest.mock('child_process');
|
|
5
|
+
var child_process = require("child_process");
|
|
4
6
|
var Constants_1 = require("../Constants");
|
|
5
7
|
var Setup_1 = require("../Setup");
|
|
8
|
+
var originalExec = child_process.exec;
|
|
9
|
+
var restoreExec = function () {
|
|
10
|
+
child_process.exec = originalExec;
|
|
11
|
+
};
|
|
12
|
+
var mockExec = function () {
|
|
13
|
+
child_process.exec.mockImplementation(function (_command, callback) { return callback(null, { stdout: '' }); });
|
|
14
|
+
};
|
|
6
15
|
describe('Wizard', function () {
|
|
16
|
+
beforeEach(function () {
|
|
17
|
+
mockExec();
|
|
18
|
+
});
|
|
19
|
+
afterEach(function () {
|
|
20
|
+
restoreExec();
|
|
21
|
+
});
|
|
7
22
|
describe('React Native', function () {
|
|
8
23
|
test('run', function () {
|
|
9
24
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Setup.js","sourceRoot":"","sources":["../../../lib/__tests__/Setup.ts"],"names":[],"mappings":";;AAAA,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,4CAA4C;AAC5E,0CAAqD;AACrD,kCAA+B;AAE/B,QAAQ,CAAC,QAAQ,EAAE;IACjB,QAAQ,CAAC,cAAc,EAAE;QACvB,IAAI,CAAC,KAAK,EAAE;YACV,mEAAmE;YACnE,MAAM,CACJ,WAAG,CAAC;gBACF,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,uBAAW,CAAC,WAAW;gBACpC,QAAQ,EAAE,CAAC,oBAAQ,CAAC,GAAG,EAAE,oBAAQ,CAAC,OAAO,CAAC;gBAC1C,WAAW,EAAE,IAAI;aAClB,CAAC,CACH,CAAC,UAAU,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["jest.mock('../Helper/Logging'); // We mock logging to not pollute the output\nimport { Integration, Platform } from '../Constants';\nimport { run } from '../Setup';\n\ndescribe('Wizard', () => {\n describe('React Native', () => {\n test('run', () => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n expect(\n run({\n quiet: true,\n integration: Integration.reactNative,\n platform: [Platform.ios, Platform.android],\n skipConnect: true,\n }),\n ).toBeTruthy();\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"Setup.js","sourceRoot":"","sources":["../../../lib/__tests__/Setup.ts"],"names":[],"mappings":";;AAAA,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,4CAA4C;AAC5E,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC3B,6CAA+C;AAE/C,0CAAqD;AACrD,kCAA+B;AAE/B,IAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC;AAExC,IAAM,WAAW,GAAG;IACjB,aAAqB,CAAC,IAAI,GAAG,YAAY,CAAC;AAC7C,CAAC,CAAC;AAEF,IAAM,QAAQ,GAAG;IACb,aAAa,CAAC,IAA8B,CAAC,kBAAkB,CAC/D,UAAC,QAAQ,EAAE,QAAQ,IAAK,OAAA,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAA9B,CAA8B,CACvD,CAAC;AACJ,CAAC,CAAC;AAEF,QAAQ,CAAC,QAAQ,EAAE;IACjB,UAAU,CAAC;QACT,QAAQ,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACR,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE;QACvB,IAAI,CAAC,KAAK,EAAE;YACV,mEAAmE;YACnE,MAAM,CACJ,WAAG,CAAC;gBACF,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,uBAAW,CAAC,WAAW;gBACpC,QAAQ,EAAE,CAAC,oBAAQ,CAAC,GAAG,EAAE,oBAAQ,CAAC,OAAO,CAAC;gBAC1C,WAAW,EAAE,IAAI;aAClB,CAAC,CACH,CAAC,UAAU,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["jest.mock('../Helper/Logging'); // We mock logging to not pollute the output\njest.mock('child_process');\nimport * as child_process from 'child_process';\n\nimport { Integration, Platform } from '../Constants';\nimport { run } from '../Setup';\n\nconst originalExec = child_process.exec;\n\nconst restoreExec = (): void => {\n (child_process as any).exec = originalExec;\n};\n\nconst mockExec = (): void => {\n ((child_process.exec as unknown) as jest.Mock).mockImplementation(\n (_command, callback) => callback(null, { stdout: '' }),\n );\n};\n\ndescribe('Wizard', () => {\n beforeEach(() => {\n mockExec();\n });\n\n afterEach(() => {\n restoreExec();\n });\n\n describe('React Native', () => {\n test('run', () => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n expect(\n run({\n quiet: true,\n integration: Integration.reactNative,\n platform: [Platform.ios, Platform.android],\n skipConnect: true,\n }),\n ).toBeTruthy();\n });\n });\n});\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as _ from 'lodash';
|
|
2
|
+
import { satisfies, subset, valid, validRange } from 'semver';
|
|
3
|
+
|
|
4
|
+
import { green, red } from './Logging';
|
|
5
|
+
|
|
6
|
+
export function checkPackageVersion(
|
|
7
|
+
appPackage: unknown,
|
|
8
|
+
packageName: string,
|
|
9
|
+
acceptableVersions: string,
|
|
10
|
+
canBeLatest: boolean,
|
|
11
|
+
): boolean {
|
|
12
|
+
const depsVersion = _.get(appPackage, ['dependencies', packageName]);
|
|
13
|
+
const devDepsVersion = _.get(appPackage, ['devDependencies', packageName]);
|
|
14
|
+
|
|
15
|
+
if (!depsVersion && !devDepsVersion) {
|
|
16
|
+
red(`✗ ${packageName} isn't in your dependencies.`);
|
|
17
|
+
red(' Please install it with yarn/npm.');
|
|
18
|
+
return false;
|
|
19
|
+
} else if (
|
|
20
|
+
!fulfillsVersionRange(depsVersion, acceptableVersions, canBeLatest) &&
|
|
21
|
+
!fulfillsVersionRange(devDepsVersion, acceptableVersions, canBeLatest)
|
|
22
|
+
) {
|
|
23
|
+
red(
|
|
24
|
+
`✗ Your \`package.json\` specifies a version of \`${packageName}\` outside of the compatible version range ${acceptableVersions}.\n`,
|
|
25
|
+
);
|
|
26
|
+
return false;
|
|
27
|
+
} else {
|
|
28
|
+
green(
|
|
29
|
+
`✓ A compatible version of \`${packageName}\` is specified in \`package.json\`.`,
|
|
30
|
+
);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function fulfillsVersionRange(
|
|
36
|
+
version: string,
|
|
37
|
+
acceptableVersions: string,
|
|
38
|
+
canBeLatest: boolean,
|
|
39
|
+
): boolean {
|
|
40
|
+
if (version === 'latest') {
|
|
41
|
+
return canBeLatest;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let cleanedUserVersion, isRange;
|
|
45
|
+
|
|
46
|
+
if (valid(version)) {
|
|
47
|
+
cleanedUserVersion = valid(version);
|
|
48
|
+
isRange = false;
|
|
49
|
+
} else if (validRange(version)) {
|
|
50
|
+
cleanedUserVersion = validRange(version);
|
|
51
|
+
isRange = true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
// If the given version is a bogus format, this will still be undefined and we'll automatically reject it
|
|
56
|
+
!!cleanedUserVersion &&
|
|
57
|
+
(isRange
|
|
58
|
+
? subset(cleanedUserVersion, acceptableVersions)
|
|
59
|
+
: satisfies(cleanedUserVersion, acceptableVersions))
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
import { green } from './Logging';
|
|
8
|
+
|
|
9
|
+
export function getPackageMangerChoice(): PackageManager | null {
|
|
10
|
+
if (fs.existsSync(path.join(process.cwd(), Yarn.LOCK_FILE))) {
|
|
11
|
+
return new Yarn();
|
|
12
|
+
}
|
|
13
|
+
if (fs.existsSync(path.join(process.cwd(), Pnpm.LOCK_FILE))) {
|
|
14
|
+
return new Pnpm();
|
|
15
|
+
}
|
|
16
|
+
if (fs.existsSync(path.join(process.cwd(), Npm.LOCK_FILE))) {
|
|
17
|
+
return new Npm();
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PackageManager {
|
|
23
|
+
installPackage(packageName: string): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class Npm implements PackageManager {
|
|
27
|
+
public static LOCK_FILE = 'package-lock.json';
|
|
28
|
+
public static LABEL = 'npm';
|
|
29
|
+
public static INSTALL_COMMAND = 'npm install';
|
|
30
|
+
|
|
31
|
+
public async installPackage(packageName: string): Promise<void> {
|
|
32
|
+
await installPackage(Npm.INSTALL_COMMAND, packageName, Npm.LABEL);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class Yarn implements PackageManager {
|
|
37
|
+
public static LOCK_FILE = 'yarn.lock';
|
|
38
|
+
public static LABEL = 'yarn';
|
|
39
|
+
public static INSTALL_COMMAND = 'yarn add';
|
|
40
|
+
|
|
41
|
+
public async installPackage(packageName: string): Promise<void> {
|
|
42
|
+
await installPackage(Yarn.INSTALL_COMMAND, packageName, Yarn.LABEL);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class Pnpm implements PackageManager {
|
|
47
|
+
public static LOCK_FILE = 'pnpm-lock.yaml';
|
|
48
|
+
public static LABEL = 'pnpm';
|
|
49
|
+
public static INSTALL_COMMAND = 'pnpm add';
|
|
50
|
+
|
|
51
|
+
public async installPackage(packageName: string): Promise<void> {
|
|
52
|
+
await installPackage(Pnpm.INSTALL_COMMAND, packageName, Pnpm.LABEL);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function installPackage(
|
|
57
|
+
command: string,
|
|
58
|
+
packageName: string,
|
|
59
|
+
label: string,
|
|
60
|
+
): Promise<void> {
|
|
61
|
+
await promisify(exec)(`${command} ${packageName}`);
|
|
62
|
+
green(`✓ Added \`${packageName}\` using \`${label}\`.`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
package/lib/Helper/Wizard.ts
CHANGED
|
@@ -10,7 +10,7 @@ const templatePath = path.join(
|
|
|
10
10
|
'..',
|
|
11
11
|
'..',
|
|
12
12
|
'..',
|
|
13
|
-
'scripts/
|
|
13
|
+
'scripts/NextJs/configs/next.config.template.js',
|
|
14
14
|
);
|
|
15
15
|
|
|
16
16
|
function configFileNames(num: number): {
|
|
@@ -31,47 +31,63 @@ function configFileNames(num: number): {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
describe('Merging next.config.js', () => {
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
fs.unlinkSync(configPath);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('merge basic next.config.js return true', () => {
|
|
40
|
+
const { sourcePath } = configFileNames(1);
|
|
41
|
+
fs.copyFileSync(sourcePath, configPath);
|
|
42
|
+
|
|
43
|
+
expect(mergeConfigFile(configPath, templatePath)).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
34
46
|
test('merge basic next.config.js', () => {
|
|
35
47
|
const { sourcePath, mergedPath } = configFileNames(1);
|
|
36
48
|
fs.copyFileSync(sourcePath, configPath);
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
fs.readFileSync(mergedPath, 'utf8'),
|
|
42
|
-
).toBe(true);
|
|
43
|
-
fs.unlinkSync(configPath);
|
|
50
|
+
mergeConfigFile(configPath, templatePath);
|
|
51
|
+
|
|
52
|
+
expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
|
|
44
53
|
});
|
|
45
54
|
|
|
46
|
-
test('merge invalid javascript config', () => {
|
|
55
|
+
test('merge invalid javascript config return false', () => {
|
|
47
56
|
const { sourcePath } = configFileNames(2);
|
|
48
57
|
fs.copyFileSync(sourcePath, configPath);
|
|
49
58
|
|
|
50
59
|
expect(mergeConfigFile(configPath, templatePath)).toBe(false);
|
|
51
|
-
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('merge more complicated next.config.js return true', () => {
|
|
63
|
+
const { sourcePath } = configFileNames(3);
|
|
64
|
+
fs.copyFileSync(sourcePath, configPath);
|
|
65
|
+
|
|
66
|
+
expect(mergeConfigFile(configPath, templatePath)).toBe(true);
|
|
52
67
|
});
|
|
53
68
|
|
|
54
69
|
test('merge more complicated next.config.js', () => {
|
|
55
70
|
const { sourcePath, mergedPath } = configFileNames(3);
|
|
56
71
|
fs.copyFileSync(sourcePath, configPath);
|
|
57
72
|
|
|
73
|
+
mergeConfigFile(configPath, templatePath);
|
|
74
|
+
|
|
75
|
+
expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('merge next.config.js with function return true', () => {
|
|
79
|
+
const { sourcePath } = configFileNames(4);
|
|
80
|
+
fs.copyFileSync(sourcePath, configPath);
|
|
81
|
+
|
|
58
82
|
expect(mergeConfigFile(configPath, templatePath)).toBe(true);
|
|
59
|
-
expect(
|
|
60
|
-
fs.readFileSync(configPath, 'utf8') ===
|
|
61
|
-
fs.readFileSync(mergedPath, 'utf8'),
|
|
62
|
-
).toBe(true);
|
|
63
|
-
fs.unlinkSync(configPath);
|
|
64
83
|
});
|
|
65
84
|
|
|
66
85
|
test('merge next.config.js with function', () => {
|
|
67
86
|
const { sourcePath, mergedPath } = configFileNames(4);
|
|
68
87
|
fs.copyFileSync(sourcePath, configPath);
|
|
69
88
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
fs.readFileSync(mergedPath, 'utf8'),
|
|
74
|
-
).toBe(true);
|
|
75
|
-
fs.unlinkSync(configPath);
|
|
89
|
+
mergeConfigFile(configPath, templatePath);
|
|
90
|
+
|
|
91
|
+
expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
|
|
76
92
|
});
|
|
77
93
|
});
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
import Chalk from 'chalk';
|
|
3
|
-
import { exec } from 'child_process';
|
|
4
3
|
import * as fs from 'fs';
|
|
5
4
|
import { Answers, prompt } from 'inquirer';
|
|
6
5
|
import * as _ from 'lodash';
|
|
7
6
|
import * as path from 'path';
|
|
8
7
|
import { satisfies, subset, valid, validRange } from 'semver';
|
|
9
|
-
import { promisify } from 'util';
|
|
10
8
|
|
|
11
9
|
import { Args } from '../../Constants';
|
|
12
10
|
import { debug, green, l, nl, red } from '../../Helper/Logging';
|
|
13
11
|
import { mergeConfigFile } from '../../Helper/MergeConfig';
|
|
12
|
+
import { checkPackageVersion } from '../../Helper/Package';
|
|
13
|
+
import { getPackageMangerChoice } from '../../Helper/PackageManager';
|
|
14
14
|
import { SentryCli, SentryCliProps } from '../../Helper/SentryCli';
|
|
15
15
|
import { BaseIntegration } from './BaseIntegration';
|
|
16
16
|
|
|
17
|
-
type PackageManager = 'yarn' | 'npm' | 'pnpm';
|
|
18
|
-
|
|
19
17
|
const COMPATIBLE_NEXTJS_VERSIONS = '>=10.0.8 <14.0.0';
|
|
20
18
|
const COMPATIBLE_SDK_VERSIONS = '>=7.3.0';
|
|
21
19
|
const PROPERTIES_FILENAME = 'sentry.properties';
|
|
@@ -110,24 +108,26 @@ export class NextJs extends BaseIntegration {
|
|
|
110
108
|
nl();
|
|
111
109
|
|
|
112
110
|
let userAnswers: Answers = { continue: true };
|
|
113
|
-
const hasCompatibleNextjsVersion =
|
|
111
|
+
const hasCompatibleNextjsVersion = checkPackageVersion(
|
|
112
|
+
appPackage,
|
|
114
113
|
'next',
|
|
115
114
|
COMPATIBLE_NEXTJS_VERSIONS,
|
|
116
115
|
true,
|
|
117
116
|
);
|
|
118
117
|
|
|
119
|
-
const packageManager =
|
|
118
|
+
const packageManager = getPackageMangerChoice();
|
|
120
119
|
const hasSdkInstalled = this._hasPackageInstalled('@sentry/nextjs');
|
|
121
120
|
|
|
122
121
|
let hasCompatibleSdkVersion = false;
|
|
123
122
|
// if no package but we have nextjs, let's add it if we can
|
|
124
123
|
if (!hasSdkInstalled && packageManager && hasCompatibleNextjsVersion) {
|
|
125
|
-
await
|
|
124
|
+
await packageManager.installPackage('@sentry/nextjs');
|
|
126
125
|
// can assume it's compatible since we just installed it
|
|
127
126
|
hasCompatibleSdkVersion = true;
|
|
128
127
|
} else {
|
|
129
128
|
// otherwise, let's check the version and spit out the appropriate error
|
|
130
|
-
hasCompatibleSdkVersion =
|
|
129
|
+
hasCompatibleSdkVersion = checkPackageVersion(
|
|
130
|
+
appPackage,
|
|
131
131
|
'@sentry/nextjs',
|
|
132
132
|
COMPATIBLE_SDK_VERSIONS,
|
|
133
133
|
true,
|
|
@@ -348,106 +348,6 @@ export class NextJs extends BaseIntegration {
|
|
|
348
348
|
return !!depsVersion || !!devDepsVersion;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
-
private _getPackageMangerChoice(): PackageManager | null {
|
|
352
|
-
if (fs.existsSync(path.join(process.cwd(), 'yarn.lock'))) {
|
|
353
|
-
return 'yarn';
|
|
354
|
-
}
|
|
355
|
-
if (fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml'))) {
|
|
356
|
-
return 'pnpm';
|
|
357
|
-
}
|
|
358
|
-
if (fs.existsSync(path.join(process.cwd(), 'package-lock.json'))) {
|
|
359
|
-
return 'npm';
|
|
360
|
-
}
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
private _getInstallCommand(packageManager: PackageManager): string {
|
|
365
|
-
switch (packageManager) {
|
|
366
|
-
case 'yarn':
|
|
367
|
-
return 'yarn add';
|
|
368
|
-
case 'pnpm':
|
|
369
|
-
return 'pnpm add';
|
|
370
|
-
case 'npm':
|
|
371
|
-
return 'npm install';
|
|
372
|
-
default:
|
|
373
|
-
throw new Error(`Unknown package manager: ${packageManager}`);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
private async _installPackage(
|
|
378
|
-
packageName: string,
|
|
379
|
-
packageManager: PackageManager,
|
|
380
|
-
): Promise<void> {
|
|
381
|
-
const command = this._getInstallCommand(packageManager);
|
|
382
|
-
await promisify(exec)(`${command} ${packageName}`);
|
|
383
|
-
green(`✓ Added \`${packageName}\` using \`${command}\`.`);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
private _checkPackageVersion(
|
|
388
|
-
packageName: string,
|
|
389
|
-
acceptableVersions: string,
|
|
390
|
-
canBeLatest: boolean,
|
|
391
|
-
): boolean {
|
|
392
|
-
const depsVersion = _.get(appPackage, ['dependencies', packageName]);
|
|
393
|
-
const devDepsVersion = _.get(appPackage, ['devDependencies', packageName]);
|
|
394
|
-
|
|
395
|
-
if (!depsVersion && !devDepsVersion) {
|
|
396
|
-
red(`✗ ${packageName} isn't in your dependencies.`);
|
|
397
|
-
red(' Please install it with yarn/npm.');
|
|
398
|
-
return false;
|
|
399
|
-
} else if (
|
|
400
|
-
!this._fulfillsVersionRange(
|
|
401
|
-
depsVersion,
|
|
402
|
-
acceptableVersions,
|
|
403
|
-
canBeLatest,
|
|
404
|
-
) &&
|
|
405
|
-
!this._fulfillsVersionRange(
|
|
406
|
-
devDepsVersion,
|
|
407
|
-
acceptableVersions,
|
|
408
|
-
canBeLatest,
|
|
409
|
-
)
|
|
410
|
-
) {
|
|
411
|
-
red(
|
|
412
|
-
`✗ Your \`package.json\` specifies a version of \`${packageName}\` outside of the compatible version range ${acceptableVersions}.\n`,
|
|
413
|
-
);
|
|
414
|
-
return false;
|
|
415
|
-
} else {
|
|
416
|
-
green(
|
|
417
|
-
`✓ A compatible version of \`${packageName}\` is specified in \`package.json\`.`,
|
|
418
|
-
);
|
|
419
|
-
return true;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
private _fulfillsVersionRange(
|
|
424
|
-
version: string,
|
|
425
|
-
acceptableVersions: string,
|
|
426
|
-
canBeLatest: boolean,
|
|
427
|
-
): boolean {
|
|
428
|
-
if (version === 'latest') {
|
|
429
|
-
return canBeLatest;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
let cleanedUserVersion, isRange;
|
|
433
|
-
|
|
434
|
-
if (valid(version)) {
|
|
435
|
-
cleanedUserVersion = valid(version);
|
|
436
|
-
isRange = false;
|
|
437
|
-
} else if (validRange(version)) {
|
|
438
|
-
cleanedUserVersion = validRange(version);
|
|
439
|
-
isRange = true;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
return (
|
|
443
|
-
// If the given version is a bogus format, this will still be undefined and we'll automatically reject it
|
|
444
|
-
!!cleanedUserVersion &&
|
|
445
|
-
(isRange
|
|
446
|
-
? subset(cleanedUserVersion, acceptableVersions)
|
|
447
|
-
: satisfies(cleanedUserVersion, acceptableVersions))
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
351
|
private _spliceInPlace(
|
|
452
352
|
arr: Array<any>,
|
|
453
353
|
start: number,
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
|
+
import { exec } from 'child_process';
|
|
2
3
|
import * as fs from 'fs';
|
|
3
|
-
import { Answers } from 'inquirer';
|
|
4
|
+
import { Answers, prompt } from 'inquirer';
|
|
4
5
|
import * as _ from 'lodash';
|
|
5
6
|
import * as path from 'path';
|
|
7
|
+
import { promisify } from 'util';
|
|
6
8
|
|
|
7
9
|
import { Args } from '../../Constants';
|
|
8
10
|
import { exists, matchesContent, matchFiles, patchMatchingFile } from '../../Helper/File';
|
|
9
|
-
import { dim, green,
|
|
11
|
+
import { dim, green, nl, red } from '../../Helper/Logging';
|
|
12
|
+
import { checkPackageVersion } from '../../Helper/Package';
|
|
13
|
+
import { getPackageMangerChoice } from '../../Helper/PackageManager';
|
|
10
14
|
import { SentryCli } from '../../Helper/SentryCli';
|
|
11
15
|
import { MobileProject } from './MobileProject';
|
|
12
16
|
|
|
13
17
|
const xcode = require('xcode');
|
|
14
18
|
|
|
19
|
+
export const COMPATIBLE_REACT_NATIVE_VERSIONS = '>=0.69.0';
|
|
20
|
+
export const COMPATIBLE_SDK_VERSION = '>= 5.0.0';
|
|
21
|
+
|
|
22
|
+
export const SENTRY_REACT_NATIVE_PACKAGE = '@sentry/react-native';
|
|
23
|
+
export const REACT_NATIVE_PACKAGE = 'react-native';
|
|
24
|
+
|
|
25
|
+
export const DOCS_MANUAL_STEPS = 'https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/'
|
|
26
|
+
|
|
15
27
|
export class ReactNative extends MobileProject {
|
|
16
28
|
|
|
17
29
|
/**
|
|
@@ -34,43 +46,86 @@ export class ReactNative extends MobileProject {
|
|
|
34
46
|
if (!(await this.shouldEmit(answers))) {
|
|
35
47
|
return {};
|
|
36
48
|
}
|
|
49
|
+
nl();
|
|
50
|
+
|
|
51
|
+
let userAnswers: Answers = { continue: true };
|
|
52
|
+
const packageManager = getPackageMangerChoice();
|
|
53
|
+
|
|
54
|
+
const hasCompatibleReactNativeVersion = checkPackageVersion(
|
|
55
|
+
this._readAppPackage(),
|
|
56
|
+
REACT_NATIVE_PACKAGE,
|
|
57
|
+
COMPATIBLE_REACT_NATIVE_VERSIONS,
|
|
58
|
+
true,
|
|
59
|
+
);
|
|
60
|
+
if (!hasCompatibleReactNativeVersion && !this._argv.quiet) {
|
|
61
|
+
userAnswers = await prompt({
|
|
62
|
+
message: `Your version of React Native is not compatible with Sentry's React Native SDK. Do you want to continue?`,
|
|
63
|
+
name: 'continue',
|
|
64
|
+
default: false,
|
|
65
|
+
type: 'confirm',
|
|
66
|
+
});
|
|
67
|
+
nl();
|
|
68
|
+
}
|
|
69
|
+
if (!userAnswers.continue) {
|
|
70
|
+
throw new Error(`Please upgrade to a version that is compatible with ${COMPATIBLE_REACT_NATIVE_VERSIONS}. Or use ${DOCS_MANUAL_STEPS}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (packageManager) {
|
|
74
|
+
await packageManager.installPackage(SENTRY_REACT_NATIVE_PACKAGE);
|
|
75
|
+
}
|
|
76
|
+
const hasCompatibleSentryReactNativeVersion = checkPackageVersion(
|
|
77
|
+
this._readAppPackage(),
|
|
78
|
+
SENTRY_REACT_NATIVE_PACKAGE,
|
|
79
|
+
COMPATIBLE_SDK_VERSION,
|
|
80
|
+
true,
|
|
81
|
+
);
|
|
82
|
+
if (!hasCompatibleSentryReactNativeVersion && !this._argv.quiet) {
|
|
83
|
+
userAnswers = await prompt({
|
|
84
|
+
message: `Your version of ${SENTRY_REACT_NATIVE_PACKAGE} is not compatible with this wizard. Do you want to continue?`,
|
|
85
|
+
name: 'continue',
|
|
86
|
+
default: false,
|
|
87
|
+
type: 'confirm',
|
|
88
|
+
});
|
|
89
|
+
nl();
|
|
90
|
+
}
|
|
91
|
+
if (!userAnswers.continue) {
|
|
92
|
+
throw new Error(`Please upgrade to a version that is compatible with ${COMPATIBLE_SDK_VERSION}.`);
|
|
93
|
+
}
|
|
37
94
|
|
|
38
95
|
const sentryCliProperties = this._sentryCli.convertAnswersToProperties(
|
|
39
96
|
answers,
|
|
40
97
|
);
|
|
41
98
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
await this._patchJsSentryInit(platform, answers);
|
|
61
|
-
await this._addSentryProperties(platform, sentryCliProperties);
|
|
62
|
-
dim(`✅ Added sentry.properties file to ${platform}`);
|
|
63
|
-
|
|
64
|
-
green(`Successfully set up ${platform} for react-native`);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
red(e);
|
|
99
|
+
const promises = this.getPlatforms(answers).map(
|
|
100
|
+
async (platform: string) => {
|
|
101
|
+
try {
|
|
102
|
+
if (platform === 'ios') {
|
|
103
|
+
await patchMatchingFile(
|
|
104
|
+
'ios/*.xcodeproj/project.pbxproj',
|
|
105
|
+
this._patchXcodeProj.bind(this),
|
|
106
|
+
);
|
|
107
|
+
green(`✓ Patched build script in Xcode project.`);
|
|
108
|
+
await this._podInstall();
|
|
109
|
+
green(`✓ Pods installed.`);
|
|
110
|
+
} else {
|
|
111
|
+
await patchMatchingFile(
|
|
112
|
+
'**/app/build.gradle',
|
|
113
|
+
this._patchBuildGradle.bind(this),
|
|
114
|
+
);
|
|
115
|
+
green(`✓ Patched build.gradle file.`);
|
|
67
116
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
117
|
+
await this._patchJsSentryInit(platform, answers);
|
|
118
|
+
await this._addSentryProperties(platform, sentryCliProperties);
|
|
119
|
+
green(`✓ Added sentry.properties file to ${platform}`);
|
|
120
|
+
} catch (e) {
|
|
121
|
+
red(e);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
await Promise.all(promises);
|
|
127
|
+
|
|
128
|
+
return answers;
|
|
74
129
|
}
|
|
75
130
|
|
|
76
131
|
public async uninstall(_answers: Answers): Promise<Answers> {
|
|
@@ -125,6 +180,22 @@ export class ReactNative extends MobileProject {
|
|
|
125
180
|
return result;
|
|
126
181
|
}
|
|
127
182
|
|
|
183
|
+
private _readAppPackage(): Record<string, unknown> {
|
|
184
|
+
let appPackage: Record<string, unknown> = {};
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
appPackage = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
|
|
188
|
+
} catch {
|
|
189
|
+
// We don't need to have this
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return appPackage;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private async _podInstall(): Promise<void> {
|
|
196
|
+
await promisify(exec)('npx --yes pod-install --non-interactive --quiet');
|
|
197
|
+
}
|
|
198
|
+
|
|
128
199
|
private async _patchJsSentryInit(
|
|
129
200
|
platform: string,
|
|
130
201
|
answers: Answers,
|
|
@@ -144,10 +215,10 @@ export class ReactNative extends MobileProject {
|
|
|
144
215
|
answers,
|
|
145
216
|
platform,
|
|
146
217
|
);
|
|
147
|
-
|
|
218
|
+
green(`✓ Patched ${jsFileToPatch.join(', ')} file(s).`);
|
|
148
219
|
} else {
|
|
149
|
-
|
|
150
|
-
|
|
220
|
+
red(`✗ Could not find ${platformGlob} nor ${universalGlob} files.`);
|
|
221
|
+
red('✗ Please, visit https://docs.sentry.io/platforms/react-native');
|
|
151
222
|
}
|
|
152
223
|
}
|
|
153
224
|
|
|
@@ -290,7 +361,7 @@ export class ReactNative extends MobileProject {
|
|
|
290
361
|
shellScript:`
|
|
291
362
|
export SENTRY_PROPERTIES=sentry.properties
|
|
292
363
|
[[ $SENTRY_INCLUDE_NATIVE_SOURCES == "true" ]] && INCLUDE_SOURCES_FLAG="--include-sources" || INCLUDE_SOURCES_FLAG=""
|
|
293
|
-
../node_modules/@sentry/cli/bin/sentry-cli debug-files upload "$INCLUDE_SOURCES_FLAG"
|
|
364
|
+
../node_modules/@sentry/cli/bin/sentry-cli debug-files upload "$INCLUDE_SOURCES_FLAG" "$DWARF_DSYM_FOLDER_PATH"
|
|
294
365
|
`,
|
|
295
366
|
},
|
|
296
367
|
);
|