diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml
index dc332d67..64af26e3 100644
--- a/.github/workflows/commitlint.yml
+++ b/.github/workflows/commitlint.yml
@@ -10,7 +10,7 @@ jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v5
+ - uses: actions/checkout@v6
with:
fetch-depth: 100
- uses: wagoid/commitlint-github-action@v6
diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml
index 750760c6..cf85f643 100644
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -11,9 +11,9 @@ jobs:
name: Lint using ESLint
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v5
+ - uses: actions/checkout@v6
- name: Use latest Node.js LTS
- uses: actions/setup-node@v5
+ uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Install dependencies
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
index ec4fdf48..3d3ce2e4 100644
--- a/.github/workflows/release-please.yml
+++ b/.github/workflows/release-please.yml
@@ -25,8 +25,8 @@ jobs:
if: ${{ needs.release-please.outputs.release_created }}
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
with:
node-version: 24.x
registry-url: 'https://registry.npmjs.org'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e36be5b5..5c519ccb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,34 @@
# Changelog
+## [6.0.0](https://github.com/nodejs/node-core-utils/compare/v5.16.2...v6.0.0) (2025-12-21)
+
+
+### ⚠ BREAKING CHANGES
+
+* drop Node.js 18.x from supported engines ([#988](https://github.com/nodejs/node-core-utils/issues/988))
+
+### Features
+
+* **git-node:** enhance remote configuration error message ([#965](https://github.com/nodejs/node-core-utils/issues/965)) ([ea17768](https://github.com/nodejs/node-core-utils/commit/ea17768bc3d3aec853e698beaecc8d97da298d65))
+* **git-node:** verify tag with official keyring ([#989](https://github.com/nodejs/node-core-utils/issues/989)) ([48a418b](https://github.com/nodejs/node-core-utils/commit/48a418b1eee227096be438c38759c96b843b8bb8))
+* **ncu-config:** add support for partially encrypted config files ([#1004](https://github.com/nodejs/node-core-utils/issues/1004)) ([7342aff](https://github.com/nodejs/node-core-utils/commit/7342affa6402a5f10130c0f486b5e1b08a4b3919))
+* **v8:** add command to sync V8 deps ([#1016](https://github.com/nodejs/node-core-utils/issues/1016)) ([aadc4fc](https://github.com/nodejs/node-core-utils/commit/aadc4fcb9c8d889424ddf51bd38a0dca1a8ec375))
+
+
+### Bug Fixes
+
+* **git-node:** clarify remote configuration error message ([#1001](https://github.com/nodejs/node-core-utils/issues/1001)) ([8746db3](https://github.com/nodejs/node-core-utils/commit/8746db3aca61587a41de221f6bd6ae554c71f1fe))
+* **git-node:** harmonize time left error messages ([#1007](https://github.com/nodejs/node-core-utils/issues/1007)) ([d5a488f](https://github.com/nodejs/node-core-utils/commit/d5a488f78bc5e143813251ae132e2c71aa79384f))
+* **git-node:** include full URL in suggested `gh` command ([#1002](https://github.com/nodejs/node-core-utils/issues/1002)) ([caee3c5](https://github.com/nodejs/node-core-utils/commit/caee3c5f9dda188d62f24d0533882ce52c60dd16))
+* **ncu-config:** do not override encrypted values silently ([#1006](https://github.com/nodejs/node-core-utils/issues/1006)) ([5d72b3e](https://github.com/nodejs/node-core-utils/commit/5d72b3e51b281e0300039e0824efe8251efce6f6))
+* remove stack traces from non-debug output ([#990](https://github.com/nodejs/node-core-utils/issues/990)) ([687217f](https://github.com/nodejs/node-core-utils/commit/687217f7867add49f8be8461cf0a85fc9364dda0))
+* spawning of `gpg` to read config ([#991](https://github.com/nodejs/node-core-utils/issues/991)) ([100c694](https://github.com/nodejs/node-core-utils/commit/100c6946b167ab7b035db929f779274b79e07694))
+
+
+### Miscellaneous Chores
+
+* drop Node.js 18.x from supported engines ([#988](https://github.com/nodejs/node-core-utils/issues/988)) ([f8371dd](https://github.com/nodejs/node-core-utils/commit/f8371dde2d8c78b50c272c8f41dedbca7b54f57c))
+
## [5.16.2](https://github.com/nodejs/node-core-utils/compare/v5.16.1...v5.16.2) (2025-10-12)
diff --git a/README.md b/README.md
index 9bcf06de..007f400e 100644
--- a/README.md
+++ b/README.md
@@ -76,18 +76,29 @@ Optionally, if you want to grant write access so `git-node` can write comments:
You can also edit the permission of existing tokens later.
-After the token is generated, create an rc file with the following content:
-(`~/.ncurc` or `$XDG_CONFIG_HOME/ncurc`):
-
-```json
-{
- "username": "your_github_username",
- "token": "token_that_you_created"
-}
+After the token is generated, you can give it to NCU using:
+
+With encryption (Recommended)
+
+```sh
+ncu-config set username your_github_username
+# Do not provide the token in the CLI, `ncu-config` will prompt you for it.
+ncu-config set -x token
+```
+
+Note: Encryption is available only if you have `gpg` setup on your machine.
+
+
+
+Without encryption
+
+```sh
+ncu-config set username your_github_username
+# Do not provide the token in the CLI, `ncu-config` will prompt you for it.
+ncu-config set token
```
-Note: you could use `ncu-config` to configure these variables, but it's not
-recommended to leave your tokens in your command line history.
+
### Setting up Jenkins credentials
@@ -108,27 +119,24 @@ To obtain the Jenkins API token
`~/.ncurc.gpg` or `$XDG_CONFIG_HOME/ncurc.gpg`) with `jenkins_token` as key,
like this:
- ```json
- {
- "username": "your_github_username",
- "token": "your_github_token",
- "jenkins_token": "your_jenkins_token"
- }
+ With encryption (recommended)
+
+ ```sh
+ ncu-config set -x jenkins_token
```
-### Protecting your credentials
+ Note: Encryption is available only if you have `gpg` setup on your machine.
-If you have `gpg` installed and setup on your local machine, it is strongly recommended
-to store an encrypted version of this file:
+
+ Without encryption
+
+ ```sh
+ ncu-config set jenkins_token
+ ```
-```console
-$ gpg --default-recipient-self --encrypt ~/.ncurc
-$ rm ~/.ncurc
-```
+
-The credentials are now encrypted in `~/.ncurc.gpg` and everytime it's needed,
-node-core-utils will invoke `gpg` that may ask you to decrypt it using
-your default key via pinentry.
+### Protecting your credentials
Put the following entries into your
[global `gitignore` file](https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreexcludesFile)
diff --git a/bin/ncu-config.js b/bin/ncu-config.js
index ffe50209..67e5545b 100755
--- a/bin/ncu-config.js
+++ b/bin/ncu-config.js
@@ -1,10 +1,14 @@
#!/usr/bin/env node
+import * as readline from 'node:readline/promises';
+import { stdin as input, stdout as output } from 'node:process';
+
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import {
- getConfig, updateConfig, GLOBAL_CONFIG, PROJECT_CONFIG, LOCAL_CONFIG
+ getConfig, updateConfig, GLOBAL_CONFIG, PROJECT_CONFIG, LOCAL_CONFIG,
+ encryptValue
} from '../lib/config.js';
import { setVerbosityFromEnv } from '../lib/verbosity.js';
@@ -13,10 +17,15 @@ setVerbosityFromEnv();
const args = yargs(hideBin(process.argv))
.completion('completion')
.command({
- command: 'set ',
+ command: 'set []',
desc: 'Set a config variable',
builder: (yargs) => {
yargs
+ .option('encrypt', {
+ describe: 'Store the value encrypted using gpg',
+ alias: 'x',
+ type: 'boolean'
+ })
.positional('key', {
describe: 'key of the configuration',
type: 'string'
@@ -61,8 +70,6 @@ const args = yargs(hideBin(process.argv))
.conflicts('global', 'project')
.help();
-const argv = args.parse();
-
function getConfigType(argv) {
if (argv.global) {
return { configName: 'global', configType: GLOBAL_CONFIG };
@@ -73,9 +80,19 @@ function getConfigType(argv) {
return { configName: 'local', configType: LOCAL_CONFIG };
}
-function setHandler(argv) {
+async function setHandler(argv) {
const { configName, configType } = getConfigType(argv);
const config = getConfig(configType);
+ if (!argv.value) {
+ const rl = readline.createInterface({ input, output });
+ argv.value = await rl.question('What value do you want to set? ');
+ rl.close();
+ } else if (argv.encrypt) {
+ console.warn('Passing sensitive config value via the shell is discouraged');
+ }
+ if (argv.encrypt) {
+ argv.value = await encryptValue(argv.value);
+ }
console.log(
`Updating ${configName} configuration ` +
`[${argv.key}]: ${config[argv.key]} -> ${argv.value}`);
@@ -96,6 +113,8 @@ function listHandler(argv) {
}
}
+const argv = await args.parse();
+
if (!['get', 'set', 'list'].includes(argv._[0])) {
args.showHelp();
}
diff --git a/components/git/v8.js b/components/git/v8.js
index 716718ab..094fc08a 100644
--- a/components/git/v8.js
+++ b/components/git/v8.js
@@ -2,12 +2,12 @@ import path from 'node:path';
import logSymbols from 'log-symbols';
-import { minor, major, backport } from '../../lib/update-v8/index.js';
+import { minor, major, backport, deps } from '../../lib/update-v8/index.js';
import { defaultBaseDir } from '../../lib/update-v8/constants.js';
import { checkCwd } from '../../lib/update-v8/common.js';
import { forceRunAsync } from '../../lib/run.js';
-export const command = 'v8 [major|minor|backport]';
+export const command = 'v8 [major|minor|backport|deps]';
export const describe = 'Update or patch the V8 engine';
export function builder(yargs) {
@@ -26,6 +26,11 @@ export function builder(yargs) {
describe: 'Bump the NODE_MODULE_VERSION constant',
default: true
});
+ yargs.option('concurrent', {
+ type: 'boolean',
+ describe: 'Update dependencies concurrently',
+ default: true,
+ });
}
})
.command({
@@ -64,6 +69,19 @@ export function builder(yargs) {
});
}
})
+ .command({
+ command: 'deps',
+ desc: 'Update V8 dependencies from the DEPS file',
+ handler,
+ builder: (yargs) => {
+ yargs
+ .option('concurrent', {
+ type: 'boolean',
+ describe: 'Update dependencies concurrently',
+ default: true,
+ });
+ }
+ })
.demandCommand(1, 'Please provide a valid command')
.option('node-dir', {
describe: 'Directory of a Node.js clone',
@@ -126,6 +144,8 @@ export function handler(argv) {
return major(options);
case 'backport':
return backport(options);
+ case 'deps':
+ return deps(options);
}
})
.catch((err) => {
diff --git a/eslint.config.js b/eslint.config.js
index 10e67b91..890d83b4 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -18,11 +18,12 @@ export default [
'coverage/',
'node_modules/',
'lib/wpt/templates/',
+ 'test/fixtures/release/*.js', // Copied from the nodejs/node repo
],
},
{
languageOptions: {
- globals: globals.node,
+ globals: globals.nodeBuiltin,
sourceType: 'module',
ecmaVersion: 'latest',
},
@@ -42,5 +43,22 @@ export default [
'n/no-process-exit': 'off',
'n/no-unsupported-features/node-builtins': 'off',
},
+ settings: {
+ 'import/resolver': {
+ node: {
+ pathFilter(pkg, path, relativePath) {
+ const pkgExport = relativePath
+ ? pkg.exports?.[`./${relativePath}`]
+ : pkg.exports?.['.'];
+ return pkgExport?.import?.default ??
+ pkgExport?.import ??
+ pkgExport?.[0]?.import ??
+ pkgExport?.default ??
+ pkgExport ??
+ (relativePath || pkg.main);
+ },
+ },
+ },
+ },
},
];
diff --git a/lib/auth.js b/lib/auth.js
index a0cf5b4a..a55f667a 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -3,7 +3,7 @@ import { ClientRequest } from 'node:http';
import ghauth from 'ghauth';
-import { getMergedConfig, getNcurcPath } from './config.js';
+import { clearCachedConfig, encryptValue, getMergedConfig, getNcurcPath } from './config.js';
export default lazy(auth);
@@ -60,67 +60,90 @@ function encode(name, token) {
return Buffer.from(`${name}:${token}`).toString('base64');
}
+function setOwnProperty(target, key, value) {
+ return Object.defineProperty(target, key, {
+ __proto__: null,
+ configurable: true,
+ enumerable: true,
+ value
+ });
+}
+
// TODO: support jenkins only...or not necessary?
// TODO: make this a class with dependency (CLI) injectable for testing
async function auth(
options = { github: true },
githubAuth = ghauth) {
- const result = {};
+ const result = {
+ get github() {
+ let username;
+ let token;
+ try {
+ ({ username, token } = getMergedConfig());
+ } catch (e) {
+ // Ignore error and prompt
+ }
+
+ check(username, token);
+ const github = encode(username, token);
+ setOwnProperty(result, 'github', github);
+ return github;
+ },
+
+ get jenkins() {
+ const { username, jenkins_token } = getMergedConfig();
+ if (!username || !jenkins_token) {
+ errorExit(
+ 'Get your Jenkins API token in https://ci.nodejs.org/me/security ' +
+ 'and run the following command to add it to your ncu config: ' +
+ 'ncu-config --global set -x jenkins_token'
+ );
+ };
+ check(username, jenkins_token);
+ const jenkins = encode(username, jenkins_token);
+ setOwnProperty(result, 'jenkins', jenkins);
+ return jenkins;
+ },
+
+ get h1() {
+ const { h1_username, h1_token } = getMergedConfig();
+ check(h1_username, h1_token);
+ const h1 = encode(h1_username, h1_token);
+ setOwnProperty(result, 'h1', h1);
+ return h1;
+ }
+ };
if (options.github) {
- let username;
- let token;
+ let config;
try {
- ({ username, token } = getMergedConfig());
- } catch (e) {
- // Ignore error and prompt
+ config = getMergedConfig();
+ } catch {
+ config = {};
}
-
- if (!username || !token) {
+ if (!Object.hasOwn(config, 'token') || !Object.hasOwn(config, 'username')) {
process.stdout.write(
'If this is your first time running this command, ' +
'follow the instructions to create an access token' +
'. If you prefer to create it yourself on Github, ' +
'see https://github.com/nodejs/node-core-utils/blob/main/README.md.\n');
const credentials = await tryCreateGitHubToken(githubAuth);
- username = credentials.user;
- token = credentials.token;
+ const username = credentials.user;
+ let token;
+ try {
+ token = await encryptValue(credentials.token);
+ } catch (err) {
+ console.warn('Failed encrypt token, storing unencrypted instead');
+ token = credentials.token;
+ }
const json = JSON.stringify({ username, token }, null, 2);
fs.writeFileSync(getNcurcPath(), json, {
mode: 0o600 /* owner read/write */
});
// Try again reading the file
- ({ username, token } = getMergedConfig());
+ clearCachedConfig();
}
- check(username, token);
- result.github = encode(username, token);
}
- if (options.jenkins) {
- const { username, jenkins_token } = getMergedConfig();
- if (!username || !jenkins_token) {
- errorExit(
- 'Get your Jenkins API token in https://ci.nodejs.org/me/configure ' +
- 'and run the following command to add it to your ncu config: ' +
- 'ncu-config --global set jenkins_token TOKEN'
- );
- };
- check(username, jenkins_token);
- result.jenkins = encode(username, jenkins_token);
- }
-
- if (options.h1) {
- const { h1_username, h1_token } = getMergedConfig();
- if (!h1_username || !h1_token) {
- errorExit(
- 'Get your HackerOne API token in ' +
- 'https://docs.hackerone.com/organizations/api-tokens.html ' +
- 'and run the following command to add it to your ncu config: ' +
- 'ncu-config --global set h1_token TOKEN or ' +
- 'ncu-config --global set h1_username USERNAME'
- );
- };
- result.h1 = encode(h1_username, h1_token);
- }
return result;
}
diff --git a/lib/config.js b/lib/config.js
index 6703ec87..3c91217d 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -4,6 +4,7 @@ import os from 'node:os';
import { readJson, writeJson } from './file.js';
import { existsSync, mkdtempSync, rmSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
+import { forceRunAsync, runSync } from './run.js';
export const GLOBAL_CONFIG = Symbol('globalConfig');
export const PROJECT_CONFIG = Symbol('projectConfig');
@@ -18,32 +19,95 @@ export function getNcurcPath() {
}
}
-export function getMergedConfig(dir, home) {
- const globalConfig = getConfig(GLOBAL_CONFIG, home);
- const projectConfig = getConfig(PROJECT_CONFIG, dir);
- const localConfig = getConfig(LOCAL_CONFIG, dir);
- return Object.assign(globalConfig, projectConfig, localConfig);
+let mergedConfig;
+export function getMergedConfig(dir, home, additional) {
+ if (mergedConfig == null) {
+ const globalConfig = getConfig(GLOBAL_CONFIG, home);
+ const projectConfig = getConfig(PROJECT_CONFIG, dir);
+ const localConfig = getConfig(LOCAL_CONFIG, dir);
+ mergedConfig = Object.assign(globalConfig, projectConfig, localConfig, additional);
+ }
+ return mergedConfig;
};
+export function clearCachedConfig() {
+ mergedConfig = null;
+}
+
+export async function encryptValue(input) {
+ console.warn('Spawning gpg to encrypt the config value');
+ return forceRunAsync(
+ process.env.GPG_BIN || 'gpg',
+ ['--default-recipient-self', '--encrypt', '--armor'],
+ {
+ captureStdout: true,
+ ignoreFailure: false,
+ input
+ }
+ );
+}
+
+function setOwnProperty(target, key, value) {
+ return Object.defineProperty(target, key, {
+ __proto__: null,
+ configurable: true,
+ enumerable: true,
+ value
+ });
+}
+function addEncryptedPropertyGetter(target, key, input) {
+ if (input?.startsWith?.('-----BEGIN PGP MESSAGE-----\n')) {
+ return Object.defineProperty(target, key, {
+ __proto__: null,
+ configurable: true,
+ get() {
+ // Using an error object to get a stack trace in debug mode.
+ const warn = new Error(
+ `The config value for ${key} is encrypted, spawning gpg to decrypt it...`
+ );
+ console.warn(setOwnProperty(warn, 'name', 'Warning'));
+ const value = runSync(process.env.GPG_BIN || 'gpg', ['--decrypt'], { input });
+ setOwnProperty(target, key, value);
+ return value;
+ },
+ set(newValue) {
+ if (!addEncryptedPropertyGetter(target, key, newValue)) {
+ throw new Error(
+ 'Refusing to override an encrypted value with a non-encrypted one. ' +
+ 'Please use an encrypted one, or delete the config key first.'
+ );
+ }
+ }
+ });
+ }
+}
-export function getConfig(configType, dir) {
+export function getConfig(configType, dir, raw = false) {
const configPath = getConfigPath(configType, dir);
const encryptedConfigPath = configPath + '.gpg';
if (existsSync(encryptedConfigPath)) {
console.warn('Encrypted config detected, spawning gpg to decrypt it...');
const { status, stdout } =
- spawnSync('gpg', ['--decrypt', encryptedConfigPath]);
+ spawnSync(process.env.GPG_BIN || 'gpg', ['--decrypt', encryptedConfigPath]);
if (status === 0) {
return JSON.parse(stdout.toString('utf-8'));
}
}
try {
- return readJson(configPath);
+ const json = readJson(configPath);
+ if (!raw) {
+ // Raw config means encrypted values are returned as is.
+ // Otherwise we install getters to decrypt them when accessed.
+ for (const [key, val] of Object.entries(json)) {
+ addEncryptedPropertyGetter(json, key, val);
+ }
+ }
+ return json;
} catch (cause) {
throw new Error('Unable to parse config file ' + configPath, { cause });
}
};
-export function getConfigPath(configType, dir) {
+function getConfigPath(configType, dir) {
switch (configType) {
case GLOBAL_CONFIG:
return getNcurcPath();
@@ -61,7 +125,7 @@ export function getConfigPath(configType, dir) {
}
};
-export function writeConfig(configType, obj, dir) {
+function writeConfig(configType, obj, dir) {
const configPath = getConfigPath(configType, dir);
const encryptedConfigPath = configPath + '.gpg';
if (existsSync(encryptedConfigPath)) {
@@ -69,7 +133,7 @@ export function writeConfig(configType, obj, dir) {
const tmpFile = path.join(tmpDir, 'config.json');
try {
writeJson(tmpFile, obj);
- const { status } = spawnSync('gpg',
+ const { status } = spawnSync(process.env.GPG_BIN || 'gpg',
['--default-recipient-self', '--yes', '--encrypt', '--output', encryptedConfigPath, tmpFile]
);
if (status !== 0) {
@@ -85,7 +149,7 @@ export function writeConfig(configType, obj, dir) {
};
export function updateConfig(configType, obj, dir) {
- const config = getConfig(configType, dir);
+ const config = getConfig(configType, dir, true);
writeConfig(configType, Object.assign(config, obj), dir);
};
diff --git a/lib/landing_session.js b/lib/landing_session.js
index 139eabc3..19944ba4 100644
--- a/lib/landing_session.js
+++ b/lib/landing_session.js
@@ -464,8 +464,8 @@ export default class LandingSession extends Session {
const url = `https://github.com/${owner}/${repo}/pull/${prid}`;
cli.log(`2. Post "Landed in ${willBeLanded}" in ${url}`);
if (isGhAvailable()) {
- cli.log(` gh pr comment ${prid} --body "Landed in ${willBeLanded}"`);
- cli.log(` gh pr close ${prid}`);
+ cli.log(` gh pr comment ${url} --body "Landed in ${willBeLanded}"`);
+ cli.log(` gh pr close ${url}`);
}
}
diff --git a/lib/pr_checker.js b/lib/pr_checker.js
index 273d0fe7..a4dfeaac 100644
--- a/lib/pr_checker.js
+++ b/lib/pr_checker.js
@@ -19,7 +19,6 @@ const { FROM_COMMENT, FROM_REVIEW_COMMENT } = REVIEW_SOURCES;
const SECOND = 1000;
const MINUTE = SECOND * 60;
-const HOUR = MINUTE * 60;
const WAIT_TIME_MULTI_APPROVAL = 24 * 2;
const WAIT_TIME_SINGLE_APPROVAL = 24 * 7;
@@ -196,10 +195,18 @@ export default class PRChecker {
const createTime = new Date(this.pr.createdAt);
const msFromCreateTime = now.getTime() - createTime.getTime();
- const minutesFromCreateTime = Math.ceil(msFromCreateTime / MINUTE);
- const hoursFromCreateTime = Math.ceil(msFromCreateTime / HOUR);
- let timeLeftMulti = this.waitTimeMultiApproval - hoursFromCreateTime;
- const timeLeftSingle = this.waitTimeSingleApproval - hoursFromCreateTime;
+ const minutesFromCreateTime = msFromCreateTime / MINUTE;
+ const timeLeftMulti = this.waitTimeMultiApproval * 60 - minutesFromCreateTime;
+ const timeLeftSingle = this.waitTimeSingleApproval * 60 - minutesFromCreateTime;
+ const timeToText = (time, liaison_word = undefined) => {
+ let unity = 'minute';
+ if (time > 59) {
+ unity = 'hour';
+ time /= 60;
+ }
+ time = Math.ceil(time);
+ return `${time} ${liaison_word ? liaison_word + ' ' : ''}${unity}${time === 1 ? '' : 's'}`;
+ };
if (approved.length >= 2) {
if (isFastTracked || isCodeAndLearn) {
@@ -208,15 +215,9 @@ export default class PRChecker {
if (timeLeftMulti < 0) {
return true;
}
- if (timeLeftMulti === 0) {
- const timeLeftMins =
- this.waitTimeMultiApproval * 60 - minutesFromCreateTime;
- cli.error(`This PR needs to wait ${timeLeftMins} ` +
- `more minutes to land${fastTrackAppendix}`);
- return false;
- }
- cli.error(`This PR needs to wait ${timeLeftMulti} more ` +
- `hours to land${fastTrackAppendix}`);
+ cli.error(
+ `This PR needs to wait ${timeToText(timeLeftMulti, 'more')} to land${fastTrackAppendix}`
+ );
return false;
}
@@ -224,10 +225,9 @@ export default class PRChecker {
if (timeLeftSingle < 0) {
return true;
}
- timeLeftMulti = timeLeftMulti < 0 || isFastTracked ? 0 : timeLeftMulti;
- cli.error(`This PR needs to wait ${timeLeftSingle} more hours to land ` +
- `(or ${timeLeftMulti} hours if there is one more approval)` +
- fastTrackAppendix);
+ cli.error(`This PR needs to wait ${timeToText(timeLeftSingle, 'more')} to land (or ${
+ timeToText(timeLeftMulti < 0 || isFastTracked ? 0 : timeLeftMulti)
+ } if there is one more approval)${fastTrackAppendix}`);
return false;
}
}
diff --git a/lib/promote_release.js b/lib/promote_release.js
index 89abc497..bdddacbb 100644
--- a/lib/promote_release.js
+++ b/lib/promote_release.js
@@ -1,5 +1,7 @@
import path from 'node:path';
import fs from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { pipeline } from 'node:stream/promises';
import semver from 'semver';
import * as gst from 'git-secure-tag';
@@ -196,31 +198,44 @@ export default class ReleasePromotion extends Session {
async verifyTagSignature(version) {
const { cli } = this;
- const verifyTagPattern = /gpg:[^\n]+\ngpg:\s+using \w+ key ([^\n]+)\ngpg:\s+issuer "([^"]+)"\ngpg:\s+Good signature from (?:"[^"]+"(?: \[ultimate\])?\ngpg:\s+aka )*"([^<]+) <\2>"/;
- const [verifyTagOutput, haystack] = await Promise.all([forceRunAsync(
- 'git', ['--no-pager',
- 'verify-tag',
- `v${version}`
- ], { ignoreFailure: false, captureStderr: true }), fs.readFile('README.md')]);
- const match = verifyTagPattern.exec(verifyTagOutput);
- if (match == null) {
- cli.warn('git was not able to verify the tag:');
- cli.info(verifyTagOutput);
- } else {
- const [, keyID, email, name] = match;
- const needle = `* **${name}** <<${email}>>\n ${'`'}${keyID}${'`'}`;
- if (haystack.includes(needle)) {
- return;
+
+ cli.startSpinner('Downloading active releasers keyring from nodejs/release-keys...');
+ const [keyRingStream, [GNUPGHOME, keyRingFd]] = await Promise.all([
+ fetch('https://github.com/nodejs/release-keys/raw/HEAD/gpg-only-active-keys/pubring.kbx'),
+ fs.mkdtemp(path.join(tmpdir(), 'ncu-'))
+ .then(async d => [d, await fs.open(path.join(d, 'pubring.kbx'), 'w')]),
+ ]);
+ if (!keyRingStream.ok) throw new Error('Failed to download keyring', { cause: keyRingStream });
+ await pipeline(keyRingStream.body, keyRingFd.createWriteStream());
+ cli.stopSpinner('Active releasers keyring stored in temp directory');
+
+ try {
+ await forceRunAsync(
+ 'git', ['--no-pager',
+ 'verify-tag',
+ `v${version}`
+ ], {
+ ignoreFailure: false,
+ spawnArgs: { env: { ...process.env, GNUPGHOME } },
+ });
+ cli.ok('git tag signature verified');
+ } catch (cause) {
+ cli.error('git was not able to verify the tag');
+ cli.warn('This means that either the tag was signed with the wrong key,');
+ cli.warn('or that nodejs/release-keys contains outdated information.');
+ cli.warn('The release should not proceed.');
+ if (!await cli.prompt('Do you want to proceed anyway?', { defaultAnswer: false })) {
+ if (await cli.prompt('Do you want to delete the local tag?')) {
+ await forceRunAsync('git', ['tag', '-d', `v${version}`]);
+ } else {
+ cli.info(`Run 'git tag -d v${version}' to remove the local tag.`);
+ }
+ throw new Error('Aborted', { cause });
}
- cli.warn('Tag was signed with an undocumented identity/key pair!');
- cli.info('Expected to find the following entry in the README:');
- cli.info(needle);
- cli.info('If you are using a subkey, it might be OK.');
- }
- cli.info(`If that doesn't sound right, consider removing the tag (git tag -d v${version
- }), check your local config, and start the process over.`);
- if (!await cli.prompt('Do you want to proceed anyway?', { defaultAnswer: false })) {
- throw new Error('Aborted');
+ } finally {
+ cli.startSpinner('Cleaning up temp files');
+ await fs.rm(GNUPGHOME, { force: true, recursive: true });
+ cli.stopSpinner('Temp files removed');
}
}
diff --git a/lib/session.js b/lib/session.js
index 4ce08a93..4c2dacf3 100644
--- a/lib/session.js
+++ b/lib/session.js
@@ -19,7 +19,7 @@ export default class Session {
this.cli = cli;
this.dir = dir;
this.prid = prid;
- this.config = { ...getMergedConfig(this.dir), ...argv };
+ this.config = getMergedConfig(this.dir, undefined, argv);
this.gpgSign = argv?.['gpg-sign']
? (argv['gpg-sign'] === true ? ['-S'] : ['-S', argv['gpg-sign']])
: [];
@@ -126,7 +126,12 @@ export default class Session {
writeJson(this.sessionPath, {
state: STARTED,
prid: this.prid,
- config: this.config
+ // Filter out getters, those are likely encrypted data we don't need on the session.
+ config: Object.entries(Object.getOwnPropertyDescriptors(this.config))
+ .reduce((pv, [key, desc]) => {
+ if (Object.hasOwn(desc, 'value')) pv[key] = desc.value;
+ return pv;
+ }, { __proto__: null }),
});
}
@@ -382,12 +387,19 @@ export default class Session {
cli.setExitCode(1);
}
if (!upstream) {
- cli.warn('You have not told git-node the remote you want to sync with.');
+ cli.warn('You have not told git-node what remote name you are trying to land commits on.');
cli.separator();
- cli.info(
- 'For example, if your remote pointing to nodejs/node is' +
- ' `remote-upstream`, you can run:\n\n' +
- ' $ ncu-config set upstream remote-upstream');
+ const remoteName = runSync('git', ['remote', '-v'])
+ .match(/^(\S+)\s+(?:https:\/\/github\.com\/|git@github\.com:)nodejs\/node\.git \(\S+\)\r?$/m)?.[1];
+ cli.info(remoteName
+ ? `You likely want to run the following:\n\n $ ncu-config set upstream ${remoteName}`
+ : 'The expected repository does not seem to appear in your local config.\n' +
+ '1. First, add the Node.js core repository as a remote:\n' +
+ ' $ git remote add upstream https://github.com/nodejs/node.git\n\n' +
+ '2. Then, tell git-node to use this remote for syncing:\n' +
+ ' $ ncu-config set upstream upstream\n\n' +
+ 'Note: Using "upstream" is recommended, but you can use any remote name.\n' +
+ 'For security reasons, you need to add the remote manually.');
cli.separator();
cli.setExitCode(1);
}
diff --git a/lib/update-v8/deps.js b/lib/update-v8/deps.js
new file mode 100644
index 00000000..f4043384
--- /dev/null
+++ b/lib/update-v8/deps.js
@@ -0,0 +1,88 @@
+import path from 'node:path';
+import { promises as fs } from 'node:fs';
+
+import { chromiumGit, v8Deps } from './constants.js';
+import { forceRunAsync } from '../run.js';
+import {
+ addToGitignore,
+ filterForVersion,
+ getNodeV8Version,
+ removeDirectory,
+ replaceGitignore,
+} from './util.js';
+
+async function fetchFromGit(cwd, repo, commit) {
+ await removeDirectory(cwd);
+ await fs.mkdir(cwd, { recursive: true });
+ await exec('init');
+ await exec('remote', 'add', 'origin', repo);
+ await exec('fetch', 'origin', commit);
+ await exec('reset', '--hard', 'FETCH_HEAD');
+ await removeDirectory(path.join(cwd, '.git'));
+
+ function exec(...options) {
+ return forceRunAsync('git', options, {
+ ignoreFailure: false,
+ spawnArgs: { cwd, stdio: 'ignore' }
+ });
+ }
+}
+
+async function readDeps(nodeDir) {
+ const depsStr = await fs.readFile(path.join(nodeDir, 'deps/v8/DEPS'), 'utf8');
+ const start = depsStr.indexOf('deps = {');
+ const end = depsStr.indexOf('\n}', start) + 2;
+ const depsDeclaration = depsStr.substring(start, end).replace(/^ *#.*/gm, '');
+ const Var = () => chromiumGit; // eslint-disable-line no-unused-vars
+ let deps;
+ eval(depsDeclaration); // eslint-disable-line no-eval
+ return deps;
+}
+
+async function lookupDep(depsTable, depName) {
+ const dep = depsTable[depName];
+ if (!dep) {
+ throw new Error(`V8 dep "${depName}" not found in DEPS file`);
+ }
+ if (typeof dep === 'object') {
+ return dep.url.split('@');
+ }
+ return dep.split('@');
+}
+
+export default function updateV8Deps() {
+ return {
+ title: 'Update V8 DEPS',
+ task: async(ctx, task) => {
+ const newV8Version = await getNodeV8Version(ctx.nodeDir);
+ const repoPrefix = newV8Version.majorMinor >= 86 ? '' : 'v8/';
+ const deps = filterForVersion(v8Deps.map((v8Dep) => ({
+ ...v8Dep,
+ repo: `${repoPrefix}${v8Dep.repo}`,
+ path: v8Dep.repo
+ })), newV8Version);
+ if (deps.length === 0) return;
+ const depsTable = await readDeps(ctx.nodeDir);
+ const subtasks = [];
+ for (const dep of deps) {
+ // Update .gitignore sequentially to avoid races
+ if (dep.gitignore) {
+ if (typeof dep.gitignore === 'string') {
+ await addToGitignore(ctx.nodeDir, dep.gitignore);
+ } else {
+ await replaceGitignore(ctx.nodeDir, dep.gitignore);
+ }
+ }
+ subtasks.push({
+ title: `Update ${dep.path}`,
+ task: async(ctx) => {
+ const [repo, commit] = await lookupDep(depsTable, dep.repo);
+ const thePath = path.join(ctx.nodeDir, 'deps/v8', dep.path);
+ await fetchFromGit(thePath, repo, commit);
+ }
+ });
+ }
+ return task.newListr(subtasks, { concurrent: ctx.concurrent });
+ }
+ };
+};
diff --git a/lib/update-v8/index.js b/lib/update-v8/index.js
index 1c9afca1..896a2228 100644
--- a/lib/update-v8/index.js
+++ b/lib/update-v8/index.js
@@ -5,6 +5,7 @@ import updateVersionNumbers from './updateVersionNumbers.js';
import commitUpdate from './commitUpdate.js';
import majorUpdate from './majorUpdate.js';
import minorUpdate from './minorUpdate.js';
+import updateDeps from './deps.js';
import updateV8Clone from './updateV8Clone.js';
export function major(options) {
@@ -34,6 +35,14 @@ export async function backport(options) {
return tasks.run(options);
};
+export async function deps(options) {
+ const tasks = new Listr(
+ [updateDeps()],
+ getOptions(options)
+ );
+ return tasks.run(options);
+};
+
/**
* Get the listr2 options.
* @param {{ verbose?: boolean }} options The original options.
diff --git a/lib/update-v8/majorUpdate.js b/lib/update-v8/majorUpdate.js
index 15fd4cd5..4005794d 100644
--- a/lib/update-v8/majorUpdate.js
+++ b/lib/update-v8/majorUpdate.js
@@ -1,17 +1,12 @@
import path from 'node:path';
-import { promises as fs } from 'node:fs';
import { getCurrentV8Version } from './common.js';
+import updateV8Deps from './deps.js';
import {
- getNodeV8Version,
- filterForVersion,
- addToGitignore,
- replaceGitignore,
removeDirectory,
isVersionString
} from './util.js';
import applyNodeChanges from './applyNodeChanges.js';
-import { chromiumGit, v8Deps } from './constants.js';
import { forceRunAsync } from '../run.js';
export default function majorUpdate() {
@@ -106,65 +101,3 @@ function addDepsV8() {
})
};
}
-
-function updateV8Deps() {
- return {
- title: 'Update V8 DEPS',
- task: async(ctx) => {
- const newV8Version = await getNodeV8Version(ctx.nodeDir);
- const repoPrefix = newV8Version.majorMinor >= 86 ? '' : 'v8/';
- const deps = filterForVersion(v8Deps.map((v8Dep) => ({
- ...v8Dep,
- repo: `${repoPrefix}${v8Dep.repo}`,
- path: v8Dep.repo
- })), newV8Version);
- if (deps.length === 0) return;
- for (const dep of deps) {
- if (dep.gitignore) {
- if (typeof dep.gitignore === 'string') {
- await addToGitignore(ctx.nodeDir, dep.gitignore);
- } else {
- await replaceGitignore(ctx.nodeDir, dep.gitignore);
- }
- }
- const [repo, commit] = await readDeps(ctx.nodeDir, dep.repo);
- const thePath = path.join(ctx.nodeDir, 'deps/v8', dep.path);
- await fetchFromGit(thePath, repo, commit);
- }
- }
- };
-}
-
-async function readDeps(nodeDir, depName) {
- const depsStr = await fs.readFile(path.join(nodeDir, 'deps/v8/DEPS'), 'utf8');
- const start = depsStr.indexOf('deps = {');
- const end = depsStr.indexOf('\n}', start) + 2;
- const depsDeclaration = depsStr.substring(start, end).replace(/^ *#.*/gm, '');
- const Var = () => chromiumGit; // eslint-disable-line no-unused-vars
- let deps;
- eval(depsDeclaration); // eslint-disable-line no-eval
- const dep = deps[depName];
- if (!dep) {
- throw new Error(`V8 dep "${depName}" not found in DEPS file`);
- }
- if (typeof dep === 'object') {
- return dep.url.split('@');
- }
- return dep.split('@');
-}
-
-async function fetchFromGit(cwd, repo, commit) {
- await fs.mkdir(cwd, { recursive: true });
- await exec('init');
- await exec('remote', 'add', 'origin', repo);
- await exec('fetch', 'origin', commit);
- await exec('reset', '--hard', 'FETCH_HEAD');
- await removeDirectory(path.join(cwd, '.git'));
-
- function exec(...options) {
- return forceRunAsync('git', options, {
- ignoreFailure: false,
- spawnArgs: { cwd, stdio: 'ignore' }
- });
- }
-}
diff --git a/lib/update-v8/util.js b/lib/update-v8/util.js
index b94a4356..a372a9fc 100644
--- a/lib/update-v8/util.js
+++ b/lib/update-v8/util.js
@@ -37,13 +37,18 @@ export function filterForVersion(list, version) {
export async function addToGitignore(nodeDir, value) {
const gitignorePath = path.join(nodeDir, 'deps/v8/.gitignore');
- await fs.appendFile(gitignorePath, `${value}\n`);
+ const gitignore = await fs.readFile(gitignorePath, 'utf8');
+ if (!gitignore.includes(value)) {
+ await fs.appendFile(gitignorePath, `${value}\n`);
+ }
}
export async function replaceGitignore(nodeDir, options) {
const gitignorePath = path.join(nodeDir, 'deps/v8/.gitignore');
let gitignore = await fs.readFile(gitignorePath, 'utf8');
- gitignore = gitignore.replace(options.match, options.replace);
+ if (!gitignore.includes(options.replace)) {
+ gitignore = gitignore.replace(options.match, options.replace);
+ }
await fs.writeFile(gitignorePath, gitignore);
}
diff --git a/lib/verbosity.js b/lib/verbosity.js
index d52b77c8..d14a7f3a 100644
--- a/lib/verbosity.js
+++ b/lib/verbosity.js
@@ -18,6 +18,9 @@ export function setVerbosityFromEnv() {
if (Object.keys(VERBOSITY).includes(env)) {
verbosity = VERBOSITY[env];
}
+ if (!isDebugVerbosity()) {
+ Error.stackTraceLimit = 0;
+ }
};
export function debuglog(...args) {
diff --git a/lib/voting_session.js b/lib/voting_session.js
index 02b035a2..e3d349fe 100644
--- a/lib/voting_session.js
+++ b/lib/voting_session.js
@@ -10,7 +10,6 @@ import {
getEditor, isGhAvailable
} from './utils.js';
-// eslint-disable-next-line import/no-unresolved
import voteUsingGit from '@node-core/caritat/voteUsingGit';
import * as yaml from 'js-yaml';
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index e63edefa..f91d647a 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1,18 +1,18 @@
{
"name": "@node-core/utils",
- "version": "5.16.2",
+ "version": "6.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@node-core/utils",
- "version": "5.16.2",
+ "version": "6.0.0",
"license": "MIT",
"dependencies": {
"@inquirer/prompts": "^7.4.1",
"@listr2/prompt-adapter-enquirer": "^2.0.12",
"@node-core/caritat": "^1.6.0",
- "@pkgjs/nv": "^0.2.2",
+ "@pkgjs/nv": "^0.3.0",
"branch-diff": "^3.1.1",
"chalk": "^5.4.1",
"changelog-maker": "^4.4.1",
@@ -23,15 +23,15 @@
"ghauth": "^6.0.12",
"git-secure-tag": "^2.3.1",
"js-yaml": "^4.1.0",
- "listr2": "^8.2.5",
+ "listr2": "^9.0.5",
"lodash": "^4.17.21",
"log-symbols": "^7.0.0",
- "ora": "^8.2.0",
+ "ora": "^9.0.0",
"replace-in-file": "^8.3.0",
"semver": "^7.7.1",
"undici": "^7.7.0",
- "which": "^5.0.0",
- "yargs": "^17.7.2"
+ "which": "^6.0.0",
+ "yargs": "^18.0.0"
},
"bin": {
"get-metadata": "bin/get-metadata.js",
@@ -53,7 +53,7 @@
"sinon": "^21.0.0"
},
"engines": {
- "node": "^18.18.0 || >=20.0.0"
+ "node": "^20.19.0 || ^22.20.0 || >=24.10.0"
}
},
"node_modules/@actions/core": {
@@ -176,9 +176,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
- "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -218,13 +218,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.21.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
- "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.6",
+ "@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -233,19 +233,22 @@
}
},
"node_modules/@eslint/config-helpers": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
- "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
"license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/core": {
- "version": "0.15.1",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
- "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -293,9 +296,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.32.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz",
- "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
+ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -306,9 +309,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
- "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -316,13 +319,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
- "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.15.1",
+ "@eslint/core": "^0.17.0",
"levn": "^0.4.1"
},
"engines": {
@@ -1045,12 +1048,12 @@
}
},
"node_modules/@pkgjs/nv": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@pkgjs/nv/-/nv-0.2.2.tgz",
- "integrity": "sha512-LbQbUKwt2d4VsTM5MKG25WLiZtmXu89zeoqVdJz3POlnyICkZ/o63WLswLleIysYOGHY9rqeOF/SBwC4hbq90Q==",
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/nv/-/nv-0.3.0.tgz",
+ "integrity": "sha512-axZda7mqX9UIos07lh8hyl+sx+/oSNAY4esWiaCHWWavV3IPiqMyX1g6OufByCKwtAEsWhDvgdWgoiycMQHd7w==",
"license": "MIT",
"dependencies": {
- "got": "^11.8.3",
+ "got": "^11.8.6",
"semver": "^7.1.1",
"yargs": "^16.2.0"
},
@@ -1189,9 +1192,9 @@
}
},
"node_modules/@reporters/github": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/@reporters/github/-/github-1.7.2.tgz",
- "integrity": "sha512-8mvTyKUxxDXkNIWfzv3FsHVwjr8JCwVtwidQws2neV6YgrsJW6OwTOBBhd01RKrDMXPxgpMQuFEfN9hRuUZGuA==",
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/@reporters/github/-/github-1.11.0.tgz",
+ "integrity": "sha512-sP/fSOgIoMYXZFWVy2Hw6vWUG3akUBiykqnFjx2jWI/kdqj55VZNXAQ27MYuiNffWlITW6mMBcv8+i47O7C77w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1417,6 +1420,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz",
"integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~7.8.0"
}
@@ -1482,6 +1486,7 @@
"integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/types": "8.38.0",
@@ -1978,6 +1983,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2017,7 +2023,6 @@
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=6"
}
@@ -2422,6 +2427,129 @@
}
}
},
+ "node_modules/c8/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/c8/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/c8/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/c8/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/c8/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/c8/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/c8/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/c8/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/c8/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
@@ -2544,9 +2672,9 @@
}
},
"node_modules/chalk": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
- "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
@@ -2629,25 +2757,25 @@
"license": "MIT"
},
"node_modules/cheerio": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.0.tgz",
- "integrity": "sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
+ "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
"license": "MIT",
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
- "encoding-sniffer": "^0.2.0",
+ "encoding-sniffer": "^0.2.1",
"htmlparser2": "^10.0.0",
"parse5": "^7.3.0",
"parse5-htmlparser2-tree-adapter": "^7.1.0",
"parse5-parser-stream": "^7.1.2",
- "undici": "^7.10.0",
+ "undici": "^7.12.0",
"whatwg-mimetype": "^4.0.0"
},
"engines": {
- "node": ">=18.17"
+ "node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
@@ -2698,16 +2826,32 @@
}
},
"node_modules/cli-truncate": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
- "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz",
+ "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==",
"license": "MIT",
"dependencies": {
- "slice-ansi": "^5.0.0",
- "string-width": "^7.0.0"
+ "slice-ansi": "^7.1.0",
+ "string-width": "^8.0.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/string-width": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz",
+ "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==",
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.3.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -2740,96 +2884,31 @@
}
},
"node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
+ "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
"license": "ISC",
"dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/cliui/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
+ "string-width": "^7.2.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=20"
}
},
"node_modules/cliui/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
"license": "MIT",
"dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
@@ -3416,7 +3495,6 @@
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
"integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ansi-colors": "^4.1.1",
"strip-ansi": "^6.0.1"
@@ -3430,7 +3508,6 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -3440,7 +3517,6 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -3681,25 +3757,24 @@
}
},
"node_modules/eslint": {
- "version": "9.31.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz",
- "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
+ "version": "9.39.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz",
+ "integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.0",
- "@eslint/config-helpers": "^0.3.0",
- "@eslint/core": "^0.15.0",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.31.0",
- "@eslint/plugin-kit": "^0.3.1",
+ "@eslint/js": "9.39.0",
+ "@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
- "@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
@@ -3929,6 +4004,7 @@
"integrity": "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/types": "^8.35.0",
"comment-parser": "^1.4.1",
@@ -3997,9 +4073,9 @@
}
},
"node_modules/eslint-plugin-n": {
- "version": "17.21.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.21.0.tgz",
- "integrity": "sha512-1+iZ8We4ZlwVMtb/DcHG3y5/bZOdazIpa/4TySo22MLKdwrLcfrX0hbadnCvykSQCCmkAnWmIP8jZVb2AAq29A==",
+ "version": "17.23.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
+ "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4008,8 +4084,8 @@
"eslint-plugin-es-x": "^7.8.0",
"get-tsconfig": "^4.8.1",
"globals": "^15.11.0",
+ "globrex": "^0.1.2",
"ignore": "^5.3.2",
- "minimatch": "^9.0.5",
"semver": "^7.6.3",
"ts-declaration-location": "^1.0.6"
},
@@ -4023,16 +4099,6 @@
"eslint": ">=8.23.0"
}
},
- "node_modules/eslint-plugin-n/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
"node_modules/eslint-plugin-n/node_modules/globals": {
"version": "15.15.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
@@ -4046,22 +4112,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint-plugin-n/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/eslint-plugin-promise": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz",
@@ -4173,9 +4223,9 @@
}
},
"node_modules/eslint/node_modules/@eslint/js": {
- "version": "9.31.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz",
- "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==",
+ "version": "9.39.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz",
+ "integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4539,9 +4589,9 @@
}
},
"node_modules/get-east-asian-width": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
- "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz",
+ "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -5133,6 +5183,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -5740,12 +5797,15 @@
}
},
"node_modules/is-fullwidth-code-point": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
- "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz",
+ "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==",
"license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.3.1"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -6194,9 +6254,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -6330,12 +6390,12 @@
"license": "MIT"
},
"node_modules/listr2": {
- "version": "8.3.3",
- "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz",
- "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==",
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz",
+ "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==",
"license": "MIT",
"dependencies": {
- "cli-truncate": "^4.0.0",
+ "cli-truncate": "^5.0.0",
"colorette": "^2.0.20",
"eventemitter3": "^5.0.1",
"log-update": "^6.1.0",
@@ -6343,7 +6403,7 @@
"wrap-ansi": "^9.0.0"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=20.0.0"
}
},
"node_modules/listr2/node_modules/wrap-ansi": {
@@ -6480,37 +6540,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/log-update/node_modules/is-fullwidth-code-point": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
- "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
- "license": "MIT",
- "dependencies": {
- "get-east-asian-width": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-update/node_modules/slice-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
- "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.2.1",
- "is-fullwidth-code-point": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
"node_modules/log-update/node_modules/wrap-ansi": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
@@ -7927,51 +7956,51 @@
}
},
"node_modules/ora": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz",
- "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-9.0.0.tgz",
+ "integrity": "sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A==",
"license": "MIT",
"dependencies": {
- "chalk": "^5.3.0",
+ "chalk": "^5.6.2",
"cli-cursor": "^5.0.0",
- "cli-spinners": "^2.9.2",
+ "cli-spinners": "^3.2.0",
"is-interactive": "^2.0.0",
- "is-unicode-supported": "^2.0.0",
- "log-symbols": "^6.0.0",
+ "is-unicode-supported": "^2.1.0",
+ "log-symbols": "^7.0.1",
"stdin-discarder": "^0.2.2",
- "string-width": "^7.2.0",
- "strip-ansi": "^7.1.0"
+ "string-width": "^8.1.0",
+ "strip-ansi": "^7.1.2"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/ora/node_modules/log-symbols": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
- "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==",
+ "node_modules/ora/node_modules/cli-spinners": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.3.0.tgz",
+ "integrity": "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ==",
"license": "MIT",
- "dependencies": {
- "chalk": "^5.3.0",
- "is-unicode-supported": "^1.3.0"
- },
"engines": {
- "node": ">=18"
+ "node": ">=18.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
- "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "node_modules/ora/node_modules/string-width": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz",
+ "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==",
"license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.3.0",
+ "strip-ansi": "^7.1.0"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -9528,6 +9557,120 @@
"node": ">=18"
}
},
+ "node_modules/replace-in-file/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/replace-in-file/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/replace-in-file/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -9948,16 +10091,16 @@
}
},
"node_modules/slice-ansi": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
- "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
+ "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==",
"license": "MIT",
"dependencies": {
- "ansi-styles": "^6.0.0",
- "is-fullwidth-code-point": "^4.0.0"
+ "ansi-styles": "^6.2.1",
+ "is-fullwidth-code-point": "^5.0.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
@@ -10294,9 +10437,9 @@
}
},
"node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
@@ -10498,6 +10641,7 @@
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -10734,7 +10878,6 @@
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -10787,9 +10930,9 @@
}
},
"node_modules/undici": {
- "version": "7.10.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz",
- "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==",
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
+ "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
@@ -11079,9 +11222,9 @@
}
},
"node_modules/which": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
- "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz",
+ "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==",
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
@@ -11090,7 +11233,7 @@
"node-which": "bin/which.js"
},
"engines": {
- "node": "^18.17.0 || >=20.5.0"
+ "node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/which-boxed-primitive": {
@@ -11468,21 +11611,20 @@
}
},
"node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz",
+ "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==",
"license": "MIT",
"dependencies": {
- "cliui": "^8.0.1",
+ "cliui": "^9.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
+ "string-width": "^7.2.0",
"y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
+ "yargs-parser": "^22.0.0"
},
"engines": {
- "node": ">=12"
+ "node": "^20.19.0 || ^22.12.0 || >=23"
}
},
"node_modules/yargs-parser": {
@@ -11494,54 +11636,13 @@
"node": ">=12"
}
},
- "node_modules/yargs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/yargs/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "22.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
+ "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==",
+ "license": "ISC",
"engines": {
- "node": ">=8"
+ "node": "^20.19.0 || ^22.12.0 || >=23"
}
},
"node_modules/yocto-queue": {
diff --git a/package.json b/package.json
index e93344cb..bee6b404 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
{
"name": "@node-core/utils",
- "version": "5.16.2",
+ "version": "6.0.0",
"description": "Utilities for Node.js core collaborators",
"type": "module",
"engines": {
- "node": "^18.18.0 || >=20.0.0"
+ "node": "^20.19.0 || ^22.20.0 || >=24.10.0"
},
"bin": {
"get-metadata": "bin/get-metadata.js",
@@ -38,7 +38,7 @@
"@inquirer/prompts": "^7.4.1",
"@listr2/prompt-adapter-enquirer": "^2.0.12",
"@node-core/caritat": "^1.6.0",
- "@pkgjs/nv": "^0.2.2",
+ "@pkgjs/nv": "^0.3.0",
"branch-diff": "^3.1.1",
"chalk": "^5.4.1",
"changelog-maker": "^4.4.1",
@@ -49,15 +49,15 @@
"ghauth": "^6.0.12",
"git-secure-tag": "^2.3.1",
"js-yaml": "^4.1.0",
- "listr2": "^8.2.5",
+ "listr2": "^9.0.5",
"lodash": "^4.17.21",
"log-symbols": "^7.0.0",
- "ora": "^8.2.0",
+ "ora": "^9.0.0",
"replace-in-file": "^8.3.0",
"semver": "^7.7.1",
"undici": "^7.7.0",
- "which": "^5.0.0",
- "yargs": "^17.7.2"
+ "which": "^6.0.0",
+ "yargs": "^18.0.0"
},
"devDependencies": {
"@eslint/js": "^9.24.0",
diff --git a/test/fixtures/release/expected-test-process-release.js b/test/fixtures/release/expected-test-process-release.js
index c031f1f2..ebb259f7 100644
--- a/test/fixtures/release/expected-test-process-release.js
+++ b/test/fixtures/release/expected-test-process-release.js
@@ -1,6 +1,5 @@
'use strict';
-// eslint-disable-next-line n/no-missing-require
require('../common');
const assert = require('assert');
diff --git a/test/fixtures/release/original-test-process-release.js b/test/fixtures/release/original-test-process-release.js
index 72275a0b..13263894 100644
--- a/test/fixtures/release/original-test-process-release.js
+++ b/test/fixtures/release/original-test-process-release.js
@@ -1,6 +1,5 @@
'use strict';
-// eslint-disable-next-line n/no-missing-require
require('../common');
const assert = require('assert');
diff --git a/test/fixtures/run-auth-github.js b/test/fixtures/run-auth-github.js
index d7151ea6..30f4c2c3 100644
--- a/test/fixtures/run-auth-github.js
+++ b/test/fixtures/run-auth-github.js
@@ -16,6 +16,11 @@ async function mockCredentials(options) {
(async function() {
const { default: auth } = await import('../../lib/auth.js');
const authParams = await auth({ github: true }, mockCredentials);
+ if (typeof authParams === 'object' && authParams != null) {
+ for (const key of Object.getOwnPropertyNames(authParams)) {
+ if (key !== 'github') delete authParams[key];
+ }
+ }
process.stdout.write(`${JSON.stringify(authParams)}\n`);
})().catch(err => {
console.error(err);
diff --git a/test/unit/auth.test.js b/test/unit/auth.test.js
index 3bc7d948..e753cb87 100644
--- a/test/unit/auth.test.js
+++ b/test/unit/auth.test.js
@@ -21,14 +21,16 @@ describe('auth', async function() {
it('asks for auth data if no ncurc is found', async function() {
await runAuthScript(
undefined,
- [FIRST_TIME_MSG, MOCKED_TOKEN]
+ [FIRST_TIME_MSG, MOCKED_TOKEN],
+ /^Spawning gpg to encrypt the config value\r?\nError: spawn do-not-exist ENOENT(?:.*\n)+Failed encrypt token, storing unencrypted instead\r?\n$/
);
});
it('asks for auth data if ncurc is invalid json', async function() {
await runAuthScript(
{ HOME: 'this is not json' },
- [FIRST_TIME_MSG, MOCKED_TOKEN]
+ [FIRST_TIME_MSG, MOCKED_TOKEN],
+ /^Spawning gpg to encrypt the config value\r?\nError: spawn do-not-exist ENOENT(?:.*\n)+Failed encrypt token, storing unencrypted instead\r?\n$/
);
});
@@ -117,7 +119,7 @@ describe('auth', async function() {
function runAuthScript(
ncurc = {}, expect = [], error = '', fixture = 'run-auth-github') {
return new Promise((resolve, reject) => {
- const newEnv = { HOME: undefined, XDG_CONFIG_HOME: undefined };
+ const newEnv = { HOME: undefined, XDG_CONFIG_HOME: undefined, GPG_BIN: 'do-not-exist' };
if (ncurc.HOME === undefined) ncurc.HOME = ''; // HOME must always be set.
for (const envVar in ncurc) {
if (ncurc[envVar] === undefined) continue;
@@ -154,8 +156,9 @@ function runAuthScript(
});
proc.on('close', () => {
try {
- assert.strictEqual(stderr, error);
- assert.strictEqual(expect.length, 0);
+ if (typeof error === 'string') assert.strictEqual(stderr, error);
+ else assert.match(stderr, error);
+ assert.deepStrictEqual(expect, []);
if (newEnv.HOME) {
fs.rmSync(newEnv.HOME, { recursive: true, force: true });
}
diff --git a/test/unit/ci_start.test.js b/test/unit/ci_start.test.js
index 154356e4..cd8df818 100644
--- a/test/unit/ci_start.test.js
+++ b/test/unit/ci_start.test.js
@@ -1,8 +1,7 @@
-/* eslint-disable import/no-named-as-default-member */
import { describe, it, before, afterEach } from 'node:test';
import assert from 'assert';
-import sinon from 'sinon';
+import * as sinon from 'sinon';
import { FormData } from 'undici';
import {
diff --git a/test/unit/pr_checker.test.js b/test/unit/pr_checker.test.js
index bd98c6e4..4542e194 100644
--- a/test/unit/pr_checker.test.js
+++ b/test/unit/pr_checker.test.js
@@ -1,8 +1,7 @@
-/* eslint-disable import/no-named-as-default-member */
import { describe, it, before, after, afterEach } from 'node:test';
import assert from 'node:assert';
-import sinon from 'sinon';
+import * as sinon from 'sinon';
import PRData from '../../lib/pr_data.js';
import PRChecker from '../../lib/pr_checker.js';
@@ -51,6 +50,7 @@ const GT_7D = '2018-11-23T17:50:44.477Z';
const LT_7D_GT_48H = '2018-11-27T17:50:44.477Z';
const LT_48H = '2018-11-30T17:50:44.477Z';
const LT_48H_GT_47H = '2018-11-29T17:55:44.477Z';
+const LT_48H_GT_47_59 = '2018-11-29T17:51:43.477Z';
const NOW = '2018-11-31T17:50:44.477Z';
const argv = { maxCommits: 3 };
@@ -305,6 +305,43 @@ describe('PRChecker', () => {
cli.assertCalledWith(expectedLogs);
});
+ it('should error when PR is younger than 48h and older than 47h58min', () => {
+ const cli = new TestCLI();
+
+ const expectedLogs = {
+ ok:
+ [['Approvals: 4'],
+ ['- Foo User (@foo): https://github.com/nodejs/node/pull/16438#pullrequestreview-71480624'],
+ ['- Quux User (@Quux): LGTM'],
+ ['- Baz User (@Baz): https://github.com/nodejs/node/pull/16438#pullrequestreview-71488236'],
+ ['- Bar User (@bar) (TSC): lgtm']],
+ info: [['This PR was created on Thu, 29 Nov 2018 17:51:43 GMT']],
+ error: [['This PR needs to wait 1 more minute to land']]
+ };
+
+ const youngPR = Object.assign({}, firstTimerPR, {
+ createdAt: LT_48H_GT_47_59
+ });
+
+ const data = {
+ pr: youngPR,
+ reviewers: allGreenReviewers,
+ comments: commentsWithLGTM,
+ reviews: approvingReviews,
+ commits: simpleCommits,
+ collaborators,
+ authorIsNew: () => true,
+ getThread() {
+ return PRData.prototype.getThread.call(this);
+ }
+ };
+ const checker = new PRChecker(cli, data, {}, argv);
+
+ const status = checker.checkReviewsAndWait(new Date(NOW));
+ assert(!status);
+ cli.assertCalledWith(expectedLogs);
+ });
+
it('should error when PR has only 1 approval < 48h', () => {
const cli = new TestCLI();
@@ -351,7 +388,7 @@ describe('PRChecker', () => {
info:
[['This PR was created on Tue, 27 Nov 2018 17:50:44 GMT']],
error: [['This PR needs to wait 72 more hours to land ' +
- '(or 0 hours if there is one more approval)']]
+ '(or 0 minutes if there is one more approval)']]
};
const youngPR = Object.assign({}, firstTimerPR, {
diff --git a/test/unit/pr_data.test.js b/test/unit/pr_data.test.js
index 1b4870ff..86f7b31d 100644
--- a/test/unit/pr_data.test.js
+++ b/test/unit/pr_data.test.js
@@ -1,8 +1,7 @@
-/* eslint-disable import/no-named-as-default-member */
import { describe, it } from 'node:test';
import assert from 'node:assert';
-import sinon from 'sinon';
+import * as sinon from 'sinon';
import PRData from '../../lib/pr_data.js';
diff --git a/test/unit/team_info.test.js b/test/unit/team_info.test.js
index a696204a..89e7e1f6 100644
--- a/test/unit/team_info.test.js
+++ b/test/unit/team_info.test.js
@@ -1,8 +1,7 @@
-/* eslint-disable import/no-named-as-default-member */
import { describe, it, before, after } from 'node:test';
import assert from 'node:assert';
-import sinon from 'sinon';
+import * as sinon from 'sinon';
import TestCLI from '../fixtures/test_cli.js';
import TeamInfo from '../../lib/team_info.js';