mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
145 lines
3.8 KiB
TypeScript
145 lines
3.8 KiB
TypeScript
import path from 'path';
|
|
|
|
import { satisfies } from 'semver';
|
|
import { getPackageJson, getProjectRootPath } from './project';
|
|
|
|
// todo: memoize
|
|
/**
|
|
* Utility to get all dependencies from the project package.json.
|
|
* The result combines dependencies and devDependencies
|
|
*
|
|
* @returns string[] dependencies
|
|
*/
|
|
export function getAllDependencies(): string[] {
|
|
const packageJSON = getPackageJson();
|
|
|
|
return [
|
|
...Object.keys(packageJSON.dependencies ?? {}),
|
|
...Object.keys(packageJSON.devDependencies ?? {}),
|
|
];
|
|
}
|
|
|
|
// todo: memoize
|
|
/**
|
|
* Utility to check if the project has a specific dependency
|
|
* in either dependencies or devDependencies.
|
|
*
|
|
* @param {string} dependencyName
|
|
* @returns boolean
|
|
*/
|
|
export function hasDependency(dependencyName: string) {
|
|
return getAllDependencies().includes(dependencyName);
|
|
}
|
|
|
|
// todo: memoize
|
|
/**
|
|
* Utility to get the path (usually nested in node_modules) of a dependency.
|
|
*
|
|
* @param dependencyName
|
|
*/
|
|
export function getDependencyPath(dependencyName: string): string | null {
|
|
try {
|
|
const resolvedPath = require.resolve(`${dependencyName}/package.json`, {
|
|
paths: [getProjectRootPath()],
|
|
});
|
|
|
|
return path.dirname(resolvedPath);
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility to get the version of a dependency.
|
|
*
|
|
* @param dependencyName
|
|
* @returns string | null - version of the dependency or null if not found
|
|
*/
|
|
export function getDependencyVersion(dependencyName: string): string | null {
|
|
const dependencyPath = getDependencyPath(dependencyName);
|
|
if (!dependencyPath) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return require(`${dependencyPath}/package.json`).version;
|
|
} catch (err) {
|
|
// ignore
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Resolve a usable version string for checks (eg. semver.satisfies).
|
|
* Strategy:
|
|
* - prefer installed package.json version (getDependencyVersion)
|
|
* - fall back to declared version in project package.json (dependencies/devDependencies)
|
|
* - if declared is a common dist-tag (alpha|beta|rc|next) return a 9.x prerelease
|
|
*/
|
|
export function getResolvedDependencyVersionForCheck(
|
|
dependencyName: string,
|
|
target: string,
|
|
): string | null {
|
|
// try installed
|
|
const installed = getDependencyVersion(dependencyName);
|
|
if (installed) {
|
|
return installed;
|
|
}
|
|
|
|
// try declared in project package.json
|
|
const pkg = getPackageJson();
|
|
const declared =
|
|
(pkg.dependencies && pkg.dependencies[dependencyName]) ||
|
|
(pkg.devDependencies && pkg.devDependencies[dependencyName]);
|
|
if (!declared) {
|
|
return null;
|
|
}
|
|
|
|
// if declared already satisfies semver check, use it
|
|
// Note: declared may be a dist-tag like 'alpha' or a range. We only treat
|
|
// common tags as prereleases of target. Avoid trying to interpret arbitrary
|
|
// ranges here.
|
|
|
|
// common dist-tags -> treat as prerelease of 9.x for the purpose of >=9 checks
|
|
if (/^(alpha|beta|rc|next)$/.test(String(declared))) {
|
|
return `${target}-0`;
|
|
}
|
|
|
|
return declared ?? null;
|
|
}
|
|
|
|
/**
|
|
* Numeric comparison that treats prerelease versions as being at the same
|
|
* numeric level as their base version. e.g. 9.0.0-alpha.2 >= 9.0.0
|
|
*/
|
|
export function isVersionGteConsideringPrerelease(
|
|
version: string | null | undefined,
|
|
target: string,
|
|
): boolean {
|
|
if (!version) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const v = require('semver').parse(String(version));
|
|
const t = require('semver').parse(String(target));
|
|
if (!v || !t) {
|
|
// fallback to semver.satisfies with a prerelease-aware lower bound
|
|
return require('semver').satisfies(String(version), `>=${target}-0`);
|
|
}
|
|
|
|
if (v.major > t.major) return true;
|
|
if (v.major < t.major) return false;
|
|
if (v.minor > t.minor) return true;
|
|
if (v.minor < t.minor) return false;
|
|
if (v.patch >= t.patch) return true;
|
|
return false;
|
|
} catch (e) {
|
|
try {
|
|
return require('semver').satisfies(String(version), `>=${target}-0`);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|