-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): add presetVersion flag for the CNW
- Loading branch information
1 parent
5f86929
commit bcf8876
Showing
9 changed files
with
120 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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' | ||
|
@@ -94,6 +102,48 @@ describe('new', () => { | |
typescript: typescriptVersion, | ||
}); | ||
}); | ||
|
||
describe('custom presets', () => { | ||
// 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 }) => { | ||
await newGenerator(tree, { | ||
...defaultOptions, | ||
name: 'my-workspace', | ||
directory: 'my-workspace', | ||
npmScope: 'npmScope', | ||
appName: 'app', | ||
preset, | ||
presetVersion, | ||
}); | ||
|
||
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 () => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ interface Schema { | |
style?: string; | ||
nxCloud?: boolean; | ||
preset: string; | ||
presetVersion?: string | number; // number is needed so that generator doesn't fail on numeric-like strings (e.g. "14") | ||
defaultBase: string; | ||
framework?: string; | ||
docker?: boolean; | ||
|
@@ -92,23 +93,38 @@ 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 SCOPED_PACKAGE = /^(@[^\/]+\/[^@\/]+)(?:@([^\/]+))?$/; | ||
const NON_SCOPED_PACKAGE = /^([^@\/]+)(?:@([^\/]+))?$/; | ||
const match = input.match(SCOPED_PACKAGE) || input.match(NON_SCOPED_PACKAGE); | ||
if (!match?.[0]) { | ||
throw new Error(`Invalid package name: ${input}`); | ||
} | ||
return { | ||
package: match[1], | ||
version: match[2], | ||
}; | ||
} | ||
|
||
function normalizeOptions(options: Schema): NormalizedSchema { | ||
const normalized: Partial<NormalizedSchema> = { ...options }; | ||
const normalized: Partial<NormalizedSchema> = { | ||
...options, | ||
presetVersion: options.presetVersion?.toString(), | ||
}; | ||
|
||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 17 additions & 7 deletions
24
packages/workspace/src/generators/utils/get-npm-package-version.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |