-
Notifications
You must be signed in to change notification settings - Fork 543
Open
Description
Right now, we have the minVersion
function:
minVersion('14.0.0 || 16.1.0 || 18.0.0') // => '14.0.0'
and the minSatisfying
function:
minSatisfying([parse('16.1.0')],'14.0.0 || 16.1.0 || 18.0.0')
// SemVer {
// options: {},
// loose: false,
// includePrerelease: false,
// raw: '16.1.0',
// major: 16,
// minor: 1,
// patch: 0,
// prerelease: [],
// build: [],
// version: '16.1.0'
// }
minSatisfying([parse('16.0.0')],'14.0.0 || 16.1.0 || 18.0.0')
// null
I suggest the addition of one or two functions:
to_be_named(version, range, options)
to_be_named('13.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '14.0.0'
to_be_named('14.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '14.0.0'
to_be_named('14.0.1', '14.0.0 || 16.1.0 || 18.0.0') // => '14.0.1'
to_be_named('15.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '16.1.0'
to_be_named('16.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '16.1.0'
to_be_named('16.1.0', '14.0.0 || 16.1.0 || 18.0.0') // => '16.1.0'
to_be_named('16.1.1', '14.0.0 || 16.1.0 || 18.0.0') // => '16.1.1'
to_be_named('18.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '18.0.0'
to_be_named('18.0.1', '14.0.0 || 16.1.0 || 18.0.0') // => '18.0.1'
to_be_named('19.0.0', '14.0.0 || 16.1.0 || 18.0.0') // => '19.0.0'
or:
to_be_named2(range, options)
to_be_named2('a || b || c') // => [ minVersion(a), minVersion(b), minVersion(c) ]
to_be_named2('8.0.0', '10.0.1', '>12.0.0 || <14.0.0 || ~18.0.0' || ^20.0.0)
// => ['8.0.0', '10.0.1', '12.0.1', '0.0.0', '18.0.0', '20.0.0' ]
My use case is the following script:
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, minVersion, 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;
}
// TODO does not handle the following case:
// range: 14.0.0 || 16.1.0 || 18.0.0
// current: 16.0.0
const version = minVersion(range).raw;
const newCurrent = compare(version, current) === -1 ? current : version;
// 16.0.0 instead of 16.1.0
engines[engine] = 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);
}
It will crawl the given node_modules
folder and return an object one can use for the engines
in your project.
Example output
{"node":"18.12.0","npm":"1.0.0","iojs":"1.0.0"}
See the TODO for the case the script cannot handle right now without one of the suggested function additions.
Metadata
Metadata
Assignees
Labels
No labels