Skip to content

Commit

Permalink
feat(core): add presetVersion flag for the create-nx-workspace (#16303)
Browse files Browse the repository at this point in the history
Co-authored-by: FrozenPandaz <[email protected]>
  • Loading branch information
dmitry-stepanenko and FrozenPandaz authored Apr 17, 2023
1 parent 6428294 commit dc98485
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 19 deletions.
4 changes: 3 additions & 1 deletion packages/workspace/src/generators/new/generate-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ function getPresetDependencies({
return {
dev: {},
dependencies: {
[preset]: presetVersion ?? getNpmPackageVersion(preset),
[preset]:
process.env['NX_E2E_PRESET_VERSION'] ??
getNpmPackageVersion(preset, presetVersion),
},
};
}
Expand Down
65 changes: 65 additions & 0 deletions packages/workspace/src/generators/new/new.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ import {
import { Preset } from '../utils/presets';
import { newGenerator, NormalizedSchema } from './new';

const DEFAULT_PACKAGE_VERSION = '1.0.0';
jest.mock('./../utils/get-npm-package-version', () => ({
...jest.requireActual<any>('./../utils/get-npm-package-version'),
getNpmPackageVersion: jest
.fn()
.mockImplementation((name, version) => version ?? DEFAULT_PACKAGE_VERSION),
}));

const defaultOptions: Omit<
NormalizedSchema,
'name' | 'directory' | 'appName' | 'isCustomPreset'
Expand Down Expand Up @@ -94,6 +102,63 @@ describe('new', () => {
typescript: typescriptVersion,
});
});

describe('custom presets', () => {
let originalValue;
beforeEach(() => {
originalValue = process.env['NX_E2E_PRESET_VERSION'];
});

afterEach(() => {
if (originalValue) {
process.env['NX_E2E_PRESET_VERSION'] = originalValue;
} else {
delete process.env['NX_E2E_PRESET_VERSION'];
}
});
// the process of actual resolving of a version relies on npm and is mocked here,
// thus "package@2" is expected to be resolved with version "2" instead of "2.0.0"
const versionAsPath =
'/Users/username/3rd-party-pkg/dist/packages/3rd-party-pkg-1.12.5.tgz';
test.each`
preset | presetVersion | expectedVersion
${'3rd-party-package'} | ${undefined} | ${DEFAULT_PACKAGE_VERSION}
${'[email protected]'} | ${undefined} | ${'1.1.2'}
${'3rd-party-package@2'} | ${undefined} | ${'2'}
${'3rd-party-package'} | ${'latest'} | ${'latest'}
${'3rd-party-package'} | ${'1.1.1'} | ${'1.1.1'}
${'3rd-party-package'} | ${versionAsPath} | ${versionAsPath}
${'[email protected]'} | ${'1.1.1'} | ${'1.1.1'}
`(
'should add custom preset "$preset" with a correct expectedVersion "$expectedVersion" when presetVersion is "$presetVersion"',
async ({ presetVersion, preset, expectedVersion }) => {
if (presetVersion) {
process.env['NX_E2E_PRESET_VERSION'] = presetVersion;
}

await newGenerator(tree, {
...defaultOptions,
name: 'my-workspace',
directory: 'my-workspace',
npmScope: 'npmScope',
appName: 'app',
preset,
});

const { devDependencies, dependencies } = readJson(
tree,
'my-workspace/package.json'
);
expect(dependencies).toStrictEqual({
'3rd-party-package': expectedVersion,
});
expect(devDependencies).toStrictEqual({
'@nrwl/workspace': nxVersion,
nx: nxVersion,
});
}
);
});
});

it('should not modify any existing files', async () => {
Expand Down
39 changes: 28 additions & 11 deletions packages/workspace/src/generators/new/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,40 @@ function validateOptions(options: Schema, host: Tree) {
}
}

function parsePresetName(input: string): { package: string; version?: string } {
// If the preset already contains a version in the name
// -- [email protected]
// -- @scope/package@version
const atIndex = input.indexOf('@', 1); // Skip the beginning @ because it denotes a scoped package.

if (atIndex > 0) {
return {
package: input.slice(0, atIndex),
version: input.slice(atIndex + 1),
};
} else {
if (!input) {
throw new Error(`Invalid package name: ${input}`);
}
return { package: input };
}
}

function normalizeOptions(options: Schema): NormalizedSchema {
const normalized: Partial<NormalizedSchema> = { ...options };
const normalized: Partial<NormalizedSchema> = {
...options,
};

normalized.name = names(options.name).fileName;
if (!options.directory) {
normalized.directory = options.name;
}

// If the preset already contains a version in the name
// -- [email protected]
// -- @scope/package@version
const match = options.preset.match(
/^(?<package>(@.+\/)?[^@]+)(@(?<version>\d+\.\d+\.\d+))?$/
);
if (match) {
normalized.preset = match.groups.package;
normalized.presetVersion = match.groups.version;
}
const parsed = parsePresetName(options.preset);

normalized.preset = parsed.package;
// explicitly specified "presetVersion" takes priority over the one from the package name
normalized.presetVersion ??= parsed.version;

normalized.isCustomPreset = !Object.values(Preset).includes(
options.preset as any
Expand Down
24 changes: 17 additions & 7 deletions packages/workspace/src/generators/utils/get-npm-package-version.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
export function getNpmPackageVersion(packageName: string): string | null {
export function getNpmPackageVersion(
packageName: string,
packageVersion?: string
): string | null {
try {
const version = require('child_process').execSync(
`npm view ${packageName} version`,
`npm view ${packageName}${
packageVersion ? '@' + packageVersion : ''
} version --json`,
{ stdio: ['pipe', 'pipe', 'ignore'] }
);

if (version) {
return version
.toString()
.trim()
.replace(/^\n*|\n*$/g, '');
// [email protected] => ["1.12.0", "1.12.1"]
// [email protected] => "1.12.1"
// package@latest => "1.12.1"
const versionOrArray = JSON.parse(version.toString());

if (typeof versionOrArray === 'string') {
return versionOrArray;
}
return versionOrArray.pop();
}
} catch (err) {}
return null;
return packageVersion ?? null;
}

0 comments on commit dc98485

Please sign in to comment.