-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ENHANCEMENT] minimum versions or minimum version in relation to #649
Comments
I have updated my script to handle the case but I still think there is value in adding either method to semver. minimum-engines.mjs #!/usr/bin/env node
/*
Copyright (c) 2023, Sebastian Davids
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Prerequisite:
// npm i --save-dev semver
// Usage:
// node minimum-engines.mjs node_modules
import { compare, ltr, minVersion, parse, satisfies, validRange } from 'semver';
import { readFile, readdir } from 'node:fs/promises';
import { resolve } from 'node:path';
if (process.argv.length < 3) {
console.error('You need to supply the path to the node_modules folder');
process.exit(1);
}
const nodeModulesPath = process.argv[2];
const getPackageJsonFiles = async function* (path) {
const dirEntries = await readdir(path, { withFileTypes: true });
for (const entry of dirEntries) {
const file = resolve(path, entry.name);
if (entry.isDirectory()) {
yield* getPackageJsonFiles(file);
} else if (entry.name === 'package.json') {
yield file;
}
}
};
const getEngines = async (path) => {
const json = await readFile(path, 'utf8');
try {
const { engines = {} } = JSON.parse(json);
return engines;
} catch {
return {};
}
};
const mergeEngine = (engines, engine, value) => {
const range = value.trim();
if (range === '' || validRange(range) === null) {
return;
}
const current = engines[engine] ?? '0.0.0';
if (satisfies(current, range)) {
return;
}
const currentVersion = parse(current);
const newCurrent = minVersion(
range
.split('||')
.map((r) => minVersion(r).raw)
.filter((r) => ltr(currentVersion, r))
.map((r) => (ltr(currentVersion, r) ? r : current))
.join(' || '),
).raw;
engines[engine] = compare(newCurrent, current) === -1 ? current : newCurrent;
};
const result = {};
try {
for await (const file of getPackageJsonFiles(nodeModulesPath)) {
const engines = await getEngines(file);
for (const engine of Object.keys(engines)) {
mergeEngine(result, engine, engines[engine]);
}
}
console.log(JSON.stringify(result));
} catch (e) {
console.error(e);
} |
I'm really confused what this is asking for. if you have a range that doesn't include v13, then v13 has no relationship to it, it's just incompatible. |
The question for Give me the version included in the range equal or higher to the given version; if the given version is higher than any included version than return it. Examples: Range: >14.0.0 || >16.0.0 || > 18.0.0 Range: >14.0.0 || >16.1.0 || > 18.0.0 Range: >14.0.0 || >16.1.0 || > 18.0.0 more examples above. The question for Give me the minimum version for each part of a composite range. |
What's the use case tho? |
See the script above for one —- it determines the minimum engines for a given project. |
That's already what |
range 1 minVersion('>14.0.0 || >16.1.0 || >18.0.0') // 14.0.0 range 2 minVersion('>16.0.0 || >18.0.0 || >20.0.0') // 16.0.0
A third possible function would be to_be_named3(ranges, options)
to_be_named3(
[
'>14.0.0 || >16.0.0 || >18.0.0'
'>16.0.0 || >18.0.0 || >20.0.0',
'>14.0.0 || >16.1.0 || >18.0.0',
]) // => 16.1.0 |
ok so you want the minimum version that satisfies both ranges? I agree there's not a simple way to do that. I have |
The results of my script above and My script: I ran it on: https://github.com/terser/html-minifier-terser It has a So I am not sure about "engines": {
"node": ">= 14.13"
} Running it just on the non-dev dependencies I get: My script: {"node":"14.0.0"} I guess ls-engines also includes the range of the project's package.json ( |
la-engines only considers prod deps by default; run it with --dev if you want those included. ofc, on a published package engines should only consider prod deps anyways. |
$ npx ls-engines --mode=actual --dev gives: With explicit engines field: $ npx ls-engines --mode=actual
┌───────────────────────────────────┬───────────────────────────┐
│ package engines: │ dependency graph engines: │
├───────────────────────────────────┼───────────────────────────┤
│ "engines": { │ "engines": { │
│ "node": "^14.13.1 || >= 16.0.0" │ "node": ">= 14.13" │
│ } │ } │
└───────────────────────────────────┴───────────────────────────┘
Your “engines” field allows fewer node versions than your dependency graph does.
If you want to widen your support, you can run `ls-engines --save`, or manually add the following to your `package.json`:
"engines": {
"node": ">= 14.13"
} Without explicit engines field: $ npx ls-engines --mode=actual
┌──────────────────┬───────────────────────────┐
│ package engines: │ dependency graph engines: │
├──────────────────┼───────────────────────────┤
│ "engines": { │ "engines": { │
│ "node": "*" │ "node": ">= 14" │
│ } │ } │
└──────────────────┴───────────────────────────┘
Your “engines” field is missing! Prefer explicitly setting a supported engine range.
You can fix this by running `ls-engines --save`, or by manually adding the following to your `package.json`:
"engines": {
"node": ">= 14"
} Should dependency graph engines not be |
Feel free to file a bug on the repo if its output is confusing. |
Right now, we have the
minVersion
function:and the
minSatisfying
function:I suggest the addition of one or two functions:
or:
My use case is the following script:
minimum-engines.mjs
It will crawl the given
node_modules
folder and return an object one can use for theengines
in your project.Example output
See the TODO for the case the script cannot handle right now without one of the suggested function additions.
The text was updated successfully, but these errors were encountered: