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/__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 c1f1e36054..ef98c74057 100644 --- a/cli/src/lib/npm/npmLibDefs.js +++ b/cli/src/lib/npm/npmLibDefs.js @@ -275,19 +275,7 @@ 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; - })(); + const pkgSemver = semver.coerce(pkgSemverRaw)?.version ?? pkgSemverRaw; if (semver.valid(pkgSemver)) { // Test the single package version against the LibDef range @@ -316,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; }