From b5b88193deb6f0daddc8a3966a3d094e985c1078 Mon Sep 17 00:00:00 2001 From: Brian Chen Date: Mon, 31 Jan 2022 20:05:05 +1100 Subject: [PATCH 1/2] can match against alpha versions now --- cli/src/commands/__tests__/install-test.js | 43 ++++++++++++++++++++++ cli/src/lib/npm/npmLibDefs.js | 30 ++++++++------- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/cli/src/commands/__tests__/install-test.js b/cli/src/commands/__tests__/install-test.js index 180e0596b8..aaa015b6bf 100644 --- a/cli/src/commands/__tests__/install-test.js +++ b/cli/src/commands/__tests__/install-test.js @@ -364,6 +364,49 @@ describe('install (command)', () => { }); }); + it('installs version matched libdef for alpha versions', () => { + return fakeProjectEnv(async FLOWPROJ_DIR => { + // Create some dependencies + await Promise.all([ + touchFile(path.join(FLOWPROJ_DIR, '.flowconfig')), + writePkgJson(path.join(FLOWPROJ_DIR, 'package.json'), { + name: 'test', + devDependencies: { + 'flow-bin': '^0.43.0', + }, + dependencies: { + foo: '1.2.3-alpha.5', + }, + }), + mkdirp(path.join(FLOWPROJ_DIR, 'node_modules', 'foo')), + mkdirp(path.join(FLOWPROJ_DIR, 'node_modules', 'flow-bin')), + ]); + + // Run the install command + await run({ + ...defaultRunProps, + ignoreDeps: [], + }); + + // Installs libdefs + expect( + await Promise.all([ + fs.exists( + path.join( + FLOWPROJ_DIR, + 'flow-typed', + 'npm', + 'flow-bin_v0.x.x.js', + ), + ), + fs.exists( + path.join(FLOWPROJ_DIR, 'flow-typed', 'npm', 'foo_v1.x.x.js'), + ), + ]), + ).toEqual([true, true]); + }); + }); + it('installs available libdefs using PnP', () => { return fakeProjectEnv(async FLOWPROJ_DIR => { // Create some dependencies diff --git a/cli/src/lib/npm/npmLibDefs.js b/cli/src/lib/npm/npmLibDefs.js index c1f1e36054..2e86b90255 100644 --- a/cli/src/lib/npm/npmLibDefs.js +++ b/cli/src/lib/npm/npmLibDefs.js @@ -255,7 +255,7 @@ function validateVersionNumPart(part: string, partName: string): number { } export function pkgVersionMatch( - pkgSemverRaw: string, + pkgSemver: string, libDefSemverRaw: string, ): boolean { // The package version should be treated as a semver implicitly prefixed by @@ -275,19 +275,21 @@ export function pkgVersionMatch( return libDefSemverRaw; })(); - const pkgSemver = (() => { - // If pkg version is prefixed with `>=` we should be treated as `^` - // Normally `>=` would mean anything greater than a particular version so - // ">=2.1.0" would match 2.1.0 up to anything such as 3.4.5 - // But in the case of flow types, an import of a lib should probably match - // the lowest version that matches the range to assume backwards compatibility usage - const gtEq = '>='; - if (pkgSemverRaw.startsWith(gtEq)) { - return pkgSemverRaw.replace(gtEq, '^'); - } - - return pkgSemverRaw; - })(); + // If pkg version is prefixed with `>=` we should be treated as `^` + // Normally `>=` would mean anything greater than a particular version so + // ">=2.1.0" would match 2.1.0 up to anything such as 3.4.5 + // But in the case of flow types, an import of a lib should probably match + // the lowest version that matches the range to assume backwards compatibility usage + const gtEq = '>='; + if (pkgSemver.startsWith(gtEq)) { + pkgSemver = pkgSemver.replace(gtEq, '^'); + } + // Libraries that are released with an alpha versioning (eg: v6.0.0-alpha.0) + // Need to have the alpha version details removed to have a semver match against + // a libdef version. + if (pkgSemver.includes('-')) { + pkgSemver = pkgSemver.substring(0, pkgSemver.indexOf('-')); + } if (semver.valid(pkgSemver)) { // Test the single package version against the LibDef range From b64c8d8772af871fa5b9021bcd6e27c88c4c571a Mon Sep 17 00:00:00 2001 From: Brian Chen Date: Tue, 1 Feb 2022 05:22:03 +1100 Subject: [PATCH 2/2] simplify code with coerce func --- cli/src/lib/npm/__tests__/npmLibDefs-test.js | 13 +++++-- cli/src/lib/npm/npmLibDefs.js | 36 ++------------------ 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/cli/src/lib/npm/__tests__/npmLibDefs-test.js b/cli/src/lib/npm/__tests__/npmLibDefs-test.js index 1f838b21ee..2c8991af9a 100644 --- a/cli/src/lib/npm/__tests__/npmLibDefs-test.js +++ b/cli/src/lib/npm/__tests__/npmLibDefs-test.js @@ -340,13 +340,22 @@ describe('npmLibDefs', () => { expect(pkgVersionMatch('>=8.5.1', '9.x.x')).toBe(false); }); - it('matches explicit libdef with major range libdef', () => { + it('matches explicit version with major range libdef', () => { expect(pkgVersionMatch('8.5.1', '8.x.x')).toBe(true); }); - it('matches explicit libdef with minor range libdef', () => { + it('matches explicit version with minor range libdef', () => { expect(pkgVersionMatch('8.5.1', '8.5.x')).toBe(true); }); + + it('matches alpha version with libdef', () => { + expect(pkgVersionMatch('8.5.1-alpha.0', '8.5.x')).toBe(true); + expect(pkgVersionMatch('8.5.1-alpha.0', '8.x.x')).toBe(true); + }); + + it('matches non-semantic version alpha version with libdef', () => { + expect(pkgVersionMatch('42.6.7.9.3-alpha', '42.6.x')).toBe(true); + }); }); describe('getInstalledNpmLibDefs', () => { diff --git a/cli/src/lib/npm/npmLibDefs.js b/cli/src/lib/npm/npmLibDefs.js index 2e86b90255..ef98c74057 100644 --- a/cli/src/lib/npm/npmLibDefs.js +++ b/cli/src/lib/npm/npmLibDefs.js @@ -255,7 +255,7 @@ function validateVersionNumPart(part: string, partName: string): number { } export function pkgVersionMatch( - pkgSemver: string, + pkgSemverRaw: string, libDefSemverRaw: string, ): boolean { // The package version should be treated as a semver implicitly prefixed by @@ -275,21 +275,7 @@ export function pkgVersionMatch( return libDefSemverRaw; })(); - // If pkg version is prefixed with `>=` we should be treated as `^` - // Normally `>=` would mean anything greater than a particular version so - // ">=2.1.0" would match 2.1.0 up to anything such as 3.4.5 - // But in the case of flow types, an import of a lib should probably match - // the lowest version that matches the range to assume backwards compatibility usage - const gtEq = '>='; - if (pkgSemver.startsWith(gtEq)) { - pkgSemver = pkgSemver.replace(gtEq, '^'); - } - // Libraries that are released with an alpha versioning (eg: v6.0.0-alpha.0) - // Need to have the alpha version details removed to have a semver match against - // a libdef version. - if (pkgSemver.includes('-')) { - pkgSemver = pkgSemver.substring(0, pkgSemver.indexOf('-')); - } + const pkgSemver = semver.coerce(pkgSemverRaw)?.version ?? pkgSemverRaw; if (semver.valid(pkgSemver)) { // Test the single package version against the LibDef range @@ -318,23 +304,7 @@ export function pkgVersionMatch( const libDefUpper = getRangeUpperBound(libDefRange); const pkgBelowLower = semver.gtr(libDefLower, pkgSemver); - // semver.coerce explanation: - // We compare a libdef version against a package version - // to check if it matches the range, if pkgAboveUpper would be true - // that means it doesn't match. - // - // Mismatches occur when for example libdef is defined as is 8.5.x - // which makes it's upper <8.6.0 - // pkgSemver is ^8.5.1 who's range will reach a max of <9.0.0 - // therefore libDefUpper is less than maximum pkgSemver range. - // - // coerce will transform any semver passed in to an explicit - // version, in this case, ^8.5.1 becomes 8.5.1 which allows - // 8.6.0 (libdef) to be above 8.5.1 (pkg). - const pkgAboveUpper = semver.ltr( - libDefUpper, - semver.coerce(pkgSemver)?.version ?? pkgSemver, - ); + const pkgAboveUpper = semver.ltr(libDefUpper, pkgSemver); if (pkgBelowLower || pkgAboveUpper) { return false; }