Skip to content

Commit

Permalink
feat(rn): One line RN SDK install command (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
krystofwoldrich authored Apr 11, 2023
1 parent 6224447 commit 71f4f6a
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 165 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

- feat(rn): One line `@sentry/react-native` setup command ([#243](https://github.com/getsentry/sentry-wizard/pull/243))

```bash
npx @sentry/wizard -s -i reactNative
```

## 2.6.1

- fix(rn): Upload debug files from `$DWARF_DSYM_FOLDER_PATH` during Xcode build ([#240](https://github.com/getsentry/sentry-wizard/pull/240))
Expand Down
61 changes: 61 additions & 0 deletions lib/Helper/Package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as _ from 'lodash';
import { satisfies, subset, valid, validRange } from 'semver';

import { green, red } from './Logging';

export function checkPackageVersion(
appPackage: unknown,
packageName: string,
acceptableVersions: string,
canBeLatest: boolean,
): boolean {
const depsVersion = _.get(appPackage, ['dependencies', packageName]);
const devDepsVersion = _.get(appPackage, ['devDependencies', packageName]);

if (!depsVersion && !devDepsVersion) {
red(`✗ ${packageName} isn't in your dependencies.`);
red(' Please install it with yarn/npm.');
return false;
} else if (
!fulfillsVersionRange(depsVersion, acceptableVersions, canBeLatest) &&
!fulfillsVersionRange(devDepsVersion, acceptableVersions, canBeLatest)
) {
red(
`✗ Your \`package.json\` specifies a version of \`${packageName}\` outside of the compatible version range ${acceptableVersions}.\n`,
);
return false;
} else {
green(
`✓ A compatible version of \`${packageName}\` is specified in \`package.json\`.`,
);
return true;
}
}

function fulfillsVersionRange(
version: string,
acceptableVersions: string,
canBeLatest: boolean,
): boolean {
if (version === 'latest') {
return canBeLatest;
}

let cleanedUserVersion, isRange;

if (valid(version)) {
cleanedUserVersion = valid(version);
isRange = false;
} else if (validRange(version)) {
cleanedUserVersion = validRange(version);
isRange = true;
}

return (
// If the given version is a bogus format, this will still be undefined and we'll automatically reject it
!!cleanedUserVersion &&
(isRange
? subset(cleanedUserVersion, acceptableVersions)
: satisfies(cleanedUserVersion, acceptableVersions))
);
}
64 changes: 64 additions & 0 deletions lib/Helper/PackageManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable @typescript-eslint/typedef */
import { exec } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';

import { green } from './Logging';

export function getPackageMangerChoice(): PackageManager | null {
if (fs.existsSync(path.join(process.cwd(), Yarn.LOCK_FILE))) {
return new Yarn();
}
if (fs.existsSync(path.join(process.cwd(), Pnpm.LOCK_FILE))) {
return new Pnpm();
}
if (fs.existsSync(path.join(process.cwd(), Npm.LOCK_FILE))) {
return new Npm();
}
return null;
}

export interface PackageManager {
installPackage(packageName: string): Promise<void>;
}

export class Npm implements PackageManager {
public static LOCK_FILE = 'package-lock.json';
public static LABEL = 'npm';
public static INSTALL_COMMAND = 'npm install';

public async installPackage(packageName: string): Promise<void> {
await installPackage(Npm.INSTALL_COMMAND, packageName, Npm.LABEL);
}
}

export class Yarn implements PackageManager {
public static LOCK_FILE = 'yarn.lock';
public static LABEL = 'yarn';
public static INSTALL_COMMAND = 'yarn add';

public async installPackage(packageName: string): Promise<void> {
await installPackage(Yarn.INSTALL_COMMAND, packageName, Yarn.LABEL);
}
}

export class Pnpm implements PackageManager {
public static LOCK_FILE = 'pnpm-lock.yaml';
public static LABEL = 'pnpm';
public static INSTALL_COMMAND = 'pnpm add';

public async installPackage(packageName: string): Promise<void> {
await installPackage(Pnpm.INSTALL_COMMAND, packageName, Pnpm.LABEL);
}
}

async function installPackage(
command: string,
packageName: string,
label: string,
): Promise<void> {
await promisify(exec)(`${command} ${packageName}`);
green(`✓ Added \`${packageName}\` using \`${label}\`.`);
return;
}
2 changes: 1 addition & 1 deletion lib/Helper/Wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ export async function startWizard<M extends IStep>(
nl();
red('Protip: Add --debug to see whats going on');
red('OR use --help to see your options');
return {};
process.exit(1);
}
}
56 changes: 36 additions & 20 deletions lib/Helper/__tests__/MergeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const templatePath = path.join(
'..',
'..',
'..',
'scripts/NextJS/configs/next.config.template.js',
'scripts/NextJs/configs/next.config.template.js',
);

function configFileNames(num: number): {
Expand All @@ -31,47 +31,63 @@ function configFileNames(num: number): {
}

describe('Merging next.config.js', () => {

afterEach(() => {
fs.unlinkSync(configPath);
});

test('merge basic next.config.js return true', () => {
const { sourcePath } = configFileNames(1);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(true);
});

test('merge basic next.config.js', () => {
const { sourcePath, mergedPath } = configFileNames(1);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(true);
expect(
fs.readFileSync(configPath, 'utf8') ===
fs.readFileSync(mergedPath, 'utf8'),
).toBe(true);
fs.unlinkSync(configPath);
mergeConfigFile(configPath, templatePath);

expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
});

test('merge invalid javascript config', () => {
test('merge invalid javascript config return false', () => {
const { sourcePath } = configFileNames(2);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(false);
fs.unlinkSync(configPath);
});

test('merge more complicated next.config.js return true', () => {
const { sourcePath } = configFileNames(3);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(true);
});

test('merge more complicated next.config.js', () => {
const { sourcePath, mergedPath } = configFileNames(3);
fs.copyFileSync(sourcePath, configPath);

mergeConfigFile(configPath, templatePath);

expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
});

test('merge next.config.js with function return true', () => {
const { sourcePath } = configFileNames(4);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(true);
expect(
fs.readFileSync(configPath, 'utf8') ===
fs.readFileSync(mergedPath, 'utf8'),
).toBe(true);
fs.unlinkSync(configPath);
});

test('merge next.config.js with function', () => {
const { sourcePath, mergedPath } = configFileNames(4);
fs.copyFileSync(sourcePath, configPath);

expect(mergeConfigFile(configPath, templatePath)).toBe(true);
expect(
fs.readFileSync(configPath, 'utf8') ===
fs.readFileSync(mergedPath, 'utf8'),
).toBe(true);
fs.unlinkSync(configPath);
mergeConfigFile(configPath, templatePath);

expect(fs.readFileSync(configPath, 'utf8')).toEqual(fs.readFileSync(mergedPath, 'utf8'));
});
});
Loading

0 comments on commit 71f4f6a

Please sign in to comment.