|
1 | 1 | import type * as d from '../../declarations';
|
2 | 2 | import { buildError } from '@utils';
|
3 | 3 | import { NodeResolveModule } from './node-resolve-module';
|
4 |
| -import semiver from 'semiver'; |
5 | 4 | import fs from 'graceful-fs';
|
6 | 5 | import path from 'path';
|
| 6 | +import satisfies from 'semver/functions/satisfies'; |
| 7 | +import major from 'semver/functions/major'; |
7 | 8 |
|
| 9 | +/** |
| 10 | + * The version range that we support for a given package |
| 11 | + * [0] is the lower end, while [1] is the higher end. |
| 12 | + * |
| 13 | + * These strings should be standard semver strings. |
| 14 | + */ |
| 15 | +type NodeVersionRange = [string, string]; |
| 16 | + |
| 17 | +/** |
| 18 | + * A manifest for lazily-loaded dependencies, mapping dependency names |
| 19 | + * to version ranges. |
| 20 | + */ |
| 21 | +type LazyDependencies = Record<string, NodeVersionRange>; |
| 22 | + |
| 23 | +/** |
| 24 | + * Lazy requirer for Node, with functionality for specifying version ranges |
| 25 | + * and returning diagnostic errors if requirements aren't met. |
| 26 | + */ |
8 | 27 | export class NodeLazyRequire implements d.LazyRequire {
|
9 | 28 | private ensured = new Set<string>();
|
10 | 29 |
|
11 |
| - constructor( |
12 |
| - private nodeResolveModule: NodeResolveModule, |
13 |
| - private lazyDependencies: { [dep: string]: [string, string] } |
14 |
| - ) {} |
| 30 | + constructor(private nodeResolveModule: NodeResolveModule, private lazyDependencies: LazyDependencies) {} |
15 | 31 |
|
16 | 32 | async ensure(fromDir: string, ensureModuleIds: string[]) {
|
17 | 33 | const diagnostics: d.Diagnostic[] = [];
|
18 |
| - const missingDeps: string[] = []; |
| 34 | + const problemDeps: string[] = []; |
19 | 35 |
|
20 | 36 | ensureModuleIds.forEach((ensureModuleId) => {
|
21 | 37 | if (!this.ensured.has(ensureModuleId)) {
|
22 |
| - const [minVersion, recommendedVersion] = this.lazyDependencies[ensureModuleId]; |
| 38 | + const [minVersion, maxVersion] = this.lazyDependencies[ensureModuleId]; |
| 39 | + |
23 | 40 | try {
|
24 | 41 | const pkgJsonPath = this.nodeResolveModule.resolveModule(fromDir, ensureModuleId);
|
25 |
| - |
26 | 42 | const installedPkgJson: d.PackageJsonData = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
27 | 43 |
|
28 |
| - if (semiver(installedPkgJson.version, minVersion) >= 0) { |
| 44 | + if (satisfies(installedPkgJson.version, `${minVersion} - ${major(maxVersion)}.x`)) { |
29 | 45 | this.ensured.add(ensureModuleId);
|
30 | 46 | return;
|
31 | 47 | }
|
32 | 48 | } catch (e) {}
|
33 |
| - missingDeps.push(`${ensureModuleId}@${recommendedVersion}`); |
| 49 | + // if we get here we didn't get to the `return` above, so either 1) there was some error |
| 50 | + // reading the package.json or 2) the version wasn't in our specified version range. |
| 51 | + problemDeps.push(`${ensureModuleId}@${maxVersion}`); |
34 | 52 | }
|
35 | 53 | });
|
36 | 54 |
|
37 |
| - if (missingDeps.length > 0) { |
| 55 | + if (problemDeps.length > 0) { |
38 | 56 | const err = buildError(diagnostics);
|
39 |
| - err.header = `Please install missing dev dependencies with either npm or yarn.`; |
40 |
| - err.messageText = `npm install --save-dev ${missingDeps.join(' ')}`; |
| 57 | + err.header = `Please install supported versions of dev dependencies with either npm or yarn.`; |
| 58 | + err.messageText = `npm install --save-dev ${problemDeps.join(' ')}`; |
41 | 59 | }
|
42 | 60 |
|
43 | 61 | return diagnostics;
|
|
0 commit comments