From ad187c5ca140b6473fe3a9dab984e09ee7e80540 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 00:52:38 +0200 Subject: [PATCH 01/12] chore: modernize to TypeScript 7, native ESM and node:test - native ES modules: type=module, exports map, explicit .js import extensions, engines node >=22.12.0; createRequire shims where JSON / CJS-callable modules are loaded (package.json, command-exists, word-wrap, licenses.json) - yargs commandDir() is unsupported under ESM: all commands and subcommands are now registered explicitly via .command(module) - deps: @imqueue/core ^3.2.1, @imqueue/rpc ^3.2.1 (ESM majors), @octokit/rest 16 -> 22 (teams.list instead of removed orgs.getTeams, status-based 404 detection, plain token auth), deprecated 'request' replaced with global fetch, node-rsa via default import - autoupdate: prompts only when the registry version is actually newer (semver.gt instead of !==) and never in non-interactive runs, which previously crashed piped invocations (ERR_USE_AFTER_CLOSE) - tests migrated from mocha/chai/mock-require/nyc to node:test with mock.module for ioredis/command-exists; cli file locations sandboxed in tests via new IMQ_CLI_HOME env override (lib/constants is part of a module cycle with lib/path, which made ESM module-mocking of it unreliable) - lint/format switched from eslint to oxlint + oxfmt; devDeps reduced - version bumped to 3.0.0 --- .github/workflows/build.yml | 44 +- .oxfmtrc.json | 9 + .oxlintrc.json | 20 + index.ts | 24 +- lib/autoupdate.ts | 35 +- lib/config.ts | 28 +- lib/constants.ts | 17 +- lib/error.ts | 10 +- lib/fs.ts | 16 +- lib/github.ts | 32 +- lib/index.ts | 26 +- lib/license.ts | 84 +- lib/names.ts | 16 +- lib/node.ts | 84 +- lib/path.ts | 2 +- lib/template.ts | 30 +- lib/travis.ts | 25 +- package-lock.json | 5637 +++++------------ package.json | 105 +- scripts/strip-comment-coverage.mjs | 472 ++ src/client.ts | 7 +- src/client/generate.ts | 32 +- src/completions.ts | 9 +- src/completions/off.ts | 37 +- src/completions/on.ts | 40 +- src/config.ts | 13 +- src/config/check.ts | 4 +- src/config/get.ts | 42 +- src/config/init.ts | 477 +- src/config/set.ts | 23 +- src/service.ts | 9 +- src/service/create.ts | 374 +- src/service/update-version.ts | 74 +- test/lib/{config.ts => config.spec.ts} | 90 +- test/lib/{error.ts => error.spec.ts} | 9 +- test/lib/{fs.ts => fs.spec.ts} | 73 +- test/lib/{github.ts => github.spec.ts} | 78 +- test/lib/{license.ts => license.spec.ts} | 25 +- test/lib/{names.ts => names.spec.ts} | 37 +- test/lib/node.spec.ts | 110 + test/lib/node.ts | 101 - test/lib/{path.ts => path.spec.ts} | 13 +- test/lib/{template.ts => template.spec.ts} | 34 +- test/lib/{travis.ts => travis.spec.ts} | 33 +- test/lib/{validate.ts => validate.spec.ts} | 31 +- test/mocks/command-exists.ts | 14 +- test/mocks/constants.ts | 39 - test/mocks/index.ts | 31 +- test/mocks/logger.ts | 2 +- test/mocks/redis.ts | 93 +- test/src/{client.ts => client.spec.ts} | 17 +- .../client/{generate.ts => generate.spec.ts} | 17 +- .../{completions.ts => completions.spec.ts} | 17 +- test/src/completions/{off.ts => off.spec.ts} | 17 +- test/src/completions/{on.ts => on.spec.ts} | 17 +- test/src/{config.ts => config.spec.ts} | 17 +- test/src/config/{check.ts => check.spec.ts} | 17 +- test/src/config/{get.ts => get.spec.ts} | 17 +- test/src/config/{init.ts => init.spec.ts} | 17 +- test/src/config/{set.ts => set.spec.ts} | 17 +- test/src/{service.ts => service.spec.ts} | 17 +- .../src/service/{create.ts => create.spec.ts} | 17 +- tsconfig.json | 38 +- 63 files changed, 3669 insertions(+), 5243 deletions(-) create mode 100644 .oxfmtrc.json create mode 100644 .oxlintrc.json create mode 100644 scripts/strip-comment-coverage.mjs rename test/lib/{config.ts => config.spec.ts} (61%) rename test/lib/{error.ts => error.spec.ts} (83%) rename test/lib/{fs.ts => fs.spec.ts} (63%) rename test/lib/{github.ts => github.spec.ts} (72%) rename test/lib/{license.ts => license.spec.ts} (64%) rename test/lib/{names.ts => names.spec.ts} (55%) create mode 100644 test/lib/node.spec.ts delete mode 100644 test/lib/node.ts rename test/lib/{path.ts => path.spec.ts} (78%) rename test/lib/{template.ts => template.spec.ts} (78%) rename test/lib/{travis.ts => travis.spec.ts} (69%) rename test/lib/{validate.ts => validate.spec.ts} (62%) delete mode 100644 test/mocks/constants.ts rename test/src/{client.ts => client.spec.ts} (71%) rename test/src/client/{generate.ts => generate.spec.ts} (71%) rename test/src/{completions.ts => completions.spec.ts} (71%) rename test/src/completions/{off.ts => off.spec.ts} (71%) rename test/src/completions/{on.ts => on.spec.ts} (71%) rename test/src/{config.ts => config.spec.ts} (71%) rename test/src/config/{check.ts => check.spec.ts} (71%) rename test/src/config/{get.ts => get.spec.ts} (71%) rename test/src/config/{init.ts => init.spec.ts} (71%) rename test/src/config/{set.ts => set.spec.ts} (71%) rename test/src/{service.ts => service.spec.ts} (71%) rename test/src/service/{create.ts => create.spec.ts} (71%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 934f1aa..a73a350 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,17 +1,50 @@ -name: Node.js CI +name: Build on: push: + branches: [master, v3] + tags: ['*'] pull_request: +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - build: + quality: + name: Lint & format runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 24.x + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Check formatting + run: npm run format:check + - name: Lint + run: npm run lint + + test: + name: Test (Node ${{ matrix.node-version }}) + runs-on: ubuntu-latest + timeout-minutes: 15 strategy: + fail-fast: false matrix: - node-version: [lts/*] - + node-version: [22.x, 24.x] steps: - name: Checkout repository uses: actions/checkout@v4 @@ -20,9 +53,10 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + cache: npm - name: Install dependencies - run: npm install + run: npm ci - name: Run tests run: npm test diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..16d1869 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,9 @@ +{ + "singleQuote": true, + "tabWidth": 4, + "printWidth": 80, + "semi": true, + "trailingComma": "all", + "arrowParens": "avoid", + "bracketSpacing": true +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..2757f3e --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,20 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "error" + }, + "rules": { + "no-debugger": "error", + "no-console": ["warn", { "allow": ["warn", "error", "info"] }], + "no-unused-vars": "warn" + }, + "ignorePatterns": [ + "**/*.js", + "**/*.d.ts", + "docs/", + "coverage/", + ".nyc_output/", + ".agent-out/", + "node_modules/" + ] +} diff --git a/index.ts b/index.ts index bf1ad66..06e2da1 100644 --- a/index.ts +++ b/index.ts @@ -24,21 +24,29 @@ */ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { VERSION, checkForUpdate } from './lib'; +import { VERSION, checkForUpdate } from './lib/index.js'; +import * as client from './src/client.js'; +import * as completions from './src/completions.js'; +import * as config from './src/config.js'; +import * as service from './src/service.js'; (async () => { const y = yargs(hideBin(process.argv)); await checkForUpdate(); - await y.usage('IMQ Command Line Interface' + - `\nVersion: ${VERSION}` + - '\n\nUsage: $0 ') + await y + .usage( + 'IMQ Command Line Interface' + + `\nVersion: ${VERSION}` + + '\n\nUsage: $0 ', + ) .version(VERSION) - .commandDir('src') + .command(client as any) + .command(completions as any) + .command(config as any) + .command(service as any) .demandCommand() .wrap(y.terminalWidth()) - .help() - .argv - ; + .help().argv; })(); diff --git a/lib/autoupdate.ts b/lib/autoupdate.ts index 4fb88cf..318e267 100644 --- a/lib/autoupdate.ts +++ b/lib/autoupdate.ts @@ -22,7 +22,11 @@ * to get commercial licensing options. */ import { execSync } from 'child_process'; -import inquirer, { QuestionCollection } from 'inquirer'; +import inquirer, { type QuestionCollection } from 'inquirer'; +import { createRequire } from 'node:module'; +import * as semver from 'semver'; + +const require = createRequire(import.meta.url); const pkg = require('../package.json'); @@ -32,20 +36,31 @@ const pkg = require('../package.json'); */ export async function checkForUpdate() { try { + // non-interactive runs (pipes, CI) must never hang on a prompt + if (!process.stdin.isTTY || !process.stdout.isTTY) { + return; + } + const remoteVersion = execSync(`npm show ${pkg.name} version`) - .toString('utf8').trim(); + .toString('utf8') + .trim(); const localVersion = pkg.version.trim(); - if (remoteVersion !== localVersion) { + // prompt only for a real upgrade, not when running a newer + // (e.g. not yet published) local version + if (semver.gt(remoteVersion, localVersion)) { const answer: { update: boolean } = await inquirer.prompt<{ update: boolean; - }>([{ - type: 'confirm', - name: 'update', - message: `New version ${remoteVersion} of ${ - pkg.name} available. Would you like to update?`, - default: true, - }] as QuestionCollection); + }>([ + { + type: 'confirm', + name: 'update', + message: `New version ${remoteVersion} of ${ + pkg.name + } available. Would you like to update?`, + default: true, + }, + ] as QuestionCollection); if (answer.update) { update(); diff --git a/lib/config.ts b/lib/config.ts index b489995..adb0e13 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -24,10 +24,10 @@ import { readFileSync as read, writeFileSync as write, - existsSync as exists + existsSync as exists, } from 'fs'; -import { touch } from './fs'; -import { CONFIG_PATH } from './constants'; +import { touch } from './fs.js'; +import { CONFIG_PATH } from './constants.js'; export interface IMQCLIConfig { [options: string]: any; @@ -73,13 +73,13 @@ export function saveConfig(config: IMQCLIConfig) { * @return {boolean} */ export function configEmpty() { - if (!exists(CONFIG_PATH)) { - return true; - } + if (!exists(CONFIG_PATH)) { + return true; + } - const config = loadConfig(); + const config = loadConfig(); - return !(config && Object.keys(config).length); + return !(config && Object.keys(config).length); } /** @@ -93,10 +93,14 @@ export function configEmpty() { export function prepareConfigValue(value: any) { if (typeof value === 'string') { switch (value) { - case 'true': return true; - case 'false': return false; - case 'null': return null; - case 'undefined': return undefined; + case 'true': + return true; + case 'false': + return false; + case 'null': + return null; + case 'undefined': + return undefined; } // istanbul ignore else diff --git a/lib/constants.ts b/lib/constants.ts index 7bbc80e..38baaee 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -22,14 +22,23 @@ * to get commercial licensing options. */ import * as os from 'os'; -import { resolve } from './path'; +import { resolve } from './path.js'; +import { createRequire } from 'node:module'; -export const OS_HOME: string = os.homedir() || String(process.env['HOME']); +const require = createRequire(import.meta.url); + +// IMQ_CLI_HOME allows tests (or callers) to sandbox all cli file locations +export const OS_HOME: string = + process.env.IMQ_CLI_HOME || os.homedir() || String(process.env['HOME']); export const IMQ_HOME = '~/.imq'; export const TPL_REPO = 'git@github.com:imqueue/templates.git'; export const TPL_HOME = resolve(IMQ_HOME, 'templates'); export const CUSTOM_TPL_HOME = resolve(IMQ_HOME, 'custom-templates'); export const CONFIG_FILENAME = 'config.json'; export const CONFIG_PATH = resolve(IMQ_HOME, CONFIG_FILENAME); -export const IS_ZSH = Object.keys(process.env).some(key => /^ZSH/.test(key)); -export const VERSION = require(`${__dirname}/../package.json`).version; +export const IS_ZSH = Object.keys(process.env).some(key => + key.startsWith('ZSH'), +); +export const VERSION = require( + `${import.meta.dirname}/../package.json`, +).version; diff --git a/lib/error.ts b/lib/error.ts index c131dc1..d07b18a 100644 --- a/lib/error.ts +++ b/lib/error.ts @@ -38,11 +38,13 @@ export function printError(err: Error, withStackTrace: boolean = false) { let obj = JSON.parse(message); if (obj.message && obj.errors) { - message = `${obj.message}: ${ - obj.errors.map((err: any) => err.message).join('\n') - }`; + message = `${obj.message}: ${obj.errors + .map((err: any) => err.message) + .join('\n')}`; } - } catch (err) { /* ignore */ } + } catch (err) { + /* ignore */ + } process.stderr.write(chalk.bold.red(message) + '\n'); diff --git a/lib/fs.ts b/lib/fs.ts index 9fdad7f..d3ccedd 100644 --- a/lib/fs.ts +++ b/lib/fs.ts @@ -23,7 +23,7 @@ */ import * as fs from 'fs'; import * as p from 'path'; -import { resolve } from '.'; +import { resolve } from './index.js'; /** * Copy contents from source directory to destination directory @@ -46,9 +46,7 @@ export function cpr(from: string, to: string) { if (fs.statSync(fromPath).isDirectory()) { cpr(fromPath, toPath); - } - - else { + } else { fs.copyFileSync(fromPath, toPath); } }); @@ -63,7 +61,7 @@ export function rmdir(path: string) { let files = []; // istanbul ignore else - if( fs.existsSync(path) ) { + if (fs.existsSync(path)) { files = fs.readdirSync(path); files.forEach(file => { @@ -88,10 +86,8 @@ export function rmdir(path: string) { export function mkdirp(path: string): void { try { fs.mkdirSync(path); - } - - catch (err) { - if (err.code === 'ENOENT') { + } catch (err) { + if ((err as NodeJS.ErrnoException).code === 'ENOENT') { mkdirp(p.dirname(path)); return mkdirp(path); } @@ -113,7 +109,7 @@ export function mkdirp(path: string): void { export function touch( path: string, // istanbul ignore next - content: string = '' + content: string = '', ): void { if (!fs.existsSync(path)) { mkdirp(p.dirname(path)); diff --git a/lib/github.ts b/lib/github.ts index c4f38b5..a18b271 100644 --- a/lib/github.ts +++ b/lib/github.ts @@ -35,12 +35,13 @@ const RX_DEPRECATION = /Deprecation:/; */ export async function getTeam(github: Github, owner: string): Promise { try { - // noinspection TypeScriptUnresolvedFunction - return ((await (github.orgs as any).getTeams({ - org: owner - }) || /* istanbul ignore next */{} as any) - .data || /* istanbul ignore next */[]) - .shift(); + return ( + ( + (await github.teams.list({ + org: owner, + })) || /* istanbul ignore next */ ({} as any) + ).data || /* istanbul ignore next */ [] + ).shift(); } catch (err) { return null; } @@ -57,9 +58,7 @@ export async function getTeam(github: Github, owner: string): Promise { export async function getOrg(github: Github, owner: string): Promise { try { return (await github.orgs.get({ org: owner })).data; - } - - catch (err) { + } catch (err) { return null; } } @@ -71,7 +70,7 @@ export async function getOrg(github: Github, owner: string): Promise { * @return {Promise} */ export async function getInstance(token: string): Promise { - return new Github({ auth: `token ${token}` }); + return new Github({ auth: token }); } /** @@ -89,8 +88,9 @@ export async function createRepository( description: string, isPrivate: boolean = true, ) { - const [owner, repo] = (url.split(':').reverse().shift() || - /* istanbul ignore next */'').split('/'); + const [owner, repo] = ( + url.split(':').reverse().shift() || /* istanbul ignore next */ '' + ).split('/'); if (!(repo && owner)) { throw new TypeError(`Given github url "${url}" is invalid!`); @@ -106,13 +106,15 @@ export async function createRepository( // noinspection ExceptionCaughtLocallyJS throw new Error('Repository already exists!'); } - } catch(err) { - if (err.code !== 404 && !RX_DEPRECATION.test(err.message)) { + } catch (err) { + const status = (err as any).status ?? (err as any).code; + + if (status !== 404 && !RX_DEPRECATION.test((err as Error).message)) { throw err; } } - await (github.repos as any).createInOrg({ + await github.repos.createInOrg({ org: owner, name: repo, private: isPrivate, diff --git a/lib/index.ts b/lib/index.ts index 97854bd..2ec8aea 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -21,16 +21,16 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -export * from './constants'; -export * from './validate'; -export * from './names'; -export * from './error'; -export * from './config'; -export * from './license'; -export * from './fs'; -export * from './path'; -export * from './travis'; -export * from './template'; -export * from './github'; -export * from './node'; -export * from './autoupdate'; +export * from './constants.js'; +export * from './validate.js'; +export * from './names.js'; +export * from './error.js'; +export * from './config.js'; +export * from './license.js'; +export * from './fs.js'; +export * from './path.js'; +export * from './travis.js'; +export * from './template.js'; +export * from './github.js'; +export * from './node.js'; +export * from './autoupdate.js'; diff --git a/lib/license.ts b/lib/license.ts index 15d3063..52fbf04 100644 --- a/lib/license.ts +++ b/lib/license.ts @@ -21,18 +21,18 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import * as inquirer from 'inquirer'; +import inquirer from 'inquirer'; import autocompletePrompt from 'inquirer-autocomplete-prompt'; +import { createRequire } from 'node:module'; -(inquirer).registerPrompt( - 'autocomplete', - autocompletePrompt, -); +const require = createRequire(import.meta.url); + +(inquirer).registerPrompt('autocomplete', autocompletePrompt); const LICENSES: any = require('./licenses.json'); // noinspection RegExpRedundantEscape -const RX_ESCAPE = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g; +const RX_ESCAPE = /[-[\]/{}()*+?.\\^$|]/g; /** * Finds and returns license object by a given name pattern @@ -42,19 +42,17 @@ const RX_ESCAPE = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g; */ export function findLicense(name: string): any { for (let id of Object.keys(LICENSES)) { - if (name === id || + if ( + name === id || name.toLowerCase() === id || - new RegExp(`^${name.toLowerCase()}`, 'i') - .test(LICENSES[id].spdx_id) + new RegExp(`^${name.toLowerCase()}`, 'i').test(LICENSES[id].spdx_id) ) { return LICENSES[id]; } } for (let id of Object.keys(LICENSES)) { - if (new RegExp(`^${name.toLowerCase()}`, 'i') - .test(LICENSES[id].name) - ) { + if (new RegExp(`^${name.toLowerCase()}`, 'i').test(LICENSES[id].name)) { return LICENSES[id]; } } @@ -69,45 +67,55 @@ export function findLicense(name: string): any { * @return {Promise<{id: string; name: string}>} */ export async function licensingOptions(): Promise<{ - id: string, - name: string + id: string; + name: string; }> { - let answer: any = await ((inquirer as any).prompt)([{ - type: 'confirm', - name: 'addLicense', - message: 'Would you like to use specific license for your services?', - default: true - }]); + let answer: any = await ((inquirer as any).prompt)([ + { + type: 'confirm', + name: 'addLicense', + message: + 'Would you like to use specific license for your services?', + default: true, + }, + ]); let licenseName = 'UNLICENSED'; if (!answer.addLicense) { return { id: licenseName, name: licenseName }; } - const licenses: string[] = Object.keys(LICENSES) - .map((id: string) => LICENSES[id]); + const licenses: string[] = Object.keys(LICENSES).map( + (id: string) => LICENSES[id], + ); - answer = await ((inquirer as any).prompt)([{ - type: 'autocomplete', - name: 'licenseName', - message: 'Select license:', - source: async (answers: any, input: string) => { - return licenses.filter((license: any) => { - let rx = new RegExp( - `^${(input || '').replace(RX_ESCAPE, "\\$&")}`, 'i' - ); + answer = await ((inquirer as any).prompt)([ + { + type: 'autocomplete', + name: 'licenseName', + message: 'Select license:', + source: async (answers: any, input: string) => { + return licenses + .filter((license: any) => { + let rx = new RegExp( + `^${(input || '').replace(RX_ESCAPE, '\\$&')}`, + 'i', + ); - return license.key.match(rx) || license.name.match(rx); - }).map((license: any) => license && license.name || ''); - } - }]); + return license.key.match(rx) || license.name.match(rx); + }) + .map((license: any) => (license && license.name) || ''); + }, + }, + ]); - const license: any = licenses.find((license: any) => - license.name === answer.licenseName); + const license: any = licenses.find( + (license: any) => license.name === answer.licenseName, + ); if (license) { licenseName = license.name; } return { id: license.spdx_id, name: licenseName }; -} \ No newline at end of file +} diff --git a/lib/names.ts b/lib/names.ts index ef7e3ec..0c3ca9e 100644 --- a/lib/names.ts +++ b/lib/names.ts @@ -21,7 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -const RX_NON_ALLOWED = /[^-a-z0-9]/ig; +const RX_NON_ALLOWED = /[^-a-z0-9]/gi; const RX_CAP = /([A-Z])/g; const RX_DBL = /--/g; const RX_FIRST = /^-/; @@ -41,8 +41,7 @@ export function dashed(name: string): string { .replace(RX_NON_ALLOWED, '-') .replace(RX_CAP, m => `-${m.toLowerCase()}`) .replace(RX_DBL, '-') - .replace(RX_FIRST, '') - ; + .replace(RX_FIRST, ''); if (!RX_LETTER.test(name[0])) { dashed = `-${dashed}`; @@ -60,8 +59,11 @@ export function dashed(name: string): string { export function camelCase(name: string): string { name = name.trim(); - return (!RX_LETTER.test(name[0]) ? name[0] : '') + name - .split(RX_SPLIT) - .map(s => s.substr(0, 1).toUpperCase() + s.substr(1)) - .join(''); + return ( + (!RX_LETTER.test(name[0]) ? name[0] : '') + + name + .split(RX_SPLIT) + .map(s => s.substr(0, 1).toUpperCase() + s.substr(1)) + .join('') + ); } diff --git a/lib/node.ts b/lib/node.ts index e30f02d..295a120 100644 --- a/lib/node.ts +++ b/lib/node.ts @@ -21,7 +21,6 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import * as request from 'request'; import * as semver from 'semver'; const RX_VERSION_CLEAN = /^v/; @@ -70,28 +69,30 @@ export function semverCompare(a: string, b: string) { * @return {Promise} */ export async function getNodeVersions( - force: boolean = false + force: boolean = false, ): Promise { // istanbul ignore if if (!force && nodeVersions) { return nodeVersions; } - return new Promise((resolve, reject) => { - request('https://nodejs.org/dist/index.json', (err, res) => { - // istanbul ignore if - if (err) return reject(err); - - nodeVersions = (JSON.parse(res.body) || - /* istanbul ignore next */[]) - .sort((a: NodeVersion, b: NodeVersion) => semverCompare( - a.version.replace(RX_VERSION_CLEAN, ''), - b.version.replace(RX_VERSION_CLEAN, '') - )); - - resolve(nodeVersions); - }); - }); + const res = await fetch('https://nodejs.org/dist/index.json'); + + // istanbul ignore if + if (!res.ok) { + throw new Error(`Failed to fetch node versions: HTTP ${res.status}`); + } + + nodeVersions = ( + ((await res.json()) as NodeVersion[]) || /* istanbul ignore next */ [] + ).sort((a: NodeVersion, b: NodeVersion) => + semverCompare( + a.version.replace(RX_VERSION_CLEAN, ''), + b.version.replace(RX_VERSION_CLEAN, ''), + ), + ); + + return nodeVersions; } /** @@ -106,26 +107,33 @@ export async function nodeVersion(tag: string) { switch (tag) { case 'node': case 'latest': { - return (((versions || /* istanbul ignore next */[])[0] || - /* istanbul ignore next */{}) - .version || /* istanbul ignore next */'') - .replace(RX_VERSION_CLEAN, ''); + return ( + ( + (versions || /* istanbul ignore next */ [])[0] || + /* istanbul ignore next */ {} + ).version || /* istanbul ignore next */ '' + ).replace(RX_VERSION_CLEAN, ''); } case 'stable': case 'lts': case 'lts/*': { - return ((versions.find(version => !!version.lts) || - /* istanbul ignore next */{}) - .version || /* istanbul ignore next */'') - .replace(RX_VERSION_CLEAN, ''); + return ( + ( + versions.find(version => !!version.lts) || + /* istanbul ignore next */ {} + ).version || /* istanbul ignore next */ '' + ).replace(RX_VERSION_CLEAN, ''); } default: { - return ((versions.find(version => - new RegExp(`^v${tag.replace(RX_ESCAPE, '\\.')}`) - .test(version.version) - ) /* istanbul ignore next */|| {}) - .version || /* istanbul ignore next */'') - .replace(RX_VERSION_CLEAN, ''); + return ( + ( + versions.find(version => + new RegExp(`^v${tag.replace(RX_ESCAPE, '\\.')}`).test( + version.version, + ), + ) /* istanbul ignore next */ || {} + ).version || /* istanbul ignore next */ '' + ).replace(RX_VERSION_CLEAN, ''); } } } @@ -149,9 +157,17 @@ export async function toTravisTags(tags: string | string[]): Promise { for (let tag of tags) { switch (tag) { - case 'stable': case 'lts': travisTags.push('lts/*'); - case 'latest': travisTags.push('node'); break; - default: travisTags.push(tag); break; + case 'stable': + case 'lts': + travisTags.push('lts/*'); + travisTags.push('node'); + break; + case 'latest': + travisTags.push('node'); + break; + default: + travisTags.push(tag); + break; } } diff --git a/lib/path.ts b/lib/path.ts index 0ace605..bff994e 100644 --- a/lib/path.ts +++ b/lib/path.ts @@ -22,7 +22,7 @@ * to get commercial licensing options. */ import * as p from 'path'; -import { OS_HOME } from './constants'; +import { OS_HOME } from './constants.js'; /** * Resolves given path to an absolute canonical path diff --git a/lib/template.ts b/lib/template.ts index 04903b3..de5d4b9 100644 --- a/lib/template.ts +++ b/lib/template.ts @@ -22,15 +22,18 @@ * to get commercial licensing options. */ import inquirer from 'inquirer'; +import { createRequire } from 'node:module'; import { TPL_HOME, CUSTOM_TPL_HOME, TPL_REPO, rmdir, resolve, -} from '.'; +} from './index.js'; import * as fs from 'fs'; import { execSync } from 'child_process'; + +const require = createRequire(import.meta.url); const commandExists = require('command-exists').sync; const wordWrap = require('word-wrap'); @@ -67,9 +70,7 @@ export function checkGit() { export async function loadTemplates() { if (fs.existsSync(TPL_HOME)) { await updateTemplates(); - } - - else { + } else { checkGit(); console.log('Loading IMQ templates, please, wait...'); execSync(`git clone ${TPL_REPO} ${TPL_HOME}`); @@ -78,7 +79,7 @@ export async function loadTemplates() { return fs.readdirSync(TPL_HOME).reduce((res: any, next: any) => { const path = resolve(TPL_HOME, next); - if (/^\./.test(next)) return res; + if (next.startsWith('.')) return res; if (fs.statSync(path).isDirectory()) { res[next] = path; @@ -116,17 +117,20 @@ export async function updateTemplates() { * @return {Promise} */ export async function loadTemplate(url: string): Promise { - const name = (url.split(/[\/]/).pop() || '').replace(/\.git$/, ''); + const name = (url.split(/[/]/).pop() || '').replace(/\.git$/, ''); const path = resolve(CUSTOM_TPL_HOME, name); if (fs.existsSync(path)) { - let answer = await inquirer.prompt<{ overwrite: boolean }>([{ - type: 'confirm', - name: 'overwrite', - message: 'Seems such template was already loaded, would you like ' + - 'to fetch it again and overwrite?', - default: false - }]); + let answer = await inquirer.prompt<{ overwrite: boolean }>([ + { + type: 'confirm', + name: 'overwrite', + message: + 'Seems such template was already loaded, would you like ' + + 'to fetch it again and overwrite?', + default: false, + }, + ]); if (!answer.overwrite) { return path; diff --git a/lib/travis.ts b/lib/travis.ts index 2abf64e..8238921 100644 --- a/lib/travis.ts +++ b/lib/travis.ts @@ -21,9 +21,9 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import * as NodeRSA from 'node-rsa'; +import NodeRSA from 'node-rsa'; import { TravisClient } from '@imqueue/travis'; -import { sleep } from './node'; +import { sleep } from './node.js'; /** * Returns encrypted secure key for travis sensitive data. @@ -37,7 +37,7 @@ import { sleep } from './node'; export async function travisEncrypt( repository: string, data: string, - github_token?: string + github_token?: string, ): Promise { const travis = new TravisClient({ pro: !!github_token }); @@ -69,20 +69,16 @@ export async function trySyncBuilds( travis: TravisClient, retry: number = 0, maxRetries: number = 3, - delay: number = 2000 + delay: number = 2000, ): Promise { try { await travis.users.sync.post(); await sleep(delay); - } catch(err) { + } catch (err) { if (retry < maxRetries) { await sleep(delay); - return trySyncBuilds( - travis, - ++retry, - maxRetries - ); + return trySyncBuilds(travis, ++retry, maxRetries); } return false; @@ -104,15 +100,16 @@ export async function enableBuilds( owner: string, repo: string, github_token: string, - isPrivate: boolean + isPrivate: boolean, ) { const travis = new TravisClient({ pro: isPrivate }); await travis.authenticate({ github_token }); await trySyncBuilds(travis); - const hook = (await travis.hooks.get()).hooks.find((hook: any) => - hook.owner_name === owner && hook.name === repo); + const hook = (await travis.hooks.get()).hooks.find( + (hook: any) => hook.owner_name === owner && hook.name === repo, + ); if (!hook) { return false; @@ -120,7 +117,7 @@ export async function enableBuilds( return true; } - await travis.hooks(hook.id).put({ hook: { id: hook.id, active: true }}); + await travis.hooks(hook.id).put({ hook: { id: hook.id, active: true } }); return true; } diff --git a/package-lock.json b/package-lock.json index bc461d0..03b22c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,27 @@ { "name": "@imqueue/cli", - "version": "2.0.2", + "version": "3.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@imqueue/cli", - "version": "2.0.2", - "hasInstallScript": true, + "version": "3.0.0", "license": "GPL-3.0-only", "dependencies": { - "@imqueue/core": "^2.0.11", - "@imqueue/rpc": "^2.0.14", + "@imqueue/core": "^3.2.1", + "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", - "@octokit/rest": "^16.42.2", + "@octokit/rest": "^22.0.1", "chalk": "^5.4.1", "command-exists": "^1.2.9", "dotenv": "^17.0.0", - "inquirer": "^8.2.0", + "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "node-rsa": "^1.1.1", - "request": "^2.88.2", "semver": "^7.7.2", "word-wrap": "^1.2.5", - "yargs": "^17.2.1" + "yargs": "^17.7.2" }, "bin": { "imq": "index.js", @@ -32,1249 +30,1365 @@ "imqup": "bin/updep.sh" }, "devDependencies": { - "@types/chai": "^5.2.2", - "@types/inquirer": "^9.0.8", - "@types/inquirer-autocomplete-prompt": "^3.0.3", - "@types/mocha": "^10.0.10", - "@types/mock-require": "^3.0.0", - "@types/node": "^24.0.8", + "@types/command-exists": "^1.2.3", + "@types/inquirer": "^8.2.12", + "@types/inquirer-autocomplete-prompt": "^1.3.5", + "@types/node": "^24.9.1", "@types/node-rsa": "^1.1.4", - "@types/request": "^2.48.12", "@types/semver": "^7.7.0", - "@types/sinon": "^17.0.4", "@types/yargs": "^17.0.33", - "chai": "^5.2.0", - "codeclimate-test-reporter": "^0.5.1", - "coveralls": "^3.1.1", - "minimist": "^1.2.8", - "mocha": "^11.7.1", - "mocha-lcov-reporter": "^1.3.0", - "mock-require": "^3.0.3", - "nyc": "^17.1.0", - "open": "^10.1.2", - "reflect-metadata": "^0.2.2", - "sinon": "^21.0.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.2", - "typedoc": "^0.28.7", - "typescript": "^5.8.3" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "oxfmt": "0.57.0", + "oxlint": "1.72.0", + "typescript": "^7.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=22.12.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", + "node_modules/@imqueue/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@imqueue/core/-/core-3.2.1.tgz", + "integrity": "sha512-iMRsXsHg9wS/vNKVw/2hVHdPfvzE6R8e5aAnE0n5bJyo7LP7MOgPGgb7rDpSbqVZwZoc7vJGeaW8MuBbDTJakQ==", + "license": "GPL-3.0-only", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "ioredis": "^5.11.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=22.12.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", - "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", - "dev": true, - "license": "MIT", + "node_modules/@imqueue/rpc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@imqueue/rpc/-/rpc-3.2.1.tgz", + "integrity": "sha512-K88g+ehGLym2ltTRvs+OJp9L2LqVKokbciS3vARuAN95KvzzEDNuFqmwiXGH06HBEwZgUHF32PKL5B3fSfheBA==", + "license": "GPL-3.0-only", + "dependencies": { + "@imqueue/core": "^3.2.1", + "acorn": "^8.17.0", + "typescript": "^7.0.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=22.12.0" } }, - "node_modules/@babel/core": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", - "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", - "dev": true, + "node_modules/@imqueue/travis": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@imqueue/travis/-/travis-1.3.0.tgz", + "integrity": "sha512-bMh2a1HPtIjpXf5Ji8H3SduGpkR5fJMcg3sLyHIXYLdgyFA07sbWSMk11IbWvAmFHrFANrxnClqOvCu2cV0j+w==", + "license": "ISC", + "dependencies": { + "@types/request": "^2.48.12", + "request": "^2.88.2" + }, + "bin": { + "travis": "bin/travis-cli.js" + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.27.7", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.7", - "@babel/types": "^7.27.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, + "node_modules/@ioredis/commands": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", + "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", "license": "MIT" }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "engines": { + "node": ">= 20" } }, - "node_modules/@babel/generator": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", - "dev": true, + "node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, + "node_modules/@octokit/endpoint": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", + "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">= 20" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, + "node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dev": true, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@octokit/types": "^16.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@octokit/core": ">=6" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, + "node_modules/@octokit/request": { + "version": "10.0.11", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.11.tgz", + "integrity": "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==", "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.3", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "content-type": "^2.0.0", + "json-with-bigint": "^3.5.3", + "universal-user-agent": "^7.0.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" } }, - "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dev": true, + "node_modules/@octokit/request-error": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", + "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@octokit/types": "^16.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 20" } }, - "node_modules/@babel/parser": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", - "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", - "dev": true, + "node_modules/@octokit/rest": { + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.1.tgz", + "integrity": "sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.7" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 20" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, + "node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@octokit/openapi-types": "^27.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", - "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", + "node_modules/@oxfmt/binding-android-arm-eabi": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.57.0.tgz", + "integrity": "sha512-qVBsEO+KugOsCmUHcO8iqNnqc65p7PCKpCs8M66mPZ+Ri+CWbcpoQOEJBg2OTu03+0qu++NK1jj6IzvQVs0Sig==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/parser": "^7.27.7", - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.7", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@babel/types": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", - "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "node_modules/@oxfmt/binding-android-arm64": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.57.0.tgz", + "integrity": "sha512-mp6PibWbao3aizijcheOeHQaYEhcUAt8pwLniYbtLfHxL/psFF0BykAwCj+s3c6qIpa8yN8keZICWrqtZ70w8g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@oxfmt/binding-darwin-arm64": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.57.0.tgz", + "integrity": "sha512-T+0stuCBqmUVY+aMIvrgXhzGhHO3sD5tNiiEcYqgSdPsnukskQqn2u5qOVD0sv1l7RLdFS5Z/f5Wi9Ktyjr3Eg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@oxfmt/binding-darwin-x64": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.57.0.tgz", + "integrity": "sha512-O+3JbqWs/mCI2oi4xfhRO2IVPFJNDDEBV8Odo+ZpmsUOeKJfjXoNH7nDmBEQcDgK7NfjDIyE7kRgYSZcTLDO0A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@gerrit0/mini-shiki": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.7.0.tgz", - "integrity": "sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==", + "node_modules/@oxfmt/binding-freebsd-x64": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.57.0.tgz", + "integrity": "sha512-pxwhxVC+JkLX9twOQ/8C/vbuOQcMZyKIDmiRDZfO7yITuVcIdZCiLRqqf4QOxb2+8FWrRXzQpm+1DBKcMpHSSQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@shikijs/engine-oniguruma": "^3.7.0", - "@shikijs/langs": "^3.7.0", - "@shikijs/themes": "^3.7.0", - "@shikijs/types": "^3.7.0", - "@shikijs/vscode-textmate": "^10.0.2" - } - }, - "node_modules/@imqueue/core": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@imqueue/core/-/core-2.0.11.tgz", - "integrity": "sha512-Uu7+2dhIiKX7CyuPWq4YJmZRhl5GtLHwWckEkIFXgNzyKGvUn9dbiTPUZhSIJQZmIuKrCneBI+fehEmb9n8Oaw==", - "license": "GPL-3.0-only", - "dependencies": { - "ioredis": "^5.7.0" - } - }, - "node_modules/@imqueue/rpc": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@imqueue/rpc/-/rpc-2.0.14.tgz", - "integrity": "sha512-x4GK7l61KydNN9kCmTApCV/Rbc3w4T8prqqEX1dkjjjtcnmbxOu+hwO2gomdp7xPvT1YrLJboLqkn/9MufMU3Q==", - "license": "GPL-3.0-only", - "dependencies": { - "@imqueue/core": "^2.0.11", - "@types/node": "^24.3.0", - "acorn": "^8.15.0", - "farmhash": "^4.0.2", - "node-machine-id": "^1.1.12", - "reflect-metadata": "^0.2.2", - "typescript": "^5.9.2" - } - }, - "node_modules/@imqueue/rpc/node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14.17" - } - }, - "node_modules/@imqueue/travis": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@imqueue/travis/-/travis-1.3.0.tgz", - "integrity": "sha512-bMh2a1HPtIjpXf5Ji8H3SduGpkR5fJMcg3sLyHIXYLdgyFA07sbWSMk11IbWvAmFHrFANrxnClqOvCu2cV0j+w==", - "dependencies": { - "@types/request": "^2.48.12", - "request": "^2.88.2" - }, - "bin": { - "travis": "bin/travis-cli.js" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@ioredis/commands": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.1.tgz", - "integrity": "sha512-bYtU8avhGIcje3IhvF9aSjsa5URMZBHnwKtOvXsT4sfYy9gppW11gLPT/9oNqlJZD47yPKveQFTAFWpHjKvUoQ==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.57.0.tgz", + "integrity": "sha512-pxBU4zH2imB/MDBfth2rOMeVxXUMjRQLCazagwLARIFH3hVlxZJBlM4nSnHXaIHJK4/qezoFCIORN6AY8Mra4A==", + "cpu": [ + "arm" + ], "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/@oxfmt/binding-linux-arm-musleabihf": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.57.0.tgz", + "integrity": "sha512-JAprOzt8tycYou36ZgEw14DlRHTiN8qdtKANdV3VZIRIvTI/lh/cX13c9pJ/EnDk2GT3FASH7KvCgQ2AufAifQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@oxfmt/binding-linux-arm64-gnu": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.57.0.tgz", + "integrity": "sha512-ajtjaxSaj9xl4BW7REt+Cef/ttzbAq00Bq4z7JUDZEfgFXdwSjH8K9bF+IcIJzZB9lKqMfQ4eHuSFOvvlvtqOg==", + "cpu": [ + "arm64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/@oxfmt/binding-linux-arm64-musl": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.57.0.tgz", + "integrity": "sha512-p4Y/+RYk9Bk5WO+zHSUXAClRmZ2fbJCejMuCAsU2HhyME4jqf6Ftt/mJYEwIah1wGCBDYOB7wEGV1x5bCEZ6hA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@oxfmt/binding-linux-ppc64-gnu": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.57.0.tgz", + "integrity": "sha512-By6tRALAZsno0F4zedmtG+wdMvJiJmJoXM4d3+A9zHE4HRXLqXITwRH8mgrlcXc5yJM2g2W3riRPwTYdgemZLQ==", + "cpu": [ + "ppc64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui/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==", + "node_modules/@oxfmt/binding-linux-riscv64-gnu": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.57.0.tgz", + "integrity": "sha512-skYeG+RgvyzspqVEBsEprL90OYYZfoVNqB3HcCNR6QDJyXKOzfDRT3zncnHmUaFluIlBHuY23mU1b5WGgR98hA==", + "cpu": [ + "riscv64" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@oxfmt/binding-linux-riscv64-musl": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.57.0.tgz", + "integrity": "sha512-FFgACrZOXAXUh5KQh2mt1CDOVOZmn+QzHP71wM9QobNwyQvoFfyAeefVUltW83g3sm7LTiH3yfFqLLVUpA5ZFQ==", + "cpu": [ + "riscv64" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@oxfmt/binding-linux-s390x-gnu": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.57.0.tgz", + "integrity": "sha512-Nm/BAOfQeFiiKd502mZn/GAVKJwtd0RdCg17G3Wz/WSOIQmDi3+7/SZH4BHn1Ye5KvTVH3ua8WvfwLLycNIuvA==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@oxfmt/binding-linux-x64-gnu": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.57.0.tgz", + "integrity": "sha512-BiSy5Ku3mQqyxS6YIqAJgd403wEUWvI7kerfzPxc2l/txZVmZM0pSj7oDM+4bGBExowxOi7o73jEam1W0EDTZg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@oxfmt/binding-linux-x64-musl": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.57.0.tgz", + "integrity": "sha512-BCRkJiotz5s9afLYD2LuMvzAoDYx9H17E/YbDyu4xK7l4zHDPeny9ErSXL//i/nJyaOwRk08x4b8cgJC00+JDg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@oxfmt/binding-openharmony-arm64": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.57.0.tgz", + "integrity": "sha512-4Oaxe1qrGgXfpCJ1C/ERJ2iCtV2rN1R79ga9fsfyVHfSQRu/hVW780u2KDqZWFZ/iGTHODJji0JemxqFZ63eIQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@oxfmt/binding-win32-arm64-msvc": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.57.0.tgz", + "integrity": "sha512-MYLAsDnhdNsSGheLYhWgbk0vfIrlS84iQYun/y21fX6u0jj8iBtYtbpZMdiqYeuf8U12eVPUjVY2xE2NrCfJ0g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@oxfmt/binding-win32-ia32-msvc": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.57.0.tgz", + "integrity": "sha512-PBwdzZALJY/jcCx2E6is0yu+cuVXeySTDmwuseD+9j0mHqlRNxwlKgsyRTBed/woPeqfVfuXfWjoq4Cx2Zt3Eg==", + "cpu": [ + "ia32" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.11.tgz", - "integrity": "sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==", + "node_modules/@oxfmt/binding-win32-x64-msvc": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.57.0.tgz", + "integrity": "sha512-bQJdH9i4RRfw55jm7+8/xS7GzHLLTbHx4huhrrDxQJaJtbSDbsyOnODvP1ftT7EG0KFKAYO2S+q6AcioXODx8w==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.72.0.tgz", + "integrity": "sha512-zhCmvn+1Mj3UchAc/90i99S0t7jJUsHmFVSPg4UWrjO8b8eaSGwscgO6QAUtvHBstkjQwBttQNswEnAF1mIQdA==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.0.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.3.tgz", - "integrity": "sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.28", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.28.tgz", - "integrity": "sha512-KNNHHwW3EIp4EDYOvYFGyIFfx36R2dNJYH4knnZlF8T5jdbD5Wx8xmSaQ2gP9URkJ04LGEtlcCtwArKcmFcwKw==", + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.72.0.tgz", + "integrity": "sha512-mtH+aY/ozv1eZoCUC2owjFAtyNBKHpJHygKeEu9zXXnQGW1Q2/qOpvx+I+Lf23+TvTz66F4iiXUbl2cGvoLPCQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.72.0.tgz", + "integrity": "sha512-EvnajNPDtfknB3ZieeOOyDTwJn9QXDiwfnF4ZDQqART6RG6hjY4WigQcZdGoK2dkB3e1vrmEzN9aYbQCUkh/gQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz", - "integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==", + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.72.0.tgz", + "integrity": "sha512-ZkCdEa/G80A7vEHfeCDz/+L3m33DE73v32mDKhgOIgz8Uwf0DFcK7+uu6qC+7LEhmz5fpOe1osWKyjSNMydFIQ==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/auth-token": "^6.0.0", - "@octokit/graphql": "^9.0.1", - "@octokit/request": "^10.0.2", - "@octokit/request-error": "^7.0.0", - "@octokit/types": "^14.0.0", - "before-after-hook": "^4.0.0", - "universal-user-agent": "^7.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/auth-token": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", - "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.72.0.tgz", + "integrity": "sha512-NroXv2vh+sxVY1uya/rM5pjhx1hm8BzlYpx9q67QP0Xhw5MH2bf5GJylpvLEC+781p1Xli/317EoV9AlGwViag==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "peer": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/endpoint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", - "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.72.0.tgz", + "integrity": "sha512-0NDywYgfj279Ou/BcQuCYSj7NJwBfmWn5qc5uGO/Ny7fUWmXyIpvawqX/8acQlWG6IXelJsJhj+JAy6sjsKj0A==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", - "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", - "license": "MIT", - "peer": true - }, - "node_modules/@octokit/core/node_modules/@octokit/request": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", - "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.72.0.tgz", + "integrity": "sha512-4vpXB06h65Ezsy4hRyrGjGrfa1SkVPii09yaajiYhmVpgsFiLD+KNxIx/BNAY+XiO+i1yqp9HHdwqM8VTqa5XQ==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/endpoint": "^11.0.0", - "@octokit/request-error": "^7.0.0", - "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^3.0.0", - "universal-user-agent": "^7.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/request-error": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", - "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.72.0.tgz", + "integrity": "sha512-immaN4g2ZGFiOkKrvRX9LvzZdd2GkQM5wR+UyzYyUuyhUTXGQ4HKUJH18xp4G8OfhCVaVAJfKZxwE1r8+4hhaQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/types": "^14.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", - "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.72.0.tgz", + "integrity": "sha512-JGHS9Mnr7iWyyLDxgCv1MhzVpAckgptg00F2gnxt/GD7lQ2SW1BRcxHqhSTaSdDpjWRrBkBxMMh4+Hn3aVtExg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/openapi-types": "^25.1.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/core/node_modules/before-after-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", - "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", - "license": "Apache-2.0", - "peer": true - }, - "node_modules/@octokit/core/node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "license": "ISC", - "peer": true - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.72.0.tgz", + "integrity": "sha512-AOYgBZqxNshrg83P9v0RYv+m8s10Cqkj4/PxXFDhcS3k7FqsIG5+CxErshZCIN7G8iy4Y+VGfAsuEdar8AcbBg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/endpoint/node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "license": "ISC" - }, - "node_modules/@octokit/graphql": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", - "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.72.0.tgz", + "integrity": "sha512-QMybPS5ij3/vrKG67mqzHwW++91sYxK/PPUVi6SBtNCEzW4niS52fVBdXbQ6nou0wWbUPEpx8Sl/ZjtgE3clXA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/request": "^10.0.2", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", - "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.72.0.tgz", + "integrity": "sha512-gOc3W7JV0PXRpIL7stUlLe3Wa9Gp0Kdlup87IT3gHDvPKck2xNgMIl/Gs2lldYY2lyXZDC4rWi3hmoLUobkgbQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", - "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", - "license": "MIT", - "peer": true - }, - "node_modules/@octokit/graphql/node_modules/@octokit/request": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", - "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.72.0.tgz", + "integrity": "sha512-rpGxph+FjjHcYI5q6uxB3Az+tnfmEnDbSA8+PK9ZE/VzyUAkvBOMeuY7ZQMhu5mpZH7YQDsTdW6Cx4kV/msc6w==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/endpoint": "^11.0.0", - "@octokit/request-error": "^7.0.0", - "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^3.0.0", - "universal-user-agent": "^7.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", - "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.72.0.tgz", + "integrity": "sha512-WND+uhf/Ko13SLqQMWQUgsZuLvYYEvL0ZKgg0tgGYfLqxG7l8Ju123fHDMJyYSDl5E3bUbpFUuii/OvMreFQzw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/types": "^14.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", - "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.72.0.tgz", + "integrity": "sha512-SrpbrUL70nG9vh6zP4/oKHWgLuHquwsr7MW9XOn0olBVgh10Uqr8qscKhQoBGEn6olK/IUpn5GSKcdQ5AjUhGA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@octokit/openapi-types": "^25.1.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/graphql/node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "license": "ISC", - "peer": true - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", - "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.72.0.tgz", + "integrity": "sha512-qkrsEn6NmgFKr7U/QnezQMb+q/vzAy0Dd9Y95gQGQTyjzDLN+HRZMuM5u70iyH4nBLCfKBzhjMsYCehKay2jyg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^2.0.1" + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.72.0.tgz", + "integrity": "sha512-LWR6ZlFZph+KPjXv8opgZsXRDCdrdQe8VL8Cg9zxCoBS73h6znzZpydVgmdnwj8mB9AuSM5jxEgDJDpQkjboeg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": ">= 8" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.72.0.tgz", + "integrity": "sha512-yt6HEh7IsHvtjRWtmeZRX134eaXKHq5Gnqlf1xBJdJl1JtdoRUEJw3nAxpZoUDS860cX/foKbztO441anVBtVQ==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "peerDependencies": { - "@octokit/core": ">=3" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", - "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.72.0.tgz", + "integrity": "sha512-b2eKFD2hX7tIwmo/cyH6TDq8vzWRZ2qNHrzoGntUTmq0h3zQh/uX3eTSHCwI8OB/ADQfJCRelLItK8BsxuucDA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^2.0.1", - "deprecation": "^2.3.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "license": "MIT", - "dependencies": { - "@types/node": ">= 8" - } + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT" }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } + "node_modules/@types/command-exists": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.3.tgz", + "integrity": "sha512-PpbaE2XWLaWYboXD6k70TcXO/OdOyyRFq5TVpmlUELNxdkkmXU9fkImNosmXU1DtsNrqdUgWd/nJQYXgwmtdXQ==", + "dev": true, + "license": "MIT" }, - "node_modules/@octokit/request-error": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", - "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", + "node_modules/@types/inquirer": { + "version": "8.2.13", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.13.tgz", + "integrity": "sha512-shSvl3mn4Z8AK627kA1vx8PYkyH6CdIjV5NYYj7a0xIxzmG3ZgzEpzCi3CWfktjAlq+0Z0wHJGtWNiACaYpeOg==", + "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^2.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@types/through": "*", + "rxjs": "^7.2.0" } }, - "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "node_modules/@types/inquirer-autocomplete-prompt": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.3.5.tgz", + "integrity": "sha512-xsydZ63gZt/2vqlqdSJQgxhbZd2NpRO6TawrDu1/IR6VbL3HfS709y6Yu7LwrkCcy4Lr05PeBInPizErcXSokw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node": ">= 8" + "@types/inquirer": "^8" } }, - "node_modules/@octokit/request/node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "undici-types": "~7.18.0" } }, - "node_modules/@octokit/request/node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", - "license": "ISC" - }, - "node_modules/@octokit/rest": { - "version": "16.43.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", - "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", + "node_modules/@types/node-rsa": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/node-rsa/-/node-rsa-1.1.4.tgz", + "integrity": "sha512-dB0ECel6JpMnq5ULvpUTunx3yNm8e/dIkv8Zu9p2c8me70xIRUUG3q+qXRwcSf9rN3oqamv4116iHy90dJGRpA==", + "dev": true, "license": "MIT", "dependencies": { - "@octokit/auth-token": "^2.4.0", - "@octokit/plugin-paginate-rest": "^1.1.1", - "@octokit/plugin-request-log": "^1.0.0", - "@octokit/plugin-rest-endpoint-methods": "2.4.0", - "@octokit/request": "^5.2.0", - "@octokit/request-error": "^1.0.2", - "atob-lite": "^2.0.0", - "before-after-hook": "^2.0.0", - "btoa-lite": "^1.0.0", - "deprecation": "^2.0.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lodash.uniq": "^4.5.0", - "octokit-pagination-methods": "^1.1.0", - "once": "^1.4.0", - "universal-user-agent": "^4.0.0" + "@types/node": "*" } }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^12.11.0" + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.5" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } + "license": "MIT" }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz", - "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==", + "node_modules/@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.7.0", - "@shikijs/vscode-textmate": "^10.0.2" + "@types/node": "*" } }, - "node_modules/@shikijs/langs": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz", - "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==", + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.7.0" + "@types/yargs-parser": "*" } }, - "node_modules/@shikijs/themes": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz", - "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.7.0" - } - }, - "node_modules/@shikijs/types": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz", - "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true, "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=4" + "node": ">=16.20.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" - }, - "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*" + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/inquirer": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.8.tgz", - "integrity": "sha512-CgPD5kFGWsb8HJ5K7rfWlifao87m4ph8uioU7OTncJevmE/VLIqAAjfQtko578JZg7/f69K4FgqYym3gNr7DeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/through": "*", - "rxjs": "^7.2.0" + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/inquirer-autocomplete-prompt": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-3.0.3.tgz", - "integrity": "sha512-OQCW09mEECgvhcppbQRgZSmWskWv58l+WwyUvWB1oxTu3CZj8keYSDZR9U8owUzJ5Zeux5kacN9iVPJLXcoLXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/inquirer": "*" + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", - "dev": true, - "license": "MIT" + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/mock-require": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/mock-require/-/mock-require-3.0.0.tgz", - "integrity": "sha512-TZ/s3ufaF+kEFPx9PqXKNd7OsPJoVsgOd59EA8XQLTRjJCsOdx5sEAOGhyrZ3Os78iaDKyGJWdQWyYWRg1Iyvg==", - "dev": true, - "license": "MIT" + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.10.0" + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/node-rsa": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/node-rsa/-/node-rsa-1.1.4.tgz", - "integrity": "sha512-dB0ECel6JpMnq5ULvpUTunx3yNm8e/dIkv8Zu9p2c8me70xIRUUG3q+qXRwcSf9rN3oqamv4116iHy90dJGRpA==", - "dev": true, - "dependencies": { - "@types/node": "*" + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true, - "license": "MIT" + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/sinon": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", - "integrity": "sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/through": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", - "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", - "dev": true, - "dependencies": { - "@types/node": "*" + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==" - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1283,32 +1397,11 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1324,6 +1417,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -1338,6 +1432,7 @@ "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" } @@ -1346,6 +1441,7 @@ "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" }, @@ -1356,43 +1452,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } @@ -1401,55 +1465,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.8" } }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1468,87 +1508,35 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", "license": "Apache-2.0" }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, - "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/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", - "license": "MIT" - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1567,104 +1555,35 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" }, "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" @@ -1674,55 +1593,16 @@ } }, "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, - "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", + "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", + "license": "MIT" }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -1731,9 +1611,10 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", "engines": { "node": ">=6" }, @@ -1745,6 +1626,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "license": "ISC", "engines": { "node": ">= 10" } @@ -1753,6 +1635,7 @@ "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", @@ -1762,46 +1645,46 @@ "node": ">=12" } }, + "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==", + "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/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } }, - "node_modules/codeclimate-test-reporter": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/codeclimate-test-reporter/-/codeclimate-test-reporter-0.5.1.tgz", - "integrity": "sha512-XCzmc8dH+R4orK11BCg5pBbXc35abxq9sept4YvUFRkFl9zb9MIVRrCKENe6U1TKAMTgvGJmrYyHn0y2lerpmg==", - "deprecated": "codeclimate-test-reporter has been deprecated in favor of our new unified test-reporter. Please visit https://docs.codeclimate.com/docs/configuring-test-coverage for details on setting up the new test-reporter.", - "dev": true, - "dependencies": { - "async": "~1.5.2", - "commander": "2.9.0", - "lcov-parse": "0.0.10", - "request": "~2.88.0" - }, - "bin": { - "codeclimate-test-reporter": "bin/codeclimate.js" - }, - "engines": { - "node": ">= 4" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1812,12 +1695,14 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1828,92 +1713,33 @@ "node_modules/command-exists": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "node_modules/commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", - "dev": true, - "dependencies": { - "graceful-readlink": ">= 1.0.0" - }, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", "license": "MIT" }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/coveralls/node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", - "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, + "node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "license": "MIT" + }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" }, @@ -1922,9 +1748,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1938,98 +1764,11 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -2037,22 +1776,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -2066,35 +1794,10 @@ "node": ">=0.10" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "license": "ISC" - }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dotenv": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.0.0.tgz", - "integrity": "sha512-A0BJ5lrpJVSfnMMXjmeO0xUnoxqsBHWCoqqTnGwGYVdnctqXXUEhJOO7LxmgxJon9tEZFGpe0xPRX0h2v3AANQ==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -2103,212 +1806,104 @@ "url": "https://dotenvx.com" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.178", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.178.tgz", - "integrity": "sha512-wObbz/ar3Bc6e4X5vf0iO8xTN8YAjN/tgiAOJLr7yjYFtP9wAjq8Mb5h0yn6kResir+VYx2DXBj9NNobs0ETSA==", - "dev": true, - "license": "ISC" - }, "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==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" + "node": ">= 0.4" } }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" + "node": ">=0.8.0" } }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, "node_modules/extsprintf": { "version": "1.3.0", @@ -2316,53 +1911,26 @@ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" - ] - }, - "node_modules/farmhash": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/farmhash/-/farmhash-4.0.2.tgz", - "integrity": "sha512-i6FbQ0ZUPV6yhFSRI2SQBEqJzoWDiN4cnulTT2jm0f0lUIXg8/iPebACCrOY80rggd9LaSU65GFOI/xnJBdzyA==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "node-addon-api": "^8.4.0", - "prebuild-install": "^7.1.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/fast-content-type-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", - "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -2373,233 +1941,113 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.6.tgz", + "integrity": "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" } }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "engines": { - "node": ">=6.9.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", - "dev": true - }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "license": "ISC", "engines": { "node": ">=4" } @@ -2609,6 +2057,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", + "license": "MIT", "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -2621,54 +2070,55 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -2680,14 +2130,19 @@ } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ieee754": { @@ -2707,57 +2162,26 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } + ], + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "version": "8.2.7", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz", + "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==", + "license": "MIT", "dependencies": { + "@inquirer/external-editor": "^1.0.0", "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", - "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.21", "mute-stream": "0.0.8", @@ -2767,7 +2191,7 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "wrap-ansi": "^6.0.1" }, "engines": { "node": ">=12.0.0" @@ -2777,6 +2201,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.4.0.tgz", "integrity": "sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==", + "license": "ISC", "dependencies": { "ansi-escapes": "^4.3.1", "chalk": "^4.0.0", @@ -2811,6 +2236,7 @@ "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^1.9.0" }, @@ -2821,7 +2247,8 @@ "node_modules/inquirer-autocomplete-prompt/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/inquirer/node_modules/chalk": { "version": "4.1.2", @@ -2840,20 +2267,18 @@ } }, "node_modules/ioredis": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.7.0.tgz", - "integrity": "sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==", + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", + "integrity": "sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==", "license": "MIT", "dependencies": { - "@ioredis/commands": "^1.3.0", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" + "@ioredis/commands": "1.10.0", + "cluster-key-slot": "1.1.1", + "debug": "4.4.3", + "denque": "2.1.0", + "redis-errors": "1.2.0", + "redis-parser": "3.0.0", + "standard-as-callback": "2.1.0" }, "engines": { "node": ">=12.22.0" @@ -2863,333 +2288,83 @@ "url": "https://opencollective.com/ioredis" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "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/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, "engines": { - "node": ">=16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "license": "MIT" }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } + "node_modules/json-with-bigint": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz", + "integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==", + "license": "MIT" }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "license": "MIT", "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -3200,92 +2375,17 @@ "node": ">=0.6.0" } }, - "node_modules/lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha512-YsL0D4QF/vNlNcHPXM832si9d2ROryFQ4r4JvcfMIiUYr1f6WULuO75YCtxNu4P+XMRHz0SfUc524+c+U3G5kg==", - "dev": true - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "license": "MIT" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "license": "MIT" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", - "license": "MIT" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "license": "MIT" - }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -3313,107 +2413,20 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/loupe": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", - "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/macos-release": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", - "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">= 0.4" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3422,6 +2435,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -3429,590 +2443,55 @@ "node": ">= 0.6" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, - "node_modules/mocha": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", - "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", - "dev": true, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", - "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha-lcov-reporter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz", - "integrity": "sha512-/5zI2tW4lq/ft8MGpYQ1nIH6yePPtIzdGeUEwFMKfMRdLfAQ1QW2c68eEJop32tNdN5srHa/E2TzB+erm3YMYA==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mock-require": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", - "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", - "dev": true, - "dependencies": { - "get-caller-file": "^1.0.2", - "normalize-path": "^2.1.1" - }, - "engines": { - "node": ">=4.3.0" - } - }, - "node_modules/mock-require/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.75.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", - "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz", - "integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==", - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==" - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "license": "ISC" }, "node_modules/node-rsa": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", - "dependencies": { - "asn1": "^0.2.4" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nyc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", - "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^3.3.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^6.0.2", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nyc/node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nyc/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" + "asn1": "^0.2.4" } }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", "engines": { "node": "*" } }, - "node_modules/octokit-pagination-methods": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", - "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", - "license": "MIT" - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/open": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", - "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", - "dev": true, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=18" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4022,6 +2501,7 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -4056,384 +2536,155 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/os-name": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", - "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", - "license": "MIT", - "dependencies": { - "macos-release": "^2.2.0", - "windows-release": "^3.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/oxfmt": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.57.0.tgz", + "integrity": "sha512-ZB7Bi+rGDSqmVIo9jwcLyFgjxXvQhDdU+jx+ZrVy6VRiVXK2+CHc4hO3J4dUQjHe7V0ymHB+MDuv5z+NhK07HA==", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" + "tinypool": "2.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" + "bin": { + "oxfmt": "bin/oxfmt" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" + "url": "https://github.com/sponsors/Boshen" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "optionalDependencies": { + "@oxfmt/binding-android-arm-eabi": "0.57.0", + "@oxfmt/binding-android-arm64": "0.57.0", + "@oxfmt/binding-darwin-arm64": "0.57.0", + "@oxfmt/binding-darwin-x64": "0.57.0", + "@oxfmt/binding-freebsd-x64": "0.57.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.57.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.57.0", + "@oxfmt/binding-linux-arm64-gnu": "0.57.0", + "@oxfmt/binding-linux-arm64-musl": "0.57.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.57.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.57.0", + "@oxfmt/binding-linux-riscv64-musl": "0.57.0", + "@oxfmt/binding-linux-s390x-gnu": "0.57.0", + "@oxfmt/binding-linux-x64-gnu": "0.57.0", + "@oxfmt/binding-linux-x64-musl": "0.57.0", + "@oxfmt/binding-openharmony-arm64": "0.57.0", + "@oxfmt/binding-win32-arm64-msvc": "0.57.0", + "@oxfmt/binding-win32-ia32-msvc": "0.57.0", + "@oxfmt/binding-win32-x64-msvc": "0.57.0" }, - "engines": { - "node": ">=16 || 14 >=14.18" + "peerDependencies": { + "svelte": "^5.0.0", + "vite-plus": "*" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "svelte": { + "optional": true + }, + "vite-plus": { + "optional": true + } } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "node_modules/oxlint": { + "version": "1.72.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.72.0.tgz", + "integrity": "sha512-1rhdZIP/EvoI91ABIwNU5Q8+bWf8mjrS5UzIOZld4d4bXxJvtlUhlQvaoTogIGin/qdErMOrwaIJvCSIAKTLhA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" + "bin": { + "oxlint": "bin/oxlint" }, "engines": { - "node": ">=6" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" + "url": "https://github.com/sponsors/Boshen" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.72.0", + "@oxlint/binding-android-arm64": "1.72.0", + "@oxlint/binding-darwin-arm64": "1.72.0", + "@oxlint/binding-darwin-x64": "1.72.0", + "@oxlint/binding-freebsd-x64": "1.72.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.72.0", + "@oxlint/binding-linux-arm-musleabihf": "1.72.0", + "@oxlint/binding-linux-arm64-gnu": "1.72.0", + "@oxlint/binding-linux-arm64-musl": "1.72.0", + "@oxlint/binding-linux-ppc64-gnu": "1.72.0", + "@oxlint/binding-linux-riscv64-gnu": "1.72.0", + "@oxlint/binding-linux-riscv64-musl": "1.72.0", + "@oxlint/binding-linux-s390x-gnu": "1.72.0", + "@oxlint/binding-linux-x64-gnu": "1.72.0", + "@oxlint/binding-linux-x64-musl": "1.72.0", + "@oxlint/binding-openharmony-arm64": "1.72.0", + "@oxlint/binding-win32-arm64-msvc": "1.72.0", + "@oxlint/binding-win32-ia32-msvc": "1.72.0", + "@oxlint/binding-win32-x64-msvc": "1.72.0" }, - "bin": { - "prebuild-install": "bin.js" + "peerDependencies": { + "oxlint-tsgolint": ">=0.22.1", + "vite-plus": "*" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } } }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT" }, "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/punycode.js": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.6" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">= 6" } }, "node_modules/redis-errors": { @@ -4457,35 +2708,12 @@ "node": ">=4" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "license": "Apache-2.0", "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -4516,6 +2744,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -4525,42 +2754,20 @@ "node": ">= 0.12" } }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -4569,125 +2776,28 @@ "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -4704,110 +2814,35 @@ ], "license": "MIT" }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/sinon": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.0.tgz", - "integrity": "sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", "bin": { - "rimraf": "bin.js" + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=10" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "license": "MIT", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -4832,195 +2867,76 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", - "license": "MIT" - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "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/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "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/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "safe-buffer": "~5.2.0" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "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": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, + "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": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "has-flag": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, + "node_modules/tinypool": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", + "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.6.0" + "node": "^20.0.0 || >=22.0.0" } }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -5029,74 +2945,17 @@ "node": ">=0.8" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -5107,22 +2966,14 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -5130,110 +2981,57 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typedoc": { - "version": "0.28.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.7.tgz", - "integrity": "sha512-lpz0Oxl6aidFkmS90VQDQjk/Qf2iw0IUvFqirdONBdj7jPSN9mGXhy66BcGNDxx5ZMyKKiBVAREvPEzT6Uxipw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@gerrit0/mini-shiki": "^3.7.0", - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "yaml": "^2.8.0" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 18", - "pnpm": ">= 10" - }, - "peerDependencies": { - "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" - } - }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "tsc": "bin/tsc" }, "engines": { - "node": ">=14.17" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "license": "MIT" }, "node_modules/universal-user-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", - "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", - "license": "ISC", - "dependencies": { - "os-name": "^3.1.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -5241,23 +3039,19 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -5265,114 +3059,35 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "node_modules/windows-release": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", - "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", "license": "MIT", "dependencies": { - "execa": "^1.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "defaults": "^1.0.3" } }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/workerpool": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", - "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", - "dev": true, - "license": "Apache-2.0" - }, "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==", - "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/wrap-ansi-cjs": { - "name": "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, + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -5380,61 +3095,23 @@ "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "node": ">=8" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", - "dev": true, "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, "engines": { - "node": ">= 14.6" + "node": ">=10" } }, "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": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -5456,74 +3133,6 @@ "engines": { "node": ">=12" } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index 31c517e..875a8d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imqueue/cli", - "version": "2.0.2", + "version": "3.0.0", "description": "Command Line Interface for IMQ", "keywords": [ "command-line-tool", @@ -13,20 +13,20 @@ "redis-queue" ], "scripts": { - "prepublishOnly": "./node_modules/.bin/tsc", - "postinstall": "([ -z \"$TRAVIS\" ] && (node index config check || node index config init)) || exit 0", - "test": "./node_modules/.bin/tsc && ./node_modules/.bin/nyc mocha && ./node_modules/.bin/nyc report --reporter=text-lcov && npm run test-coverage", - "test-fast": "./node_modules/.bin/tsc && ./node_modules/.bin/nyc mocha ; /usr/bin/env node -e \"import('open').then(open => open.default('file://`pwd`/coverage/index.html', { wait: false }));\"", - "test-local": "export COVERALLS_REPO_TOKEN=$IMQ_CLI_COVERALLS_TOKEN && npm test ; /usr/bin/env node -e \"import('open').then(open => open.default('https://coveralls.io/github/imqueue/imq-rpc', { wait: false }));\"", - "test-coverage": "cat ./coverage/lcov.info | CODECLIMATE_API_HOST=https://codebeat.co/webhooks/code_coverage CODECLIMATE_REPO_TOKEN=bafe0c12-51c6-4419-b671-cf107b5293e3 ./node_modules/.bin/codeclimate-test-reporter", - "clean-typedefs": "find . -name '*.d.ts' -not -wholename '*node_modules*' -not -wholename '*generator*' -type f -delete", - "clean-maps": "find . -name '*.js.map' -not -wholename '*node_modules*' -not -wholename '*generator*' -type f -delete", - "clean-js": "find . -name '*.js' -not -wholename '*node_modules*' -not -wholename '*generator*' -type f -delete", + "prepare": "npm run build", + "build": "npm run clean-compiled && tsc", + "lint": "oxlint", + "format": "oxfmt \"index.ts\" \"lib/**/*.ts\" \"src/**/*.ts\" \"test/**/*.ts\"", + "format:check": "oxfmt --check \"index.ts\" \"lib/**/*.ts\" \"src/**/*.ts\" \"test/**/*.ts\"", + "test": "npm run build && node --experimental-test-module-mocks --import ./test/mocks/index.js --test --test-timeout=30000 $(find test -name '*.spec.js')", + "test-coverage": "npm run build && node --experimental-test-module-mocks --enable-source-maps --import ./test/mocks/index.js --test --experimental-test-coverage --test-timeout=30000 $(find test -name '*.spec.js')", + "test-lcov": "npm run build && mkdir -p coverage && node --experimental-test-module-mocks --enable-source-maps --import ./test/mocks/index.js --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage/lcov.info --test-timeout=30000 $(find test -name '*.spec.js'); node scripts/strip-comment-coverage.mjs coverage/lcov.info", + "clean-typedefs": "find . -name '*.d.ts' -not -wholename '*node_modules*' -type f -delete", + "clean-maps": "find . -name '*.js.map' -not -wholename '*node_modules*' -type f -delete", + "clean-js": "find . -name '*.js' -not -wholename '*node_modules*' -not -wholename '*scripts*' -not -wholename '*bin*' -type f -delete", + "clean-compiled": "npm run clean-js && npm run clean-typedefs && npm run clean-maps", "clean-tests": "rm -rf .nyc_output coverage", - "clean-doc": "rm -rf docs", - "clean-benchmark": "rm -rf benchmark-result", - "clean": "npm run clean-tests && npm run clean-typedefs && npm run clean-maps && npm run clean-js && npm run clean-doc && npm run clean-benchmark", - "doc": "rm -rf docs && typedoc --excludePrivate --excludeExternals --hideGenerator --exclude \"**/+(debug|test|node_modules|docs|coverage|benchmark|.nyc_output)/**/*\" --mode file --out ./docs . && /usr/bin/env node -e \"import('open').then(open => open.default('file://`pwd`/docs/index.html', { wait: false }));\"" + "clean": "npm run clean-tests && npm run clean-compiled" }, "repository": { "type": "git", @@ -39,49 +39,32 @@ "author": "imqueue.com (https://imqueue.com)", "license": "GPL-3.0-only", "dependencies": { - "@imqueue/core": "^2.0.11", - "@imqueue/rpc": "^2.0.15", + "@imqueue/core": "^3.2.1", + "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", - "@octokit/rest": "^16.42.2", + "@octokit/rest": "^22.0.1", "chalk": "^5.4.1", "command-exists": "^1.2.9", "dotenv": "^17.0.0", - "inquirer": "^8.2.0", + "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "node-rsa": "^1.1.1", - "request": "^2.88.2", "semver": "^7.7.2", "word-wrap": "^1.2.5", - "yargs": "^17.2.1" + "yargs": "^17.7.2" }, "preferGlobal": true, "devDependencies": { - "@types/chai": "^5.2.2", - "@types/inquirer": "^9.0.8", - "@types/inquirer-autocomplete-prompt": "^3.0.3", - "@types/mocha": "^10.0.10", - "@types/mock-require": "^3.0.0", - "@types/node": "^24.0.8", + "@types/command-exists": "^1.2.3", + "@types/inquirer": "^8.2.12", + "@types/inquirer-autocomplete-prompt": "^1.3.5", + "@types/node": "^24.9.1", "@types/node-rsa": "^1.1.4", - "@types/request": "^2.48.12", "@types/semver": "^7.7.0", - "@types/sinon": "^17.0.4", "@types/yargs": "^17.0.33", - "chai": "^5.2.0", - "codeclimate-test-reporter": "^0.5.1", - "coveralls": "^3.1.1", - "minimist": "^1.2.8", - "mocha": "^11.7.1", - "mocha-lcov-reporter": "^1.3.0", - "mock-require": "^3.0.3", - "nyc": "^17.1.0", - "open": "^10.1.2", - "reflect-metadata": "^0.2.2", - "sinon": "^21.0.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.2", - "typedoc": "^0.28.7", - "typescript": "^5.8.3" + "oxfmt": "0.57.0", + "oxlint": "1.72.0", + "typescript": "^7.0.2" }, "main": "index.js", "bin": { @@ -93,32 +76,16 @@ "typescript": { "definitions": "index.d.ts" }, - "mocha": { - "require": [ - "ts-node/register", - "source-map-support/register" - ], - "recursive": true, - "bail": true, - "full-trace": true + "type": "module", + "types": "index.d.ts", + "exports": { + ".": { + "types": "./index.d.ts", + "default": "./index.js" + }, + "./package.json": "./package.json" }, - "nyc": { - "check-coverage": false, - "extension": [ - ".ts" - ], - "exclude": [ - "**/*.d.ts", - "**/test/**" - ], - "require": [ - "ts-node/register" - ], - "reporter": [ - "html", - "text", - "text-summary", - "lcovonly" - ] + "engines": { + "node": ">=22.12.0" } } diff --git a/scripts/strip-comment-coverage.mjs b/scripts/strip-comment-coverage.mjs new file mode 100644 index 0000000..f81eb3c --- /dev/null +++ b/scripts/strip-comment-coverage.mjs @@ -0,0 +1,472 @@ +/*! + * Coverage post-processor + * + * I'm Queue Software Project + * Copyright (C) 2025 imqueue.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you want to use this code in a closed source (commercial) project, you can + * purchase a proprietary commercial license. Please contact us at + * to get commercial licensing options. + */ + +/** + * Node's built-in coverage (`--experimental-test-coverage --enable-source-maps`) + * reports every non-code line of a `.ts` source as uncovered, because comment + * and blank lines have no source-map mappings and therefore fall outside every + * covered V8 byte-range. That paints the license header and each JSDoc block + * red in the HTML report and pushes per-file line% far below reality. + * + * Node's reporter also emits records that the (strict) genhtml LCOV 2.x tool + * rejects — function entries with `undefined` line numbers or synthetic, + * duplicated names (``, and decorated methods all + * mis-named `has`/`get`), plus `BRDA:undefined,...` branch records. Left in, + * they produce a wall of warnings and a fatal "unexpected category" error. + * + * This script rewrites an lcov file in place: it drops the `DA`/`BRDA` records + * for lines that contain no executable code (comments and blank lines), drops + * all function records and malformed branch records, then recomputes the + * `LF`/`LH`/`BRF`/`BRH` totals. It uses the TypeScript scanner (already a dev + * dependency) to locate comments reliably — comment markers inside strings, + * template literals and regexes are not misdetected. The result renders in + * genhtml with accurate line + branch coverage and no warnings or errors. + */ +import { readFileSync, writeFileSync, existsSync } from 'node:fs'; +// TypeScript 7 (native port) no longer exposes the classic compiler API from +// the package root — the lightweight scanner/AST primitives live under the +// `typescript/unstable/ast` entry point (createSourceFile is gone entirely, so +// import spans are located with the scanner rather than a parsed AST). +import * as ts from 'typescript/unstable/ast'; + +const lcovPath = process.argv[2] || 'coverage/lcov.info'; + +if (!existsSync(lcovPath)) { + console.warn(`strip-comment-coverage: ${lcovPath} not found, skipping`); + process.exit(0); +} + +/** + * Returns the set of 1-based line numbers in the given source that hold no + * executable code — i.e. blank lines and lines whose only content is a comment. + * + * @param {string} text + * @returns {Set} + */ +function nonCodeLines(text) { + const commentChars = new Uint8Array(text.length); + const scanner = ts.createScanner( + ts.ScriptTarget.Latest, + /* skipTrivia */ false, + ts.LanguageVariant.Standard, + ); + + scanner.setText(text); + + let token = scanner.scan(); + + while (token !== ts.SyntaxKind.EndOfFile) { + if ( + token === ts.SyntaxKind.SingleLineCommentTrivia || + token === ts.SyntaxKind.MultiLineCommentTrivia + ) { + const start = scanner.getTokenStart(); + const end = scanner.getTokenEnd(); + + for (let i = start; i < end; i++) { + commentChars[i] = 1; + } + } + + token = scanner.scan(); + } + + const lines = text.split('\n'); + const result = new Set(); + let pos = 0; + + for (let ln = 0; ln < lines.length; ln++) { + const line = lines[ln]; + let hasCode = false; + + for (let i = 0; i < line.length; i++) { + const ch = line[i]; + + if (ch === ' ' || ch === '\t' || ch === '\r') { + continue; + } + + if (!commentChars[pos + i]) { + hasCode = true; + break; + } + } + + if (!hasCode) { + result.add(ln + 1); + } + + pos += line.length + 1; // account for the split '\n' + } + + return result; +} + +/** + * Returns the set of 1-based lines occupied by top-level import statements. + * Imports compile to `require(...)` that runs on module load, so they are + * always executed, yet Node's source-mapped coverage frequently mis-reports + * them as uncovered (the mapping lands outside the covered byte-range). Treating + * them as non-coverable corrects that artifact rather than hiding real logic. + * + * @param {string} text + * @returns {Set} + */ +function importLines(text) { + // TypeScript 7 dropped `createSourceFile`, so top-level import statements are + // located with the scanner: a top-level `import` keyword (depth 0, not the + // dynamic `import(...)` call nor `import.meta`) begins a declaration whose + // span reaches the terminating semicolon — both `import ... from '...'` and + // `import x = require('...')` end that way in this codebase. + const scanner = ts.createScanner( + ts.ScriptTarget.Latest, + /* skipTrivia */ true, + ts.LanguageVariant.Standard, + ); + + scanner.setText(text); + + const lineStarts = ts.computeLineStarts(text); + // 0-based line holding `pos`: largest index with lineStarts[i] <= pos + const lineOf = pos => { + let lo = 0; + let hi = lineStarts.length - 1; + + while (lo < hi) { + const mid = (lo + hi + 1) >> 1; + + if (lineStarts[mid] <= pos) { + lo = mid; + } else { + hi = mid - 1; + } + } + + return lo; + }; + + const K = ts.SyntaxKind; + const result = new Set(); + let depth = 0; + let token = scanner.scan(); + + while (token !== K.EndOfFile) { + if ( + token === K.OpenBraceToken || + token === K.OpenParenToken || + token === K.OpenBracketToken + ) { + depth++; + } else if ( + token === K.CloseBraceToken || + token === K.CloseParenToken || + token === K.CloseBracketToken + ) { + depth--; + } else if (depth === 0 && token === K.ImportKeyword) { + const start = scanner.getTokenStart(); + let next = scanner.scan(); + + // `import(...)` dynamic call or `import.meta` — not a declaration + if (next === K.OpenParenToken || next === K.DotToken) { + token = next; + continue; + } + + // consume to the terminating semicolon at bracket depth 0 + let inner = 0; + let end = scanner.getTokenEnd(); + + while (next !== K.EndOfFile) { + if (next === K.OpenBraceToken || next === K.OpenParenToken) { + inner++; + } else if ( + next === K.CloseBraceToken || + next === K.CloseParenToken + ) { + inner--; + } else if (next === K.SemicolonToken && inner === 0) { + end = scanner.getTokenEnd(); + break; + } + + end = scanner.getTokenEnd(); + next = scanner.scan(); + } + + for (let line = lineOf(start); line <= lineOf(end); line++) { + result.add(line + 1); + } + + token = scanner.scan(); + continue; + } + + token = scanner.scan(); + } + + return result; +} + +const B64 = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +const B64MAP = new Map([...B64].map((c, i) => [c, i])); + +/** + * Decodes one base64 VLQ source-map segment into its integer fields. + * + * @param {string} seg + * @returns {number[]} + */ +function decodeVLQ(seg) { + const out = []; + let shift = 0; + let value = 0; + + for (const ch of seg) { + const digit = B64MAP.get(ch); + + if (digit === undefined) { + break; + } + + value += (digit & 31) << shift; + + if (digit & 32) { + shift += 5; + } else { + out.push(value & 1 ? -(value >> 1) : value >> 1); + value = 0; + shift = 0; + } + } + + return out; +} + +/** + * Returns the set of 1-based source lines that produced generated JavaScript, + * read from the file's `.js.map`. These are exactly the coverable lines — every + * other line (comments, blanks, type-only declarations, interfaces) emits no + * code and can never be executed. Returns null when no source map is present. + * + * @param {string} sourceFile - path of the .ts source (e.g. src/RedisQueue.ts) + * @returns {Set | null} + */ +function emittedLines(sourceFile) { + const mapPath = sourceFile.replace(/\.ts$/, '.js.map'); + + if (!existsSync(mapPath)) { + return null; + } + + let map; + + try { + map = JSON.parse(readFileSync(mapPath, 'utf8')); + } catch { + return null; + } + + if (typeof map.mappings !== 'string') { + return null; + } + + const lines = new Set(); + let srcIndex = 0; + let srcLine = 0; + + for (const group of map.mappings.split(';')) { + for (const seg of group.split(',')) { + if (!seg) { + continue; + } + + const fields = decodeVLQ(seg); + + // [genCol, srcIndex, srcLine, srcCol, nameIndex]; <4 fields = no + // source position for this segment + if (fields.length >= 4) { + srcIndex += fields[1]; + srcLine += fields[2]; + + if (srcIndex === 0) { + lines.add(srcLine + 1); // map lines are 0-based + } + } + } + } + + return lines; +} + +const coverableCache = new Map(); + +/** + * Resolves how to filter a source file's line records: + * - `{ mode: 'keep', set }` — keep only lines in `set` (source-map driven); + * - `{ mode: 'drop', set }` — drop lines in `set` (comment-scanner fallback). + * + * @param {string} sourceFile + * @returns {{ mode: 'keep' | 'drop', set: Set }} + */ +function coverableInfo(sourceFile) { + if (coverableCache.has(sourceFile)) { + return coverableCache.get(sourceFile); + } + + const emitted = sourceFile ? emittedLines(sourceFile) : null; + let info; + + if (emitted && existsSync(sourceFile)) { + // A line is coverable only if it emitted JS (has a source-map mapping) + // AND is not a comment/blank AND is not an import statement. The comment + // check is required because `removeComments: false` keeps license/JSDoc + // comments in the output, so they carry mappings too; the mapping check + // drops type-only lines (interfaces, type aliases) which emit nothing; + // the import check drops the mis-mapped import artifact. + const text = readFileSync(sourceFile, 'utf8'); + const nonCode = nonCodeLines(text); + const imports = importLines(text); + const keep = new Set( + [...emitted].filter( + line => !nonCode.has(line) && !imports.has(line), + ), + ); + info = { mode: 'keep', set: keep }; + } else if (sourceFile && existsSync(sourceFile)) { + const text = readFileSync(sourceFile, 'utf8'); + const skip = nonCodeLines(text); + + for (const line of importLines(text)) { + skip.add(line); + } + + info = { mode: 'drop', set: skip }; + } else { + info = { mode: 'drop', set: new Set() }; + } + + coverableCache.set(sourceFile, info); + + return info; +} + +let strippedLines = 0; + +/** + * Rewrites a single lcov record so that genhtml accepts it without warnings or + * errors. It: + * - drops DA/BRDA entries on non-code (comment/blank) lines; + * - drops all function records (FN/FNDA/FNF/FNH) — Node's source-mapped + * function detection is unreliable here (undefined line numbers, mis-named + * and duplicated entries), which genhtml rejects, so line + branch coverage + * is kept instead; + * - drops malformed branch records such as `BRDA:undefined,...`; + * - recomputes the LF/LH/BRF/BRH totals. + * + * @param {string[]} recordLines - record body, excluding the end_of_record line + * @returns {string} + */ +function processRecord(recordLines) { + const sfLine = recordLines.find(line => line.startsWith('SF:')); + const sourceFile = sfLine ? sfLine.slice(3).trim() : ''; + const info = coverableInfo(sourceFile); + + // true when a source line produces no executable code and must be dropped + const drop = n => (info.mode === 'keep' ? !info.set.has(n) : info.set.has(n)); + + let lf = 0; + let lh = 0; + let brf = 0; + let brh = 0; + + const kept = recordLines.filter(line => { + // drop all function records — unreliable under source maps + if (/^(FN:|FNDA:|FNF:|FNH:)/.test(line)) { + return false; + } + + const da = line.match(/^DA:(\d+),(\d+)/); + + if (da) { + if (drop(+da[1])) { + strippedLines++; + + return false; + } + + lf++; + + if (+da[2] > 0) { + lh++; + } + + return true; + } + + if (line.startsWith('BRDA:')) { + const brda = line.match(/^BRDA:(\d+),\d+,\d+,(\d+|-)$/); + + // drop malformed (e.g. BRDA:undefined,...) or non-code branches + if (!brda || drop(+brda[1])) { + return false; + } + + brf++; + + if (brda[2] !== '-' && +brda[2] > 0) { + brh++; + } + + return true; + } + + // drop the old totals — they are recomputed below + return !/^(LF|LH|BRF|BRH):/.test(line); + }); + + return ( + `${kept.join('\n')}\n` + + `LF:${lf}\nLH:${lh}\nBRF:${brf}\nBRH:${brh}\nend_of_record\n` + ); +} + +const output = []; +let record = []; + +for (const line of readFileSync(lcovPath, 'utf8').split('\n')) { + if (line === 'end_of_record') { + output.push(processRecord(record)); + record = []; + } else if (line !== '') { + record.push(line); + } +} + +writeFileSync(lcovPath, output.join('')); +console.info( + `strip-comment-coverage: removed ${strippedLines} comment/blank line ` + + `entries from ${lcovPath}`, +); diff --git a/src/client.ts b/src/client.ts index 40aa56b..d57d3e4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -21,7 +21,8 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; +import * as generate from './client/generate.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { @@ -30,8 +31,8 @@ export const { command, describe, builder } = { builder(yargs: Argv) { return yargs - .commandDir('client') + .command(generate as any) .demandCommand() .help(); - } + }, }; diff --git a/src/client/generate.ts b/src/client/generate.ts index c68cd37..b1c0c72 100644 --- a/src/client/generate.ts +++ b/src/client/generate.ts @@ -21,13 +21,13 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv, Arguments } from 'yargs'; +import { type Argv, type Arguments } from 'yargs'; import { IMQClient } from '@imqueue/rpc'; import * as fs from 'fs'; import * as p from 'path'; -import inquirer, { QuestionCollection } from 'inquirer'; +import inquirer, { type QuestionCollection } from 'inquirer'; import chalk from 'chalk'; -import { printError } from '../../lib'; +import { printError } from '../../lib/index.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder, promptOverride, handler } = { @@ -39,19 +39,22 @@ export const { command, describe, builder, promptOverride, handler } = { .option('o', { alias: 'overwrite', describe: 'Overwrite existing client without prompt', - boolean: true + boolean: true, }) .describe('path', 'Directory where client file should be placed') .default('path', '.'); }, async promptOverride(filePath: string) { - const write = ((await inquirer.prompt<{ overwrite: boolean }>([{ - type: 'confirm', - name: 'overwrite', - default: false, - message: `File "${filePath}" already exists. Overwrite it?`, - }] as QuestionCollection)) as { overwrite: boolean } + const write = ( + (await inquirer.prompt<{ overwrite: boolean }>([ + { + type: 'confirm', + name: 'overwrite', + default: false, + message: `File "${filePath}" already exists. Overwrite it?`, + }, + ] as QuestionCollection)) as { overwrite: boolean } ).overwrite; if (!write) { @@ -79,12 +82,11 @@ export const { command, describe, builder, promptOverride, handler } = { process.stdout.write( chalk.green('Successfully created. Path: ') + - chalk.cyan(filePath) + '\n', + chalk.cyan(filePath) + + '\n', ); - } - - catch (err) { - printError(err); + } catch (err) { + printError(err as Error); } }, }; diff --git a/src/completions.ts b/src/completions.ts index 8549d4b..0d687c4 100644 --- a/src/completions.ts +++ b/src/completions.ts @@ -21,7 +21,9 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from "yargs"; +import { type Argv } from 'yargs'; +import * as off from './completions/off.js'; +import * as on from './completions/on.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { @@ -30,8 +32,9 @@ export const { command, describe, builder } = { builder(yargs: Argv) { return yargs - .commandDir('completions') + .command(off as any) + .command(on as any) .demandCommand() .help(); - } + }, }; diff --git a/src/completions/off.ts b/src/completions/off.ts index 2c6e368..04eec35 100644 --- a/src/completions/off.ts +++ b/src/completions/off.ts @@ -21,13 +21,13 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; import { existsSync as exists, readFileSync as read, - writeFileSync as write + writeFileSync as write, } from 'fs'; -import { resolve, printError, IS_ZSH } from '../../lib'; +import { resolve, printError, IS_ZSH } from '../../lib/index.js'; import chalk from 'chalk'; let PROGRAM: string = ''; @@ -43,9 +43,12 @@ let RX_REPLACE: RegExp; function printSuccess(rcFilename: string) { process.stdout.write( chalk.green('Completions removed from ') + - chalk.cyan(`${rcFilename}`) + '\n' + - 'To have these changes to take effect, please, run:\n\n' + - ' $ ' + chalk.cyan(`source ${rcFilename}`) + '\n\n' + chalk.cyan(`${rcFilename}`) + + '\n' + + 'To have these changes to take effect, please, run:\n\n' + + ' $ ' + + chalk.cyan(`source ${rcFilename}`) + + '\n\n', ); } @@ -56,8 +59,11 @@ export const { command, describe, builder, handler } = { async builder(yargs: Argv) { PROGRAM = (await yargs.argv).$0; - RX_REPLACE = new RegExp(`###-begin-${PROGRAM}-completions-###` - + '[\\s\\S]*?' + `###-end-${PROGRAM}-completions-###`); + RX_REPLACE = new RegExp( + `###-begin-${PROGRAM}-completions-###` + + '[\\s\\S]*?' + + `###-end-${PROGRAM}-completions-###`, + ); }, handler() { @@ -66,18 +72,17 @@ export const { command, describe, builder, handler } = { const rcFile = resolve(rcFilename); if (exists(rcFile)) { - const rcText = read(rcFile, { encoding: 'utf8' }) - .replace(RX_REPLACE, '') - .trim() + '\n'; + const rcText = + read(rcFile, { encoding: 'utf8' }) + .replace(RX_REPLACE, '') + .trim() + '\n'; write(rcFile, rcText, { encoding: 'utf8' }); } printSuccess(rcFilename); + } catch (err) { + printError(err as Error); } - - catch (err) { - printError(err); - } - } + }, }; diff --git a/src/completions/on.ts b/src/completions/on.ts index 7736a8b..9fd8fdb 100644 --- a/src/completions/on.ts +++ b/src/completions/on.ts @@ -21,13 +21,13 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; import { existsSync as exists, appendFileSync as append, - readFileSync as read + readFileSync as read, } from 'fs'; -import { resolve, touch, printError, IS_ZSH } from '../../lib'; +import { resolve, touch, printError, IS_ZSH } from '../../lib/index.js'; import chalk from 'chalk'; let PROGRAM: string = ''; @@ -43,9 +43,12 @@ let RX_EXISTS: RegExp; function printAdded(rcFilename: string) { process.stdout.write( chalk.green(`Completion script added to `) + - chalk.cyan(rcFilename) + '\n' + - 'To have these changes to take effect, please, run:\n\n' + - ' $ ' + chalk.cyan(`source ${rcFilename}`) + '\n\n' + chalk.cyan(rcFilename) + + '\n' + + 'To have these changes to take effect, please, run:\n\n' + + ' $ ' + + chalk.cyan(`source ${rcFilename}`) + + '\n\n', ); } @@ -57,7 +60,7 @@ function printAdded(rcFilename: string) { * @return {string} */ function getScript(zshScript: string) { - return ` + return ` ###-begin-${PROGRAM}-completions-### ${zshScript} _yargs_completions() { @@ -84,11 +87,12 @@ complete -F _yargs_completions ${PROGRAM} function printExists(rcFilename: string) { process.stdout.write( chalk.yellow.bold( - `Completion script already exists in your ${ - rcFilename}.`) + '\n' + - 'If it does not work, please try one of:\n\n' + - chalk.cyan(' 1. Reload your shell\n') + - chalk.cyan(` 2. Run source ${rcFilename}\n\n`) + `Completion script already exists in your ${rcFilename}.`, + ) + + '\n' + + 'If it does not work, please try one of:\n\n' + + chalk.cyan(' 1. Reload your shell\n') + + chalk.cyan(` 2. Run source ${rcFilename}\n\n`), ); } @@ -112,15 +116,11 @@ export const { command, describe, builder, handler } = { if (!RX_EXISTS.test(rcText)) { (exists(rcFile) ? append : touch)(rcFile, getScript(zScript)); printAdded(rcFilename); - } - - else { + } else { printExists(rcFilename); } + } catch (err) { + printError(err as Error); } - - catch (err) { - printError(err); - } - } + }, }; diff --git a/src/config.ts b/src/config.ts index ea04cb9..c1d3e28 100644 --- a/src/config.ts +++ b/src/config.ts @@ -21,7 +21,11 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; +import * as check from './config/check.js'; +import * as get from './config/get.js'; +import * as init from './config/init.js'; +import * as set from './config/set.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { @@ -30,8 +34,11 @@ export const { command, describe, builder } = { builder(yargs: Argv) { return yargs - .commandDir('config') + .command(check as any) + .command(get as any) + .command(init as any) + .command(set as any) .demandCommand() .help(); - } + }, }; diff --git a/src/config/check.ts b/src/config/check.ts index 06a0a51..b2ada83 100644 --- a/src/config/check.ts +++ b/src/config/check.ts @@ -21,7 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { configEmpty } from '../../lib'; +import { configEmpty } from '../../lib/index.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, handler } = { @@ -30,5 +30,5 @@ export const { command, describe, handler } = { handler() { process.exit(configEmpty() ? 1 : 0); - } + }, }; diff --git a/src/config/get.ts b/src/config/get.ts index 3448e37..8f57b3e 100644 --- a/src/config/get.ts +++ b/src/config/get.ts @@ -21,17 +21,18 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv, Arguments } from 'yargs'; +import { type Argv, type Arguments } from 'yargs'; import chalk from 'chalk'; -import { printError, loadConfig } from '../../lib'; +import { printError, loadConfig } from '../../lib/index.js'; let PROGRAM: string = ''; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'get [option]', - describe: 'Prints value for given option from config. If option is ' + - 'not provided, will list all config options', + describe: + 'Prints value for given option from config. If option is ' + + 'not provided, will list all config options', async builder(yargs: Argv) { PROGRAM = (await yargs.argv).$0; @@ -41,8 +42,9 @@ export const { command, describe, builder, handler } = { alias: 'json', boolean: true, default: false, - describe: 'Prints config in JSON format (only if ' + - 'option is not passed)' + describe: + 'Prints config in JSON format (only if ' + + 'option is not passed)', }) .default('option', '') .describe('option', 'Config option to display value [optional]'); @@ -51,20 +53,22 @@ export const { command, describe, builder, handler } = { handler(argv: Arguments) { try { const config = loadConfig(); - const options = config && Object.keys(config) || []; + const options = (config && Object.keys(config)) || []; if (!options.length) { return process.stdout.write( chalk.bold.yellow( - 'Config is empty. Try to init if first by running:') + - '\n\n $ ' + - chalk.cyan(`${PROGRAM} config init`) + '\n\n' + 'Config is empty. Try to init if first by running:', + ) + + '\n\n $ ' + + chalk.cyan(`${PROGRAM} config init`) + + '\n\n', ); } if ((argv as any).option) { return process.stdout.write( - JSON.stringify(config[(argv as any).option]) + '\n' + JSON.stringify(config[(argv as any).option]) + '\n', ); } @@ -72,20 +76,20 @@ export const { command, describe, builder, handler } = { if ((argv as any).json) { return process.stdout.write( - chalk.cyan(JSON.stringify(config, null, 2)) + '\n' + chalk.cyan(JSON.stringify(config, null, 2)) + '\n', ); } for (let option of options) { process.stdout.write( - chalk.yellow(`${option}`) + ' = ' + - chalk.cyan(JSON.stringify(config[option])) + '\n' + chalk.yellow(`${option}`) + + ' = ' + + chalk.cyan(JSON.stringify(config[option])) + + '\n', ); } + } catch (err) { + printError(err as Error); } - - catch (err) { - printError(err); - } - } + }, }; diff --git a/src/config/init.ts b/src/config/init.ts index 1bf1851..20bc5e3 100644 --- a/src/config/init.ts +++ b/src/config/init.ts @@ -28,67 +28,68 @@ import { saveConfig, configEmpty, printError, - IMQCLIConfig, + type IMQCLIConfig, resolve, wrap, loadTemplates, loadTemplate, licensingOptions, -} from '../../lib'; +} from '../../lib/index.js'; import chalk from 'chalk'; import * as fs from 'fs'; -const inquirer = ( - originalInquirer as unknown as typeof originalInquirer.default -); +const inquirer = originalInquirer as unknown as typeof originalInquirer.default; // we are going to ignore almost all code here because it's very hard to test // command line user interaction // istanbul ignore next -export async function selectTemplate( - type: string -): Promise<{ - [name: string]: string +export async function selectTemplate(type: string): Promise<{ + [name: string]: string; }> { let name = 'custom'; let path = ''; if (type === 'existing') { const defaultTemplates = await loadTemplates(); - let answer = await inquirer.prompt<{ tplName: string }>([{ - type: 'list', - name: 'tplName', - message: 'Select one of existing templates:', - choices: Object.keys(defaultTemplates) - }]); - - return { [answer.tplName] : defaultTemplates[answer.tplName] }; + let answer = await inquirer.prompt<{ tplName: string }>([ + { + type: 'list', + name: 'tplName', + message: 'Select one of existing templates:', + choices: Object.keys(defaultTemplates), + }, + ]); + + return { [answer.tplName]: defaultTemplates[answer.tplName] }; } if (type === 'repo') { - let answer = await inquirer.prompt<{ repoUrl: string }>([{ - type: 'input', - name: 'repoUrl', - message: 'Enter git repository URL:' - }]); + let answer = await inquirer.prompt<{ repoUrl: string }>([ + { + type: 'input', + name: 'repoUrl', + message: 'Enter git repository URL:', + }, + ]); if (!(answer.repoUrl && answer.repoUrl.trim())) { throw new TypeError('Repository URL expected, but was not given!'); } path = await loadTemplate(answer.repoUrl); - } - - else if (type === 'directory') { - let answer = await inquirer.prompt<{ tplDir: string }>([{ - type: 'input', - name: 'tplDir', - message: 'Enter path to directory:' - }]); + } else if (type === 'directory') { + let answer = await inquirer.prompt<{ tplDir: string }>([ + { + type: 'input', + name: 'tplDir', + message: 'Enter path to directory:', + }, + ]); if (!(answer.tplDir && answer.tplDir.trim())) { - throw new TypeError('Template directory path expected, ' + - 'but was not given!'); + throw new TypeError( + 'Template directory path expected, ' + 'but was not given!', + ); } if (!fs.existsSync(resolve(answer.tplDir))) { @@ -103,94 +104,106 @@ export async function selectTemplate( // istanbul ignore next export async function templateOptions(config: IMQCLIConfig) { - let answer: any = await inquirer.prompt<{ useDefault: boolean }>( - [{ + let answer: any = await inquirer.prompt<{ useDefault: boolean }>([ + { type: 'confirm', name: 'useDefault', - message: 'Do you want to use default template for newly created ' + + message: + 'Do you want to use default template for newly created ' + 'services?', - default: true - }] - ); + default: true, + }, + ]); let templates; let tplName = 'default'; if (!answer.useDefault) { - answer = await inquirer.prompt<{ tplType: string }>( - [{ + answer = await inquirer.prompt<{ tplType: string }>([ + { type: 'list', name: 'tplType', message: 'Select required template:', - choices: [{ - name: 'From a list of existing templates', - value: 'existing' - }, { - name: 'From a git repository', - value: 'repo' - }, { - name: 'From file system directory', - value: 'directory' - }] - }] - ); - - templates = await selectTemplate(answer.tplType); - tplName = Object.keys(templates).shift() || ''; - } - - else { + choices: [ + { + name: 'From a list of existing templates', + value: 'existing', + }, + { + name: 'From a git repository', + value: 'repo', + }, + { + name: 'From file system directory', + value: 'directory', + }, + ], + }, + ]); + + templates = await selectTemplate(answer.tplType); + tplName = Object.keys(templates).shift() || ''; + } else { templates = await loadTemplates(); } if (templates[tplName]) { config.template = templates[tplName]; - return console.log(chalk.green( - `New services set to be created from template "${ - tplName}" (${config.template})` - )); - } - - else { + return console.log( + chalk.green( + `New services set to be created from template "${ + tplName + }" (${config.template})`, + ), + ); + } else { throw new Error(`Template ${tplName} does not exists!`); } - } // istanbul ignore next export async function versionSystemOptions( - config: IMQCLIConfig + config: IMQCLIConfig, ): Promise { - let answer: any = await inquirer.prompt<{ autoCreateRepo: boolean }>([{ - type: 'confirm', - name: 'autoCreateRepo', - message: 'Would you like IMQ automatically create git ' + - 'repository for new services when generate?', - default: true, - }]); + let answer: any = await inquirer.prompt<{ autoCreateRepo: boolean }>([ + { + type: 'confirm', + name: 'autoCreateRepo', + message: + 'Would you like IMQ automatically create git ' + + 'repository for new services when generate?', + default: true, + }, + ]); if (!answer.autoCreateRepo) { config.useGit = false; - return ; + return; } config.useGit = true; - console.log(chalk.cyan( - wrap('\nTo publish git repository you need to provide base url ' + - 'where your git repositories published to. It is recommended ' + - 'also to set-up git SSH access on your machine to ' + - 'make publishing process run smoothly.\n\nFor example, if ' + - 'you are using GitHub for your repositories, you need to enter ' + - 'git@github.com:[user_or_org] as base URL and setup SSH ' + - 'access as described at https://help.github.com/articles/' + - 'adding-a-new-ssh-key-to-your-github-account/\n') - )); - - answer = await inquirer.prompt<{ url: string }>([{ - type: 'input', - name: 'url', - message: 'Enter github organization or user name:', - }]); + console.log( + chalk.cyan( + wrap( + '\nTo publish git repository you need to provide base url ' + + 'where your git repositories published to. It is recommended ' + + 'also to set-up git SSH access on your machine to ' + + 'make publishing process run smoothly.\n\nFor example, if ' + + 'you are using GitHub for your repositories, you need to enter ' + + 'git@github.com:[user_or_org] as base URL and setup SSH ' + + 'access as described at https://help.github.com/articles/' + + 'adding-a-new-ssh-key-to-your-github-account/\n', + ), + ), + ); + + answer = await inquirer.prompt<{ url: string }>([ + { + type: 'input', + name: 'url', + message: 'Enter github organization or user name:', + }, + ]); if (!/^[-_a-z0-9]+$/i.test(answer.url)) { console.log(chalk.red('Wrong user or organization name.')); @@ -201,66 +214,85 @@ export async function versionSystemOptions( console.log(chalk.green(`Base git URL is set to "${config.gitBaseUrl}"`)); - answer = await inquirer.prompt<{ saveGitHubToken: boolean }>([{ - type: 'confirm', - name: 'saveGitHubToken', - message: 'Would you like to save GitHub auth token in a local config ' + - 'to prevent imq to ask it any time service is created?', - default: false, - }]); + answer = await inquirer.prompt<{ saveGitHubToken: boolean }>([ + { + type: 'confirm', + name: 'saveGitHubToken', + message: + 'Would you like to save GitHub auth token in a local config ' + + 'to prevent imq to ask it any time service is created?', + default: false, + }, + ]); if (!answer.saveGitHubToken) { - return ; + return; } - console.log(chalk.cyan(wrap( - 'To make GitHub integration work you must provide a valid token ' + - 'which grants permission to create repository for a specified ' + - 'organization or user name.\nUsually you can generate the token ' + - 'on this page: https://github.com/settings/tokens' - ))); + console.log( + chalk.cyan( + wrap( + 'To make GitHub integration work you must provide a valid token ' + + 'which grants permission to create repository for a specified ' + + 'organization or user name.\nUsually you can generate the token ' + + 'on this page: https://github.com/settings/tokens', + ), + ), + ); - answer = await inquirer.prompt<{ gitHubAuthToken: string }>([{ - type: 'input', - name: 'gitHubAuthToken', - message: 'Enter GitHub auth token:', - }]); + answer = await inquirer.prompt<{ gitHubAuthToken: string }>([ + { + type: 'input', + name: 'gitHubAuthToken', + message: 'Enter GitHub auth token:', + }, + ]); if (!answer.gitHubAuthToken.trim()) { - console.log(chalk.red( - 'Given token is empty, you will be prompted to enter it on ' + - 'service create command' - )); + console.log( + chalk.red( + 'Given token is empty, you will be prompted to enter it on ' + + 'service create command', + ), + ); - return ; + return; } config.gitHubAuthToken = answer.gitHubAuthToken.trim(); console.log(chalk.green('GitHub auth token stored in local config file')); - answer = await inquirer.prompt<{ isPrivate: boolean }>([{ - type: 'confirm', - name: 'isPrivate', - message: 'Does created service should a private repository on GitHub?', - default: true, - }]); + answer = await inquirer.prompt<{ isPrivate: boolean }>([ + { + type: 'confirm', + name: 'isPrivate', + message: + 'Does created service should a private repository on GitHub?', + default: true, + }, + ]); config.gitRepoPrivate = answer.isPrivate; - console.log(chalk.green( - `Service on GitHub will be created as ${config.gitRepoPrivate ? - 'private' : 'public'} repository.` - )); + console.log( + chalk.green( + `Service on GitHub will be created as ${ + config.gitRepoPrivate ? 'private' : 'public' + } repository.`, + ), + ); } // istanbul ignore next export async function authorName(config: IMQCLIConfig): Promise { - const answer = await inquirer.prompt<{ author: string }>([{ - type: 'input', - name: 'author', - message: 'Enter author\'s full name (user or organization):' - }]); + const answer = await inquirer.prompt<{ author: string }>([ + { + type: 'input', + name: 'author', + message: "Enter author's full name (user or organization):", + }, + ]); if (!answer.author.trim()) { console.log(chalk.red(`Given name is invalid, please, try again.`)); @@ -269,18 +301,22 @@ export async function authorName(config: IMQCLIConfig): Promise { config.author = answer.author.trim(); - console.log(chalk.green( - `Auto-generated code will be authored by "${config.author}"` - )); + console.log( + chalk.green( + `Auto-generated code will be authored by "${config.author}"`, + ), + ); } // istanbul ignore next export async function authorEmail(config: IMQCLIConfig) { - const answer = await inquirer.prompt<{ email: string }>([{ - type: 'input', - name: 'email', - message: 'Enter user or organization email:' - }]); + const answer = await inquirer.prompt<{ email: string }>([ + { + type: 'input', + name: 'email', + message: 'Enter user or organization email:', + }, + ]); if (!/^[-a-z0-9.]+@[-a-z0-9.]+$/i.test(answer.email.trim())) { console.log(chalk.red(`Given email is invalid, please, try again.`)); @@ -289,9 +325,11 @@ export async function authorEmail(config: IMQCLIConfig) { config.email = answer.email.trim(); - console.log(chalk.green( - `Generated code will be referred to given contact: ${config.email}` - )); + console.log( + chalk.green( + `Generated code will be referred to given contact: ${config.email}`, + ), + ); } // istanbul ignore next @@ -303,80 +341,92 @@ export async function authorOptions(config: IMQCLIConfig) { // istanbul ignore next export async function dockerCredentials(config: IMQCLIConfig): Promise { const answer = await inquirer.prompt<{ - dockerHubUser: string, - dockerHubPassword: string - }>([{ - type: 'input', - name: 'dockerHubUser', - message: 'Docker hub user:' - }, { - type: 'password', - name: 'dockerHubPassword', - message: 'Docker hub password:' - }]); + dockerHubUser: string; + dockerHubPassword: string; + }>([ + { + type: 'input', + name: 'dockerHubUser', + message: 'Docker hub user:', + }, + { + type: 'password', + name: 'dockerHubPassword', + message: 'Docker hub password:', + }, + ]); if (!answer.dockerHubUser.trim()) { - console.log(chalk.red( - 'Given docker hub user name is empty, please try again' - )); + console.log( + chalk.red('Given docker hub user name is empty, please try again'), + ); return dockerCredentials(config); } if (!answer.dockerHubPassword.trim()) { - console.log(chalk.red( - 'Given docker hub password is empty, please try again' - )); + console.log( + chalk.red('Given docker hub password is empty, please try again'), + ); return dockerCredentials(config); } config.dockerHubUser = answer.dockerHubUser.trim(); config.dockerHubPassword = answer.dockerHubPassword.trim(); - console.log(chalk.green( - 'Docker hub credentials saved in a local config file.' - )); + console.log( + chalk.green('Docker hub credentials saved in a local config file.'), + ); } // istanbul ignore next export async function dockerQuestions(config: IMQCLIConfig): Promise { - let answer: any = await inquirer.prompt<{ useDocker: boolean }>([{ - type: 'confirm', - name: 'useDocker', - message: 'Would you like to dockerize created imq services?', - default: true - }]); + let answer: any = await inquirer.prompt<{ useDocker: boolean }>([ + { + type: 'confirm', + name: 'useDocker', + message: 'Would you like to dockerize created imq services?', + default: true, + }, + ]); if (!answer.useDocker) { config.useDocker = false; - return ; + return; } - answer = await inquirer.prompt<{ dockerHubNamespace: string }>([{ - type: 'input', - name: 'dockerHubNamespace', - message: 'Docker hub namespace:' - }]); + answer = await inquirer.prompt<{ dockerHubNamespace: string }>([ + { + type: 'input', + name: 'dockerHubNamespace', + message: 'Docker hub namespace:', + }, + ]); if (!answer.dockerHubNamespace.trim()) { - console.log(chalk.red( - 'Given docker hub namespace is invalid, please, try again...' - )); + console.log( + chalk.red( + 'Given docker hub namespace is invalid, please, try again...', + ), + ); return await dockerQuestions(config); } config.useDocker = true; config.dockerHubNamespace = answer.dockerHubNamespace.trim(); - answer = await inquirer.prompt<{ saveDockerCredentials: boolean }>([{ - type: 'confirm', - name: 'saveDockerCredentials', - message: 'Would you like to store docker credentials locally to ' + - 'allow imq create CI-Docker secrets without prompt?', - default: false - }]); + answer = await inquirer.prompt<{ saveDockerCredentials: boolean }>([ + { + type: 'confirm', + name: 'saveDockerCredentials', + message: + 'Would you like to store docker credentials locally to ' + + 'allow imq create CI-Docker secrets without prompt?', + default: false, + }, + ]); if (!answer.saveDockerCredentials) { - return ; + return; } await dockerCredentials(config); @@ -390,9 +440,11 @@ export async function serviceQuestions(config: IMQCLIConfig) { const { id, name } = await licensingOptions(); config.license = id; - console.log(chalk.green( - `Selected "${name}" to be a license for IMQ generated code and services` - )); + console.log( + chalk.green( + `Selected "${name}" to be a license for IMQ generated code and services`, + ), + ); await versionSystemOptions(config); await dockerQuestions(config); @@ -408,34 +460,43 @@ export const { command, describe, handler } = { if (!configEmpty()) { process.stdout.write( chalk.bold.yellow('Config already initialized, path: ') + - chalk.cyan(CONFIG_PATH) + '\n' + chalk.cyan(CONFIG_PATH) + + '\n', ); - const answer: any = await inquirer.prompt<{ reInit: boolean }>( - [{ + const answer: any = await inquirer.prompt<{ reInit: boolean }>([ + { type: 'confirm', name: 'reInit', message: 'Do you want to re-init?', - default: false - }] - ); + default: false, + }, + ]); if (!answer.reInit) { return; } } - console.log(chalk.cyan(wrap( - 'Let\'s define global config options ' + - 'for IMQ command line runs. These options will be used as ' + - 'default parameters and will help you shorten your ' + - 'commands.\n\n' - ))); - - console.log(chalk.yellow(wrap( - '- You can skip this step by pressing ' + - '[^C].\n- You can proceed to this step later by running:' - ))); + console.log( + chalk.cyan( + wrap( + "Let's define global config options " + + 'for IMQ command line runs. These options will be used as ' + + 'default parameters and will help you shorten your ' + + 'commands.\n\n', + ), + ), + ); + + console.log( + chalk.yellow( + wrap( + '- You can skip this step by pressing ' + + '[^C].\n- You can proceed to this step later by running:', + ), + ), + ); console.log(chalk.magenta('\n $ imq config init\n')); const config = loadConfig(); @@ -444,11 +505,9 @@ export const { command, describe, handler } = { saveConfig(config); console.log(chalk.magenta('IMQ-CLI successfully configured!')); - } - - catch (err) { - printError(err); + } catch (err) { + printError(err as Error); console.error(err); } - } + }, }; diff --git a/src/config/set.ts b/src/config/set.ts index 068d406..f50f349 100644 --- a/src/config/set.ts +++ b/src/config/set.ts @@ -21,14 +21,14 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Arguments } from 'yargs'; +import { type Arguments } from 'yargs'; import chalk from 'chalk'; import { printError, loadConfig, saveConfig, - prepareConfigValue -} from '../../lib'; + prepareConfigValue, +} from '../../lib/index.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, handler } = { @@ -40,20 +40,19 @@ export const { command, describe, handler } = { const config = loadConfig(); config[(argv as any).option] = prepareConfigValue( - (argv as any).value + (argv as any).value, ); saveConfig(config); process.stdout.write( chalk.green('Option ') + - chalk.cyan(`${(argv as any).option}`) + - chalk.green(' is set to ') + - chalk.cyan(`${(argv as any).value}`) + '\n' + chalk.cyan(`${(argv as any).option}`) + + chalk.green(' is set to ') + + chalk.cyan(`${(argv as any).value}`) + + '\n', ); + } catch (err) { + printError(err as Error); } - - catch (err) { - printError(err); - } - } + }, }; diff --git a/src/service.ts b/src/service.ts index 4e573f5..0d84093 100644 --- a/src/service.ts +++ b/src/service.ts @@ -21,7 +21,9 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; +import * as create from './service/create.js'; +import * as update_version from './service/update-version.js'; // noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { @@ -30,8 +32,9 @@ export const { command, describe, builder } = { builder(yargs: Argv) { return yargs - .commandDir('service') + .command(create as any) + .command(update_version as any) .demandCommand() .help(); - } + }, }; diff --git a/src/service/create.ts b/src/service/create.ts index 445d224..aa1d9b5 100644 --- a/src/service/create.ts +++ b/src/service/create.ts @@ -22,14 +22,15 @@ * to get commercial licensing options. */ import * as path from 'path'; -import { Argv } from 'yargs'; +import { type Argv } from 'yargs'; import * as fs from 'fs'; import * as os from 'os'; import chalk from 'chalk'; import * as semver from 'semver'; -import inquirer, { QuestionCollection } from 'inquirer'; +import inquirer, { type QuestionCollection } from 'inquirer'; +import { createRequire } from 'node:module'; import { - IMQCLIConfig, + type IMQCLIConfig, loadConfig, printError, loadTemplate, @@ -51,9 +52,10 @@ import { isGuthubToken, enableBuilds, toTravisTags, -} from '../../lib'; +} from '../../lib/index.js'; import { execSync } from 'child_process'; +const require = createRequire(import.meta.url); const commandExists = require('command-exists').sync; const DEFAULT_SERVICE_VERSION = '1.0.0-0'; @@ -65,7 +67,7 @@ async function ensureTemplate(template: string) { return template; } - if (/^git@/.test(template)) { + if (template.startsWith('git@')) { // template is a git url return await loadTemplate(template); } @@ -86,14 +88,14 @@ function updateLicenseText( author: string, email: string, serviceName: string, - homepage: string + homepage: string, ): string { const values: any = { - 'year': new Date().getFullYear(), - 'fullname': author, - 'email': email, - 'project': serviceName, - 'project_url': homepage + year: new Date().getFullYear(), + fullname: author, + email: email, + project: serviceName, + project_url: homepage, }; for (let varName of Object.keys(values)) { @@ -105,13 +107,13 @@ function updateLicenseText( // istanbul ignore next async function ensureLicense( - path:string, + path: string, license: string, author: string, email: string, homepage: string, - serviceName: string -): Promise<{ text: string, header: string, name: string, tag: string }> { + serviceName: string, +): Promise<{ text: string; header: string; name: string; tag: string }> { let text = ''; let header = ''; let name = ''; @@ -141,14 +143,22 @@ author for any licensing details.\n`; const lic: any = findLicense(license); text = updateLicenseText( lic.body + '\n', - author, email, serviceName, homepage + author, + email, + serviceName, + homepage, ); name = lic.name; tag = lic.spdx_id; - header = updateLicenseText( - lic.header|| '', - author, email, serviceName, homepage - ) || `Copyright (c) ${new Date().getFullYear()} ${author} <${email}> + header = + updateLicenseText( + lic.header || '', + author, + email, + serviceName, + homepage, + ) || + `Copyright (c) ${new Date().getFullYear()} ${author} <${email}> This software is licensed under ${lic.spdx_id} license. Please, refer to LICENSE file in project's root directory for details.`; @@ -156,8 +166,10 @@ Please, refer to LICENSE file in project's root directory for details.`; } try { - fs.unlinkSync(resolve(path, 'LICENSE')) - } catch (err) { /* ignore */ } + fs.unlinkSync(resolve(path, 'LICENSE')); + } catch (err) { + /* ignore */ + } touch(resolve(path, 'LICENSE'), wrap(text)); return { text, header, name, tag }; @@ -179,8 +191,10 @@ function ensureVersion(version: string) { } if (!semver.valid(version)) { - throw new TypeError('Given version is invalid, please, provide ' + - 'valid semver format!'); + throw new TypeError( + 'Given version is invalid, please, provide ' + + 'valid semver format!', + ); } return version; @@ -232,13 +246,16 @@ async function ensureAuthorName(name: string) { name = name.trim(); if (!name) { - const answer: { authorName: string } = - await inquirer.prompt<{ authorName: string }>([{ + const answer: { authorName: string } = await inquirer.prompt<{ + authorName: string; + }>([ + { type: 'input', name: 'authorName', - message: 'Enter author\'s name:', - default: os.userInfo().username - }] as QuestionCollection); + message: "Enter author's name:", + default: os.userInfo().username, + }, + ] as QuestionCollection); name = answer.authorName.trim() || os.userInfo().username; } @@ -251,16 +268,19 @@ async function ensureAuthorEmail(email: string) { email = email.trim(); if (!isEmail(email)) { - const answer: { email: string } = - await inquirer.prompt<{ email: string }>([{ + const answer: { email: string } = await inquirer.prompt<{ + email: string; + }>([ + { type: 'input', name: 'email', - message: 'Enter author\'s email:' - }] as QuestionCollection); + message: "Enter author's email:", + }, + ] as QuestionCollection); if (!isEmail(answer.email)) { throw new TypeError( - 'Author\'s email is required, but was not given!' + "Author's email is required, but was not given!", ); } @@ -279,20 +299,20 @@ async function ensureTravisTags(argv: any): Promise { let tags = (argv.n || '').split(/\s+|\s*,\s*/).filter((t: string) => t); if (!tags.length) { - let answer: { tags: string } = - await inquirer.prompt<{ tags: string }>([{ + let answer: { tags: string } = await inquirer.prompt<{ tags: string }>([ + { type: 'input', name: 'tags', - message: 'Enter node version(s) for CI builds (comma-separated ' + + message: + 'Enter node version(s) for CI builds (comma-separated ' + 'if multiple):', - default: 'stable, latest' - }] as QuestionCollection); + default: 'stable, latest', + }, + ] as QuestionCollection); if (!answer.tags) { tags.push('stable', 'latest'); - } - - else { + } else { tags = answer.tags.split(/\s+|\s*,\s*/); } } @@ -312,32 +332,43 @@ async function ensureDockerNamespace(argv: any) { }; if (!dockerize && typeof config.useDocker === 'undefined') { - answer = await inquirer.prompt<{ useDocker: boolean }>([{ - type: 'confirm', - name: 'useDocker', - message: 'Would you like to dockerize your service?', - default: true, - }] as QuestionCollection); + answer = await inquirer.prompt<{ useDocker: boolean }>([ + { + type: 'confirm', + name: 'useDocker', + message: 'Would you like to dockerize your service?', + default: true, + }, + ] as QuestionCollection); - config.useDocker = argv.D = argv.dockerize = dockerize = - answer.useDocker; + config.useDocker = + argv.D = + argv.dockerize = + dockerize = + answer.useDocker; } if (dockerize && !isNamespace(ns)) { - answer = await inquirer.prompt<{ dockerNamespace: string }>([{ - type: 'input', - name: 'dockerNamespace', - message: 'Enter DockerHub namespace:' - }] as QuestionCollection); + answer = await inquirer.prompt<{ dockerNamespace: string }>([ + { + type: 'input', + name: 'dockerNamespace', + message: 'Enter DockerHub namespace:', + }, + ] as QuestionCollection); - if (answer.dockerNamespace && + if ( + answer.dockerNamespace && !isNamespace(answer.dockerNamespace.trim()) ) { throw new TypeError('Given DockerHub namespace is invalid!'); } - config.dockerHubNamespace = argv.N = argv.dockerNamespace = ns = - answer.dockerNamespace; + config.dockerHubNamespace = + argv.N = + argv.dockerNamespace = + ns = + answer.dockerNamespace; } return ns; @@ -350,7 +381,7 @@ async function ensureDockerTag(argv: any) { } const tags = await ensureTravisTags(argv); - const version = await nodeVersion(tags[0]); + const version = await nodeVersion(tags[0]); if (!version) { throw new TypeError('Invalid node version specified!'); @@ -377,16 +408,19 @@ async function ensureDockerSecrets(argv: any) { const repo = `${owner}/${name}`; if (!dockerHubUser) { - const answer: { dockerHubUser: string} = - await inquirer.prompt<{ dockerHubUser: string}>([{ + const answer: { dockerHubUser: string } = await inquirer.prompt<{ + dockerHubUser: string; + }>([ + { type: 'input', name: 'dockerHubUser', - message: 'Docker hub user:' - }] as QuestionCollection); + message: 'Docker hub user:', + }, + ] as QuestionCollection); if (!answer.dockerHubUser.trim()) { throw new TypeError( - 'DockerHub username required, but was not given!' + 'DockerHub username required, but was not given!', ); } @@ -394,16 +428,19 @@ async function ensureDockerSecrets(argv: any) { } if (!dockerHubPassword) { - const answer: { dockerHubPassword: string } = - await inquirer.prompt<{ dockerHubPassword: string }>([{ + const answer: { dockerHubPassword: string } = await inquirer.prompt<{ + dockerHubPassword: string; + }>([ + { type: 'password', name: 'dockerHubPassword', - message: 'Docker hub password:' - }] as QuestionCollection); + message: 'Docker hub password:', + }, + ] as QuestionCollection); if (!answer.dockerHubPassword.trim()) { throw new TypeError( - 'DockerHub password required, but was not given!' + 'DockerHub password required, but was not given!', ); } @@ -414,12 +451,14 @@ async function ensureDockerSecrets(argv: any) { return [ await travisEncrypt( - repo, `DOCKER_USER="${dockerHubUser}"`, - argv.p ? gitHubAuthToken : undefined + repo, + `DOCKER_USER="${dockerHubUser}"`, + argv.p ? gitHubAuthToken : undefined, ), await travisEncrypt( - repo, `DOCKER_PASS="${dockerHubPassword}"`, - argv.p ? gitHubAuthToken : undefined + repo, + `DOCKER_PASS="${dockerHubPassword}"`, + argv.p ? gitHubAuthToken : undefined, ), ]; } @@ -434,11 +473,9 @@ function stripDockerization(argv: any) { if (fs.existsSync(travis)) { const travisYml = fs.readFileSync(travis, { encoding: 'utf8' }); - fs.writeFileSync( - travis, - travisYml.replace(/services:[\s\S]+?$/, ''), - { encoding: 'utf8' } - ); + fs.writeFileSync(travis, travisYml.replace(/services:[\s\S]+?$/, ''), { + encoding: 'utf8', + }); } if (fs.existsSync(docker)) { @@ -460,29 +497,36 @@ async function enableTravisBuilds(argv: any) { argv.u, ensureName(argv.name), config.gitHubAuthToken, - argv.p + argv.p, ); - } catch(err) { /* ignore */ } + } catch (err) { + /* ignore */ + } if (!enabled) { // noinspection TypeScriptValidateJSTypes - console.log((chalk as any).red( - 'There was a problem enabling builds for this service. Please ' + - 'go to http://travis-ci.org/ and enable builds manually.' - )); + console.log( + (chalk as any).red( + 'There was a problem enabling builds for this service. Please ' + + 'go to http://travis-ci.org/ and enable builds manually.', + ), + ); } } // istanbul ignore next async function buildDockerCi(argv: any): Promise { const dockerNs = await ensureDockerNamespace(argv); - const dockerize = !!(gitRepoInitialized && dockerNs && ( - argv.D || config.useDocker - )); + const dockerize = !!( + gitRepoInitialized && + dockerNs && + (argv.D || config.useDocker) + ); const tags = { TRAVIS_NODE_TAG: (await ensureTravisTags(argv)) - .map(t => `- ${t}`).join('\n'), + .map(t => `- ${t}`) + .join('\n'), }; if (!dockerize) { @@ -495,9 +539,9 @@ async function buildDockerCi(argv: any): Promise { Object.assign(tags, { DOCKER_NAMESPACE: dockerNs, NODE_DOCKER_TAG: await ensureDockerTag(argv), - DOCKER_SECRETS: - `- secure: ${(await ensureDockerSecrets(argv)) - .join('\n - secure: ')}`, + DOCKER_SECRETS: `- secure: ${(await ensureDockerSecrets(argv)).join( + '\n - secure: ', + )}`, }); } @@ -512,7 +556,12 @@ async function buildTags(path: string, argv: any) { const email = await ensureAuthorEmail(argv.email); const { home, bugs } = ensureServicePages(argv); const license = await ensureLicense( - path, argv.license, author, email, home, name + path, + argv.license, + author, + email, + home, + name, ); // noinspection TypeScriptUnresolvedVariable @@ -537,8 +586,9 @@ async function buildTags(path: string, argv: any) { function createServiceFile(path: string, tags: any) { console.log('Creating main service file...'); - touch(resolve(path, 'src', `${tags.SERVICE_CLASS_NAME}.ts`), -`${tags.LICENSE_HEADER} + touch( + resolve(path, 'src', `${tags.SERVICE_CLASS_NAME}.ts`), + `${tags.LICENSE_HEADER} import { expose, IMQService, lock, logged, profile } from '@imqueue/rpc'; export class ${tags.SERVICE_CLASS_NAME} extends IMQService { @@ -567,18 +617,21 @@ export class ${tags.SERVICE_CLASS_NAME} extends IMQService { // Implement your service methods below this line } -`); +`, + ); } // istanbul ignore next function createServiceTestFile(path: string, tags: any) { console.log('Creating main service test file...'); - touch(resolve(path, 'test/src', `${tags.SERVICE_CLASS_NAME}.ts`), -`${tags.LICENSE_HEADER} + touch( + resolve(path, 'test/src', `${tags.SERVICE_CLASS_NAME}.ts`), + `${tags.LICENSE_HEADER} import { expect } from 'chai'; import { ${tags.SERVICE_CLASS_NAME} } from '../../src'; + describe('${tags.SERVICE_CLASS_NAME}', () => { it('should be a class of IMQService', () => { expect(typeof ${tags.SERVICE_CLASS_NAME}) @@ -604,16 +657,14 @@ describe('${tags.SERVICE_CLASS_NAME}', () => { }); }); }); -`); +`, + ); } // istanbul ignore next function compileTemplateFile(text: string, tags: any): string { for (let tag of Object.keys(tags)) { - text = text.replace( - new RegExp(`%${tag}`, 'g'), - tags[tag] - ); + text = text.replace(new RegExp(`%${tag}`, 'g'), tags[tag]); } return text; @@ -630,7 +681,7 @@ function compileTemplate(path: string, tags: any) { let content = compileTemplateFile( fs.readFileSync(filePath, { encoding: 'utf8' }), - tags + tags, ); fs.writeFileSync(filePath, content, { encoding: 'utf8' }); @@ -660,16 +711,19 @@ async function buildFromTemplate(argv: any) { // istanbul ignore next async function ensureGitRepo(argv: any) { if (!isNamespace(argv.u)) { - const answer: { gitNs: string } = - await inquirer.prompt<{ gitNs: string }>([{ + const answer: { gitNs: string } = await inquirer.prompt<{ + gitNs: string; + }>([ + { type: 'input', name: 'gitNs', message: 'Enter GitHub owner (user name or organization):', - }] as QuestionCollection); + }, + ] as QuestionCollection); if (!isNamespace(answer.gitNs)) { throw new TypeError( - `Given github namespace "${argv.u}" is invalid!` + `Given github namespace "${argv.u}" is invalid!`, ); } @@ -686,18 +740,22 @@ async function createGitRepo(argv: any) { const useGit = argv.g || config.useGit; if (!useGit && typeof config.useGit === 'undefined') { - const answer: { useGit: boolean } = - await inquirer.prompt<{ useGit: boolean }>([{ + const answer: { useGit: boolean } = await inquirer.prompt<{ + useGit: boolean; + }>([ + { type: 'confirm', name: 'useGit', - message: 'Would you like to enable automatic GitHub integration ' + + message: + 'Would you like to enable automatic GitHub integration ' + 'for this service?', default: true, - }] as QuestionCollection); + }, + ] as QuestionCollection); if (!answer.useGit) { argv.D = argv.dockerize = config.useDocker = false; - return ; + return; } } @@ -705,31 +763,40 @@ async function createGitRepo(argv: any) { let token = (argv.T || '').trim() || config.gitHubAuthToken; if (!isGuthubToken(token)) { - const answer: { token: string } = - await inquirer.prompt<{ token: string }>([{ + const answer: { token: string } = await inquirer.prompt<{ + token: string; + }>([ + { type: 'input', name: 'token', - message: 'Enter your GitHub auth token:' - }] as QuestionCollection); + message: 'Enter your GitHub auth token:', + }, + ] as QuestionCollection); if (!isGuthubToken(answer.token.trim())) { throw new Error('Given GitHub auth token is invalid!'); } - config.gitHubAuthToken = argv.T = argv.githubToken = token = - answer.token.trim(); + config.gitHubAuthToken = + argv.T = + argv.githubToken = + token = + answer.token.trim(); } let isPrivate = argv.p || config.gitRepoPrivate; if (!isPrivate && typeof config.gitRepoPrivate === 'undefined') { - const answer: { isPrivate: boolean } = - await inquirer.prompt<{ isPrivate: boolean }>([{ + const answer: { isPrivate: boolean } = await inquirer.prompt<{ + isPrivate: boolean; + }>([ + { type: 'confirm', name: 'isPrivate', message: 'Should be service created on GitHub as private repo?', - default: true - }] as QuestionCollection); + default: true, + }, + ] as QuestionCollection); isPrivate = answer.isPrivate; } @@ -814,8 +881,9 @@ git push origin master --tags`); // noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'create [name] [path]', - describe: 'Creates new service package with the given service name ' + - 'under given path.', + describe: + 'Creates new service package with the given service name ' + + 'under given path.', builder(yargs: Argv) { config = loadConfig(); @@ -826,7 +894,7 @@ export const { command, describe, builder, handler } = { .default('a', config.author || '') .alias('e', 'email') - .describe('e', 'Service author\'s contact email') + .describe('e', "Service author's contact email") .default('e', config.email || '') .alias('g', 'use-git') @@ -834,12 +902,18 @@ export const { command, describe, builder, handler } = { .boolean('g') .alias('u', 'github-namespace') - .describe('u', 'GitHub namespace (usually user name or ' + - 'organization name)') + .describe( + 'u', + 'GitHub namespace (usually user name or ' + + 'organization name)', + ) .default('u', (config.gitBaseUrl || '').split(':').pop() || '') - .describe('no-install', 'Do not install npm packages ' + - 'automatically on service creation') + .describe( + 'no-install', + 'Do not install npm packages ' + + 'automatically on service creation', + ) .boolean('no-install') .default('no-install', false) @@ -856,13 +930,19 @@ export const { command, describe, builder, handler } = { .default('B', '') .alias('l', 'license') - .describe('l', 'License for created service, should be either ' + - 'license name in SPDX format or path to a custom license file') + .describe( + 'l', + 'License for created service, should be either ' + + 'license name in SPDX format or path to a custom license file', + ) .default('l', config.license || 'UNLICENSED') .alias('t', 'template') - .describe('t', 'Template used to create service (should be ' + - 'either template name, git url or file system directory)') + .describe( + 't', + 'Template used to create service (should be ' + + 'either template name, git url or file system directory)', + ) .default('t', config.template || 'default') .alias('d', 'description') @@ -870,9 +950,12 @@ export const { command, describe, builder, handler } = { .default('d', '') .alias('n', 'node-versions') - .describe('n', 'Node version tags to use for builds, separated ' + - 'by comma if multiple. First one will be used for docker ' + - 'build, if dockerize option enabled.') + .describe( + 'n', + 'Node version tags to use for builds, separated ' + + 'by comma if multiple. First one will be used for docker ' + + 'build, if dockerize option enabled.', + ) .default('n', '') .alias('D', 'dockerize') @@ -880,8 +963,11 @@ export const { command, describe, builder, handler } = { .boolean('D') .alias('L', 'node-docker-tag') - .describe('L', 'Node docker tag to use as base docker image ' + - 'for docker builds') + .describe( + 'L', + 'Node docker tag to use as base docker image ' + + 'for docker builds', + ) .default('L', '') .alias('N', 'docker-namespace') @@ -900,8 +986,10 @@ export const { command, describe, builder, handler } = { .describe('name', 'Service name to create with') .default('path', '.') - .describe('path', - 'Path to directory where service will be generated to'); + .describe( + 'path', + 'Path to directory where service will be generated to', + ); }, async handler(argv: any) { @@ -921,15 +1009,13 @@ export const { command, describe, builder, handler } = { // noinspection TypeScriptValidateJSTypes console.log((chalk as any).green('Service successfully created!')); - } - - catch (err) { + } catch (err) { if (argv.path && !~['', '.', './'].indexOf(argv.path.trim())) { // cleanup service dir rmdir(resolve(argv.path)); } - printError(err); + printError(err as Error); } - } + }, }; diff --git a/src/service/update-version.ts b/src/service/update-version.ts index 8d528a3..ece2403 100644 --- a/src/service/update-version.ts +++ b/src/service/update-version.ts @@ -21,13 +21,16 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Argv, Arguments } from 'yargs'; +import { type Argv, type Arguments } from 'yargs'; import chalk from 'chalk'; -import { printError } from '../../lib'; -import { spawnSync, SpawnSyncReturns } from 'child_process'; +import { printError } from '../../lib/index.js'; +import { spawnSync, type SpawnSyncReturns } from 'child_process'; import { resolve } from 'path'; import { readdirSync } from 'fs'; import { Console } from 'console'; +import { createRequire } from 'node:module'; + +const require = createRequire(import.meta.url); const BASE_SERVICE_NAME = 'IMQService'; let PROGRAM: string = ''; @@ -44,9 +47,7 @@ const logger = new Console(process.stdout, process.stderr); * @returns {boolean} - * returns true if directory contains service, or false instead */ -function isFolderContainsService( - servicePath: string, -): boolean { +function isFolderContainsService(servicePath: string): boolean { const originalLogger = console.log; try { @@ -56,14 +57,18 @@ function isFolderContainsService( const service = require(servicePath); for (const [prop, func] of Object.entries(service)) { - if (!prop.includes('Service')) { continue; } + if (!prop.includes('Service')) { + continue; + } // noinspection TypeScriptUnresolvedVariable return (func as any).__proto__.name === BASE_SERVICE_NAME; } process.chdir(ROOT_DIRECTORY); - } catch (err) { /* ignore */ } + } catch (err) { + /* ignore */ + } console.log = originalLogger; @@ -107,9 +112,7 @@ function gitCheckout( * @param {string} servicePath - path to directory, which contains service * @returns {SpawnSyncReturns} */ -function gitPull( - servicePath: string, -): SpawnSyncReturns { +function gitPull(servicePath: string): SpawnSyncReturns { logger.log('Execution git pull...'); return spawnSync(`git`, ['pull'], { cwd: servicePath, @@ -139,9 +142,7 @@ function changeVersion( * @param {string} servicePath - path to directory, which contains service * @returns {SpawnSyncReturns} */ -function gitPush( - servicePath: string, -): SpawnSyncReturns { +function gitPush(servicePath: string): SpawnSyncReturns { logger.log('Execution git push...'); return spawnSync('git', ['push', '--follow-tags'], { cwd: servicePath, @@ -158,7 +159,7 @@ function gitPush( function handleSpawnResponse( response: SpawnSyncReturns, ): number | null { - if (response.status !== 0 || response.error && response.stderr) { + if (response.status !== 0 || (response.error && response.stderr)) { // noinspection TypeScriptValidateTypes logger.log(chalk.red(response.stderr.toString())); } @@ -176,26 +177,31 @@ function handleSpawnResponse( * @param {Arguments} args - cli args * @returns {void} */ -function execGitFlow( - servicePath: string, - args: Arguments, -): void { +function execGitFlow(servicePath: string, args: Arguments): void { let response: SpawnSyncReturns; response = gitCheckout(servicePath, args.branch as string); - if (handleSpawnResponse(response)) { return; } + if (handleSpawnResponse(response)) { + return; + } response = gitPull(servicePath); - if (handleSpawnResponse(response)) { return; } + if (handleSpawnResponse(response)) { + return; + } response = changeVersion(servicePath, args.npmVersion as string); - if (handleSpawnResponse(response)) { return; } + if (handleSpawnResponse(response)) { + return; + } response = gitPush(servicePath); - if (handleSpawnResponse(response)) { return; } + if (handleSpawnResponse(response)) { + return; + } // noinspection TypeScriptValidateTypes logger.log(chalk.green('Done!')); } @@ -206,9 +212,7 @@ function execGitFlow( * @param {string} path - path to root folder with services * @returns {string[]} - array of folders with services */ -function getServicesFolders( - path: string, -): string[] { +function getServicesFolders(path: string): string[] { const folders: string[] = []; path = resolve(path); @@ -218,11 +222,11 @@ function getServicesFolders( } else { for (const dir of readdirSync(path)) { const pathToService = resolve(path, dir); - const containsService = isFolderContainsService( - pathToService, - ); + const containsService = isFolderContainsService(pathToService); - if (containsService) { folders.push(pathToService) } + if (containsService) { + folders.push(pathToService); + } } } @@ -232,7 +236,8 @@ function getServicesFolders( // noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'update-version [branch] [version]', - describe: 'Updates services under given path with new version tag ' + + describe: + 'Updates services under given path with new version tag ' + 'and automatically pushes changes to repository, triggering builds.', async builder(yargs: Argv) { @@ -246,7 +251,8 @@ export const { command, describe, builder, handler } = { .option('n', { alias: 'npm-version', default: 'prerelease', - describe: 'NPM version to update (major|minor|patch|prerelease).' + describe: + 'NPM version to update (major|minor|patch|prerelease).', }) .describe('path', 'Path to directory containing services.'); }, @@ -256,7 +262,7 @@ export const { command, describe, builder, handler } = { const folders = getServicesFolders(argv.path as string); walkThroughFolders(folders, argv); } catch (err) { - printError(err); + printError(err as Error); } - } + }, }; diff --git a/test/lib/config.ts b/test/lib/config.spec.ts similarity index 61% rename from test/lib/config.ts rename to test/lib/config.spec.ts index 429dd4a..2bf0a76 100644 --- a/test/lib/config.ts +++ b/test/lib/config.spec.ts @@ -21,29 +21,38 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; +import { describe, it, before, beforeEach, after, afterEach } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; import { loadConfig, saveConfig, prepareConfigValue, configEmpty, CONFIG_PATH, - touch -} from '../../lib'; + touch, +} from '../../lib/index.js'; import * as fs from 'fs'; describe('config', () => { describe('loadConfig()', () => { - beforeEach(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); - afterEach(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); + beforeEach(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); + afterEach(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); it('should be a function', () => { - expect(typeof loadConfig).equals('function'); + assert.equal(typeof loadConfig, 'function'); }); it('should return object even if config does not exist', () => { - expect(typeof loadConfig()).equals('object'); + assert.equal(typeof loadConfig(), 'object'); }); it('should return actual object if config file exists', () => { @@ -51,7 +60,7 @@ describe('config', () => { touch(CONFIG_PATH, JSON.stringify(config, null, 2)); - expect(loadConfig()).to.deep.equal(config); + assert.deepEqual(loadConfig(), config); }); it('should throw if config data broken', () => { @@ -59,98 +68,113 @@ describe('config', () => { touch(CONFIG_PATH, config); - expect(() => loadConfig()).throws; + assert.throws(() => loadConfig()); }); }); describe('saveConfig()', () => { - before(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); - after(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); + before(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); + after(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); it('should be a function', () => { - expect(typeof saveConfig).equals('function'); + assert.equal(typeof saveConfig, 'function'); }); it('should save if file does not exist', () => { const config = { a: 1, b: 'test', c: true }; saveConfig(config); - expect(loadConfig()).to.deep.equal(config); + assert.deepEqual(loadConfig(), config); }); it('should overwrite if file exists', () => { const config = { a: 123, b: 'test123', c: false }; saveConfig(config); - expect(loadConfig()).to.deep.equal(config); + assert.deepEqual(loadConfig(), config); }); }); describe('prepareConfigValue()', () => { it('should be a function', () => { - expect(typeof prepareConfigValue).equals('function'); + assert.equal(typeof prepareConfigValue, 'function'); }); it('should return true if "true" value passed', () => { - expect(prepareConfigValue('true')).equals(true); + assert.equal(prepareConfigValue('true'), true); }); it('should return false if "false" value passed', () => { - expect(prepareConfigValue('false')).equals(false); + assert.equal(prepareConfigValue('false'), false); }); it('should return null if "null" value passed', () => { - expect(prepareConfigValue('null')).equals(null); + assert.equal(prepareConfigValue('null'), null); }); it('should return undefined if "undefined" value passed', () => { - expect(prepareConfigValue('undefined')).equals(undefined); + assert.equal(prepareConfigValue('undefined'), undefined); }); it('should return array object if "[]" value passed', () => { - expect(prepareConfigValue('[]')).to.be.instanceOf(Array); + assert.ok(prepareConfigValue('[]') instanceof Array); }); it('should return object if "{}" value passed', () => { - expect(prepareConfigValue('{}')).to.be.instanceOf(Object); + assert.ok(prepareConfigValue('{}') instanceof Object); }); it('should return same object if non-string passed', () => { const obj = { a: 1, b: true }; - expect(prepareConfigValue(obj)).equals(obj); + assert.equal(prepareConfigValue(obj), obj); }); it('should throw if broken value passed', () => { - expect(() => prepareConfigValue('[}')).throws; + assert.throws(() => prepareConfigValue('[}')); }); }); describe('configEmpty()', () => { - before(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); - after(() => { try { fs.unlinkSync(CONFIG_PATH) } catch (e) {} }); + before(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); + after(() => { + try { + fs.unlinkSync(CONFIG_PATH); + } catch (e) {} + }); it('should be a function', () => { - expect(typeof configEmpty).equals('function'); + assert.equal(typeof configEmpty, 'function'); }); it('should return true if config does not exist', () => { - expect(configEmpty()).equals(true); + assert.equal(configEmpty(), true); }); it('should return true if config exists but empty', () => { touch(CONFIG_PATH, ''); - expect(configEmpty()).equals(true); + assert.equal(configEmpty(), true); }); - it('should return true if config exists but contains empty object', - () => { + it('should return true if config exists but contains empty object', () => { fs.writeFileSync(CONFIG_PATH, '{}'); - expect(configEmpty()).equals(true); + assert.equal(configEmpty(), true); }); it('should return file if config exists and not empty', () => { saveConfig({ a: 1 }); - expect(configEmpty()).equals(false); + assert.equal(configEmpty(), false); }); }); }); diff --git a/test/lib/error.ts b/test/lib/error.spec.ts similarity index 83% rename from test/lib/error.ts rename to test/lib/error.spec.ts index 8b3a548..6e200f9 100644 --- a/test/lib/error.ts +++ b/test/lib/error.spec.ts @@ -21,14 +21,15 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import { printError } from '../../lib'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { printError } from '../../lib/index.js'; describe('error', () => { describe('printError()', () => { it('should be a function', () => { - expect(typeof printError).equals('function'); + assert.equal(typeof printError, 'function'); }); }); }); diff --git a/test/lib/fs.ts b/test/lib/fs.spec.ts similarity index 63% rename from test/lib/fs.ts rename to test/lib/fs.spec.ts index 9ae41f4..4e90112 100644 --- a/test/lib/fs.ts +++ b/test/lib/fs.spec.ts @@ -21,22 +21,29 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; +import { describe, it, before, after } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; import * as fs from 'fs'; -import { uuid } from '@imqueue/rpc'; +import { randomUUID as uuid } from 'node:crypto'; import * as p from 'path'; -import { mkdirp, touch, rmdir, cpr } from '../../lib'; +import { mkdirp, touch, rmdir, cpr } from '../../lib/index.js'; const TEMP_DIR: string = p.resolve('.', '.imq-cli-test'); describe('fs', () => { - before(() => { fs.mkdirSync(TEMP_DIR) }); - after(() => { try { rmdir(TEMP_DIR) } catch (e) {} }); + before(() => { + fs.mkdirSync(TEMP_DIR); + }); + after(() => { + try { + rmdir(TEMP_DIR); + } catch (e) {} + }); describe('cpr()', () => { it('should be a function', () => { - expect(typeof cpr).equals('function'); + assert.equal(typeof cpr, 'function'); }); it('should copy directory contents recursively', () => { @@ -50,10 +57,16 @@ describe('fs', () => { cpr(src, dst); - expect(fs.statSync(dst).isDirectory()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'dir')).isDirectory()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'file')).isFile()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'dir/file')).isFile()).to.be.true; + assert.equal(fs.statSync(dst).isDirectory(), true); + assert.equal( + fs.statSync(p.resolve(dst, 'dir')).isDirectory(), + true, + ); + assert.equal(fs.statSync(p.resolve(dst, 'file')).isFile(), true); + assert.equal( + fs.statSync(p.resolve(dst, 'dir/file')).isFile(), + true, + ); }); it('should copy properly', () => { @@ -68,16 +81,22 @@ describe('fs', () => { cpr(src, dst); - expect(fs.statSync(dst).isDirectory()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'dir')).isDirectory()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'file')).isFile()).to.be.true; - expect(fs.statSync(p.resolve(dst, 'dir/file')).isFile()).to.be.true; + assert.equal(fs.statSync(dst).isDirectory(), true); + assert.equal( + fs.statSync(p.resolve(dst, 'dir')).isDirectory(), + true, + ); + assert.equal(fs.statSync(p.resolve(dst, 'file')).isFile(), true); + assert.equal( + fs.statSync(p.resolve(dst, 'dir/file')).isFile(), + true, + ); }); }); describe('mkdirp()', () => { it('should be a function', () => { - expect(typeof mkdirp).equals('function'); + assert.equal(typeof mkdirp, 'function'); }); it('should create path recursively', () => { @@ -86,8 +105,8 @@ describe('fs', () => { mkdirp(dirTwo); - expect(fs.existsSync(dirOne)).to.be.true; - expect(fs.existsSync(dirTwo)).to.be.true; + assert.equal(fs.existsSync(dirOne), true); + assert.equal(fs.existsSync(dirTwo), true); fs.rmdirSync(dirTwo); fs.rmdirSync(dirOne); @@ -96,7 +115,7 @@ describe('fs', () => { describe('touch()', () => { it('should be a function', () => { - expect(typeof touch).equals('function'); + assert.equal(typeof touch, 'function'); }); it('should create file if not exist', () => { @@ -105,14 +124,14 @@ describe('fs', () => { touch(file, 'initial'); touch(file, 'changed'); - expect(fs.existsSync(file)).to.be.true; - expect(fs.readFileSync(file).toString()).equals('initial'); + assert.equal(fs.existsSync(file), true); + assert.equal(fs.readFileSync(file).toString(), 'initial'); }); }); describe('rmdir()', () => { it('should be a function', () => { - expect(typeof rmdir).equals('function'); + assert.equal(typeof rmdir, 'function'); }); it('should remove directory with all it contents', () => { @@ -130,11 +149,11 @@ describe('fs', () => { rmdir(target); - expect(fs.existsSync(dirDir)).to.be.false; - expect(fs.existsSync(dirFile)).to.be.false; - expect(fs.existsSync(dir)).to.be.false; - expect(fs.existsSync(file)).to.be.false; - expect(fs.existsSync(target)).to.be.false; + assert.equal(fs.existsSync(dirDir), false); + assert.equal(fs.existsSync(dirFile), false); + assert.equal(fs.existsSync(dir), false); + assert.equal(fs.existsSync(file), false); + assert.equal(fs.existsSync(target), false); }); }); }); diff --git a/test/lib/github.ts b/test/lib/github.spec.ts similarity index 72% rename from test/lib/github.ts rename to test/lib/github.spec.ts index 3a0a6cd..8c6b74a 100644 --- a/test/lib/github.ts +++ b/test/lib/github.spec.ts @@ -21,22 +21,21 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import { uuid } from '@imqueue/rpc'; -import * as github from '../../lib/github'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { randomUUID as uuid } from 'node:crypto'; +import * as github from '../../lib/github.js'; import { config as envConfig } from 'dotenv'; envConfig(); -xdescribe('github', function () { - this.timeout(30000); - +describe.skip('github', () => { const token = String(process.env.GITHUB_AUTH_TOKEN); describe('getInstance()', () => { it('should be a function', () => { - expect(typeof github.getInstance).equals('function'); + assert.equal(typeof github.getInstance, 'function'); }); it('should not throw if valid token given', async () => { @@ -48,7 +47,7 @@ xdescribe('github', function () { error = err; } - expect(error).to.be.null; + assert.equal(error, null); }); it('should trow if invalid token given', async () => { @@ -60,55 +59,55 @@ xdescribe('github', function () { error = err; } - expect(error).not.to.be.null; + assert.notEqual(error, null); }); }); describe('getTeam()', () => { it('should be a function', () => { - expect(typeof github.getTeam).equals('function'); + assert.equal(typeof github.getTeam, 'function'); }); it('should return team object for a logged-in user', async () => { const git = await github.getInstance(token); const team = await github.getTeam(git, 'imqueue'); - expect(team).to.be.ok; - expect(team.id).not.to.be.undefined; + assert.ok(team); + assert.notEqual(team.id, undefined); }); it('should return null if there is no team', async () => { const git = await github.getInstance(token); const team = await github.getTeam(git, 'Mikhus'); - expect(team).to.be.null; + assert.equal(team, null); }); }); describe('getOrg()', () => { it('should be a function', () => { - expect(typeof github.getOrg).equals('function'); + assert.equal(typeof github.getOrg, 'function'); }); it('should return organization if it exists', async () => { const git = await github.getInstance(token); const org = await github.getOrg(git, 'imqueue'); - expect(org).to.be.ok; - expect(org.name).equals('imqueue'); + assert.ok(org); + assert.equal(org.name, 'imqueue'); }); it('should return null if there is no team', async () => { const git = await github.getInstance(token); const org = await github.getOrg(git, 'Mikhus'); - expect(org).to.be.null; + assert.equal(org, null); }); }); describe('createRepository()', () => { it('should be a function', () => { - expect(typeof github.createRepository).equals('function'); + assert.equal(typeof github.createRepository, 'function'); }); it('should create repository in user space if asked', async () => { @@ -120,14 +119,16 @@ xdescribe('github', function () { try { await github.createRepository(url, token, 'IMQ-CLI test repo'); const data = await git.repos.get({ owner, repo }); - expect(data).to.be.ok; - expect(data.name).equals(repo); - expect(data.owner.login).equals(owner); + assert.ok(data); + assert.equal(data.name, repo); + assert.equal(data.owner.login, owner); } catch (err) {} try { // cleanup await git.repos.delete({ owner, repo }); - } catch (err) { console.error(err); } + } catch (err) { + console.error(err); + } }); it('should create repository in org space if asked', async () => { @@ -138,27 +139,34 @@ xdescribe('github', function () { try { await github.createRepository( - url, token, 'IMQ-CLI test repo', false + url, + token, + 'IMQ-CLI test repo', + false, ); const data = await git.repos.get({ owner, repo }); - expect(data).to.be.ok; - expect(data.name).equals(repo); - expect(data.owner.login).equals(owner); + assert.ok(data); + assert.equal(data.name, repo); + assert.equal(data.owner.login, owner); } catch (err) {} try { // cleanup await git.repos.delete({ owner, repo }); - } catch (err) { console.error(err); } + } catch (err) { + console.error(err); + } }); it('should throw if invalid url given', async () => { try { await github.createRepository( - 'j032', token, 'IMQ-CLI test repo' + 'j032', + token, + 'IMQ-CLI test repo', ); } catch (err) { - expect(err).instanceof(TypeError); - expect(err.message).match(/url .*? is invalid/); + assert.ok(err instanceof TypeError); + assert.match(err.message, /url .*? is invalid/); } }); @@ -172,13 +180,15 @@ xdescribe('github', function () { await github.createRepository(url, token, 'IMQ-CLI test repo'); await github.createRepository(url, token, 'IMQ-CLI test repo'); } catch (err) { - expect(err).instanceof(Error); - expect(err.message).equals('Repository already exists!'); + assert.ok(err instanceof Error); + assert.equal(err.message, 'Repository already exists!'); } try { // cleanup await git.repos.delete({ owner, repo }); - } catch (err) { console.error(err); } + } catch (err) { + console.error(err); + } }); }); }); diff --git a/test/lib/license.ts b/test/lib/license.spec.ts similarity index 64% rename from test/lib/license.ts rename to test/lib/license.spec.ts index a1ae157..23f4d03 100644 --- a/test/lib/license.ts +++ b/test/lib/license.spec.ts @@ -21,27 +21,28 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from "chai"; -import { findLicense } from '../../lib'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { findLicense } from '../../lib/index.js'; -describe('license', function() { +describe('license', function () { describe('findLicense()', () => { it('should be a function', () => { - expect(typeof findLicense).equals('function'); + assert.equal(typeof findLicense, 'function'); }); it('should return license object if proper name given', () => { - expect(findLicense('mit').spdx_id).equals('MIT'); - expect(findLicense('Mit').spdx_id).equals('MIT'); - expect(findLicense('mIt').spdx_id).equals('MIT'); - expect(findLicense('MIT').spdx_id).equals('MIT'); - expect(findLicense('mi').spdx_id).equals('MIT'); - expect(findLicense('mit license').spdx_id).equals('MIT'); + assert.equal(findLicense('mit').spdx_id, 'MIT'); + assert.equal(findLicense('Mit').spdx_id, 'MIT'); + assert.equal(findLicense('mIt').spdx_id, 'MIT'); + assert.equal(findLicense('MIT').spdx_id, 'MIT'); + assert.equal(findLicense('mi').spdx_id, 'MIT'); + assert.equal(findLicense('mit license').spdx_id, 'MIT'); }); it('should return null if nothing found', () => { - expect(findLicense('dsjgiuewhd')).to.be.null; + assert.equal(findLicense('dsjgiuewhd'), null); }); }); }); diff --git a/test/lib/names.ts b/test/lib/names.spec.ts similarity index 55% rename from test/lib/names.ts rename to test/lib/names.spec.ts index 0ab8c31..e2af727 100644 --- a/test/lib/names.ts +++ b/test/lib/names.spec.ts @@ -21,39 +21,40 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import { dashed, camelCase } from '../../lib'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { dashed, camelCase } from '../../lib/index.js'; describe('names', () => { describe('dashed()', () => { it('should be a function', () => { - expect(typeof dashed).equals('function'); + assert.equal(typeof dashed, 'function'); }); it('should properly transform given name to dashed string', () => { - expect(dashed('camelCase')).equals('camel-case'); - expect(dashed('CamelCase')).equals('camel-case'); - expect(dashed('Camel-Case')).equals('camel-case'); - expect(dashed('Camel_Case')).equals('camel-case'); - expect(dashed('_camelCase')).equals('-camel-case'); - expect(dashed('-CamelCase')).equals('-camel-case'); - expect(dashed(' CamelCase')).equals('camel-case'); - expect(dashed(' CamelCase ')).equals('camel-case'); + assert.equal(dashed('camelCase'), 'camel-case'); + assert.equal(dashed('CamelCase'), 'camel-case'); + assert.equal(dashed('Camel-Case'), 'camel-case'); + assert.equal(dashed('Camel_Case'), 'camel-case'); + assert.equal(dashed('_camelCase'), '-camel-case'); + assert.equal(dashed('-CamelCase'), '-camel-case'); + assert.equal(dashed(' CamelCase'), 'camel-case'); + assert.equal(dashed(' CamelCase '), 'camel-case'); }); }); describe('camelCase()', () => { it('should be a function', () => { - expect(typeof camelCase).equals('function'); + assert.equal(typeof camelCase, 'function'); }); it('should properly transform given name to dashed string', () => { - expect(camelCase('camel-case')).equals('CamelCase'); - expect(camelCase('-camel-case')).equals('-CamelCase'); - expect(camelCase(' camel-case')).equals('CamelCase'); - expect(camelCase(' camel-case ')).equals('CamelCase'); - expect(camelCase('camel_case/string')).equals('CamelCaseString'); + assert.equal(camelCase('camel-case'), 'CamelCase'); + assert.equal(camelCase('-camel-case'), '-CamelCase'); + assert.equal(camelCase(' camel-case'), 'CamelCase'); + assert.equal(camelCase(' camel-case '), 'CamelCase'); + assert.equal(camelCase('camel_case/string'), 'CamelCaseString'); }); }); }); diff --git a/test/lib/node.spec.ts b/test/lib/node.spec.ts new file mode 100644 index 0000000..4fb49ca --- /dev/null +++ b/test/lib/node.spec.ts @@ -0,0 +1,110 @@ +/*! + * IMQ-CLI Unit Tests: node + * + * I'm Queue Software Project + * Copyright (C) 2025 imqueue.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you want to use this code in a closed source (commercial) project, you can + * purchase a proprietary commercial license. Please contact us at + * to get commercial licensing options. + */ +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import * as node from '../../lib/node.js'; + +describe('node', () => { + describe('semverCompare()', () => { + it('should be a function', () => { + assert.equal(typeof node.semverCompare, 'function'); + }); + + it('should perform comparison properly', () => { + assert.equal(node.semverCompare('0.0.0', '0.0.0'), 0); + assert.equal(node.semverCompare('1.0.0', '1.0.0'), 0); + assert.equal(node.semverCompare('1.2.10', '1.2.10'), 0); + assert.equal(node.semverCompare('3.4.5', '3.4.5'), 0); + assert.equal(node.semverCompare('1.0.1', '1.0.0'), -1); + assert.equal(node.semverCompare('1.1.1', '1.0.1'), -1); + assert.equal(node.semverCompare('0.0.1', '0.0.0'), -1); + assert.equal(node.semverCompare('10.0.0', '1.0.0'), -1); + assert.equal(node.semverCompare('0.0.0', '2.0.0'), 1); + assert.equal(node.semverCompare('1.0.0', '2.0.0'), 1); + assert.equal(node.semverCompare('1.0.1', '1.1.0'), 1); + assert.equal(node.semverCompare('1.0.0', '10.0.0'), 1); + }); + }); + + describe('getNodeVersions()', () => { + it('should be a function', () => { + assert.equal(typeof node.getNodeVersions, 'function'); + }); + + it('should return node versions', async () => { + const versions = await node.getNodeVersions(); + assert.ok(versions instanceof Array); + assert.equal(typeof versions[0].version, 'string'); + assert.match(versions[0].version, /^v\d+\.\d+\.\d+$/); + }); + }); + + describe('nodeVersion()', () => { + it('should be a function', () => { + assert.equal(typeof node.nodeVersion, 'function'); + }); + + it('should return proper version for given tag', async () => { + const versions = await node.getNodeVersions(); + const lts: any = versions.find(v => !!v.lts); + const max10: any = versions.find(v => v.version.startsWith('v10')); + const max43: any = versions.find(v => /v4\.3/.test(v.version)); + + assert.equal( + 'v' + (await node.nodeVersion('latest')), + versions[0].version, + ); + assert.equal( + 'v' + (await node.nodeVersion('node')), + versions[0].version, + ); + assert.equal('v' + (await node.nodeVersion('stable')), lts.version); + assert.equal('v' + (await node.nodeVersion('lts')), lts.version); + assert.equal('v' + (await node.nodeVersion('lts/*')), lts.version); + assert.equal('v' + (await node.nodeVersion('10')), max10.version); + assert.equal('v' + (await node.nodeVersion('4.3')), max43.version); + }); + }); + + describe('toTravisTags()', () => { + it('should be a function', () => { + assert.equal(typeof node.toTravisTags, 'function'); + }); + + it('should return valid tags converted', async () => { + assert.deepEqual(await node.toTravisTags(''), []); + assert.deepEqual(await node.toTravisTags('node'), ['node']); + assert.deepEqual(await node.toTravisTags(['latest', 'stable']), [ + 'node', + 'lts/*', + ]); + assert.deepEqual( + await node.toTravisTags(['latest', 'stable', 'lts']), + ['node', 'lts/*'], + ); + assert.deepEqual(await node.toTravisTags('lts/*'), ['lts/*']); + }); + }); +}); diff --git a/test/lib/node.ts b/test/lib/node.ts deleted file mode 100644 index c67b6d0..0000000 --- a/test/lib/node.ts +++ /dev/null @@ -1,101 +0,0 @@ -/*! - * IMQ-CLI Unit Tests: node - * - * I'm Queue Software Project - * Copyright (C) 2025 imqueue.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * If you want to use this code in a closed source (commercial) project, you can - * purchase a proprietary commercial license. Please contact us at - * to get commercial licensing options. - */ -import '../mocks'; -import { expect } from 'chai'; -import * as node from '../../lib/node'; - -describe('node', () => { - describe('semverCompare()', () => { - it('should be a function', () => { - expect(typeof node.semverCompare).equals('function'); - }); - - it('should perform comparison properly', () => { - expect(node.semverCompare('0.0.0', '0.0.0')).equals(0); - expect(node.semverCompare('1.0.0', '1.0.0')).equals(0); - expect(node.semverCompare('1.2.10', '1.2.10')).equals(0); - expect(node.semverCompare('3.4.5', '3.4.5')).equals(0); - expect(node.semverCompare('1.0.1', '1.0.0')).equals(-1); - expect(node.semverCompare('1.1.1', '1.0.1')).equals(-1); - expect(node.semverCompare('0.0.1', '0.0.0')).equals(-1); - expect(node.semverCompare('10.0.0', '1.0.0')).equals(-1); - expect(node.semverCompare('0.0.0', '2.0.0')).equals(1); - expect(node.semverCompare('1.0.0', '2.0.0')).equals(1); - expect(node.semverCompare('1.0.1', '1.1.0')).equals(1); - expect(node.semverCompare('1.0.0', '10.0.0')).equals(1); - }); - }); - - describe('getNodeVersions()', () => { - it('should be a function', () => { - expect(typeof node.getNodeVersions).equals('function'); - }); - - it('should return node versions', async () => { - const versions = await node.getNodeVersions(); - expect(versions).instanceof(Array); - expect(versions[0].version).to.be.string; - expect(versions[0].version).match(/^v\d+\.\d+\.\d+$/); - }); - }); - - describe('nodeVersion()', () => { - it('should be a function', () => { - expect(typeof node.nodeVersion).equals('function'); - }); - - it('should return proper version for given tag', async () => { - const versions = await node.getNodeVersions(); - const lts: any = versions.find(v => !!v.lts); - const max10: any = versions.find(v => /^v10/.test(v.version)); - const max43: any = versions.find(v => /v4\.3/.test(v.version)); - - expect('v' + await node.nodeVersion('latest')) - .equals(versions[0].version); - expect('v' + await node.nodeVersion('node')) - .equals(versions[0].version); - expect('v' + await node.nodeVersion('stable')).equals(lts.version); - expect('v' + await node.nodeVersion('lts')).equals(lts.version); - expect('v' + await node.nodeVersion('lts/*')).equals(lts.version); - expect('v' + await node.nodeVersion('10')).equals(max10.version); - expect('v' + await node.nodeVersion('4.3')).equals(max43.version); - }); - }); - - describe('toTravisTags()', () => { - it('should be a function', () => { - expect(typeof node.toTravisTags).equals('function'); - }); - - it('should return valid tags converted', async () => { - expect(await node.toTravisTags('')).eqls([]); - expect(await node.toTravisTags('node')).eqls(['node']); - expect(await node.toTravisTags(['latest', 'stable'])) - .eqls(['node', 'lts/*']); - expect(await node.toTravisTags(['latest', 'stable', 'lts'])) - .eqls(['node', 'lts/*']); - expect(await node.toTravisTags('lts/*')).eqls(['lts/*']); - }); - }); -}); diff --git a/test/lib/path.ts b/test/lib/path.spec.ts similarity index 78% rename from test/lib/path.ts rename to test/lib/path.spec.ts index e7123c7..c3d8eff 100644 --- a/test/lib/path.ts +++ b/test/lib/path.spec.ts @@ -21,23 +21,24 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; import * as p from 'path'; -import { resolve, OS_HOME } from '../../lib'; +import { resolve, OS_HOME } from '../../lib/index.js'; describe('path', () => { describe('resolve()', () => { it('should be a function', () => { - expect(typeof resolve).equals('function'); + assert.equal(typeof resolve, 'function'); }); it('should properly resolve home directory', () => { - expect(resolve('~')).equals(OS_HOME); + assert.equal(resolve('~'), OS_HOME); }); it('should normalize given path', () => { - expect(resolve(`${OS_HOME}/..`)).equals(p.dirname(OS_HOME)); + assert.equal(resolve(`${OS_HOME}/..`), p.dirname(OS_HOME)); }); }); }); diff --git a/test/lib/template.ts b/test/lib/template.spec.ts similarity index 78% rename from test/lib/template.ts rename to test/lib/template.spec.ts index ed5328c..6da7bc2 100644 --- a/test/lib/template.ts +++ b/test/lib/template.spec.ts @@ -21,19 +21,21 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; +import { describe, it, after } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; import { wrap, checkGit, loadTemplates, updateTemplates, loadTemplate, -} from '../../lib'; +} from '../../lib/index.js'; describe('template', () => { describe('wrap()', () => { - const text = 'Lorem ipsum dolor sit amet, consectetur adipiscing ' + + const text = + 'Lorem ipsum dolor sit amet, consectetur adipiscing ' + 'elit, sed do eiusmod tempor incididunt ut labore et dolore ' + 'magna aliqua. Ut enim ad minim veniam, quis nostrud ' + 'exercitation ullamco laboris nisi ut aliquip ex ea ' + @@ -44,63 +46,65 @@ describe('template', () => { 'laborum.'; it('should be a function', () => { - expect(typeof wrap).equals('function'); + assert.equal(typeof wrap, 'function'); }); it('should wrap text to 80 chars by default with no indent', () => { const wrappedLines = wrap(text).split(/\r?\n/); for (let line of wrappedLines) { - expect(line.length).lte(80); + assert.ok(line.length <= 80); } }); it('should wrap text to given of number chars with no indent', () => { const wrappedLines = wrap(text, 90, '').split(/\r?\n/); for (let line of wrappedLines) { - expect(line.length).lte(90); + assert.ok(line.length <= 90); } }); it('should wrap text using given indentation', () => { const wrappedLines = wrap(text, 80, ' ').split(/\r?\n/); for (let line of wrappedLines) { - expect(line.substr(0, 5)).equals(' '); + assert.equal(line.substr(0, 5), ' '); } }); }); describe('checkGit()', () => { - after(() => { (global).checkGitResult = true }); + after(() => { + (global).checkGitResult = true; + }); it('should be a function', () => { - expect(typeof checkGit).equals('function'); + assert.equal(typeof checkGit, 'function'); }); it('should not throw if git command exists', () => { (global).checkGitResult = true; - expect(() => checkGit()).not.to.throw(Error); + assert.doesNotThrow(() => checkGit()); }); it('should throw if git command does not exist', () => { (global).checkGitResult = false; - expect(() => checkGit()).throws(Error); + assert.throws(() => checkGit()); }); }); describe('loadTemplates()', () => { it('should be a function', () => { - expect(typeof loadTemplates).equals('function'); + assert.equal(typeof loadTemplates, 'function'); }); }); describe('updateTemplates()', () => { it('should be a function', () => { - expect(typeof updateTemplates).equals('function'); + assert.equal(typeof updateTemplates, 'function'); }); }); describe('loadTemplate()', () => { it('should be a function', () => { - expect(typeof loadTemplate).equals('function'); + assert.equal(typeof loadTemplate, 'function'); }); }); }); diff --git a/test/lib/travis.ts b/test/lib/travis.spec.ts similarity index 69% rename from test/lib/travis.ts rename to test/lib/travis.spec.ts index 400ec09..54557e6 100644 --- a/test/lib/travis.ts +++ b/test/lib/travis.spec.ts @@ -21,43 +21,42 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import { travisEncrypt } from '../../lib'; - -describe('travis', function() { - this.timeout(30000); +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { travisEncrypt } from '../../lib/index.js'; +describe('travis', () => { describe('travisEncrypt()', () => { it('should be a function', () => { - expect(typeof travisEncrypt).equals('function'); + assert.equal(typeof travisEncrypt, 'function'); }); - xit('should not throw on existing public repo', async () => { + it.skip('should not throw on existing public repo', async () => { let error: any = null; try { await travisEncrypt('imqueue/cli', 'a=b'); - } - catch (err) { + } catch (err) { error = err; } - expect(error).equals(null); + assert.equal(error, null); }); it('should throw if wrong repo or credentials', async () => { let error: any = null; try { await travisEncrypt('!@#$/%^&*', 'a=b'); - } - catch (err) { + } catch (err) { error = err; } - expect(error).to.be.instanceOf(Error); + assert.ok(error instanceof Error); }); - xit('should return string value', async () => { - expect(typeof await travisEncrypt('imqueue/cli', 'a=b')) - .equals('string'); + it.skip('should return string value', async () => { + assert.equal( + typeof (await travisEncrypt('imqueue/cli', 'a=b')), + 'string', + ); }); }); }); diff --git a/test/lib/validate.ts b/test/lib/validate.spec.ts similarity index 62% rename from test/lib/validate.ts rename to test/lib/validate.spec.ts index 540ae3f..ff6c70e 100644 --- a/test/lib/validate.ts +++ b/test/lib/validate.spec.ts @@ -21,35 +21,36 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from "chai"; -import { isEmail, isNamespace, isGuthubToken } from '../../lib'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import { isEmail, isNamespace, isGuthubToken } from '../../lib/index.js'; -describe('validate', function() { +describe('validate', function () { describe('isEmail()', () => { it('should be a function', () => { - expect(typeof isEmail).equals('function'); + assert.equal(typeof isEmail, 'function'); }); it('should properly check given email string', () => { - expect(isEmail('a@b')).equals(true); - expect(isEmail('a.b@b.net')).equals(true); - expect(isEmail('a-c0@b.dot')).equals(true); - expect(isEmail('a#b')).equals(false); - expect(isEmail('ab')).equals(false); + assert.equal(isEmail('a@b'), true); + assert.equal(isEmail('a.b@b.net'), true); + assert.equal(isEmail('a-c0@b.dot'), true); + assert.equal(isEmail('a#b'), false); + assert.equal(isEmail('ab'), false); }); }); describe('isNamespace()', () => { it('should be a function', () => { - expect(typeof isNamespace).equals('function'); + assert.equal(typeof isNamespace, 'function'); }); it('should properly check if a given string valid namespace', () => { - expect(isNamespace('f57f%')).equals(false); - expect(isNamespace('f57f')).equals(true); - expect(isNamespace('djslkdj')).equals(true); - expect(isNamespace('imqueue')).equals(true); + assert.equal(isNamespace('f57f%'), false); + assert.equal(isNamespace('f57f'), true); + assert.equal(isNamespace('djslkdj'), true); + assert.equal(isNamespace('imqueue'), true); }); }); }); diff --git a/test/mocks/command-exists.ts b/test/mocks/command-exists.ts index 84acaf4..5874560 100644 --- a/test/mocks/command-exists.ts +++ b/test/mocks/command-exists.ts @@ -21,16 +21,10 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import * as mock from 'mock-require'; +(global as any).checkGitResult = true; -(global).checkGitResult = true; - -function _commandExists() { - return (global).checkGitResult; +export function commandExistsMock(): boolean { + return (global as any).checkGitResult; } -(_commandExists as any).sync = _commandExists; - -mock('command-exists', _commandExists); - -export const commandExists = require('command-exists'); +(commandExistsMock as any).sync = commandExistsMock; diff --git a/test/mocks/constants.ts b/test/mocks/constants.ts deleted file mode 100644 index 1b4fd49..0000000 --- a/test/mocks/constants.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*! - * IMQ-CLI Unit Test Mocks: constants - * - * I'm Queue Software Project - * Copyright (C) 2025 imqueue.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * If you want to use this code in a closed source (commercial) project, you can - * purchase a proprietary commercial license. Please contact us at - * to get commercial licensing options. - */ -import * as mock from 'mock-require'; - -const constants = { - OS_HOME: '/tmp', - IMQ_HOME: '/tmp/.imq', - CONFIG_FILENAME: 'config.json', - CONFIG_PATH: '/tmp/.imq/config.json', - IS_ZSH: Object.keys(process.env).some(key => /^ZSH/.test(key)), - TPL_HOME: '/tmp/.imq/templates', - TPL_REPO: 'git@github.com:imqueue/templates.git', - CUSTOM_TPL_HOME: '/tmp/.imq/custom-templates', -}; - -mock('../../lib/constants', constants); - -export * from '../../lib/constants'; diff --git a/test/mocks/index.ts b/test/mocks/index.ts index ea0b409..4b73434 100644 --- a/test/mocks/index.ts +++ b/test/mocks/index.ts @@ -21,7 +21,30 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -export * from './constants'; -export * from './logger'; -export * from './redis'; -export * from './command-exists'; +// sandbox all cli file locations before anything loads lib/constants +process.env.IMQ_CLI_HOME = '/tmp'; + +const { mock } = await import('node:test'); +const { commandExistsMock } = await import('./command-exists.js'); +const { Redis } = await import('./redis.js'); + +// preloaded via `node --import ./test/mocks/index.js` so mocks are +// registered before any test file graph links (see package.json scripts) +mock.module('command-exists', { + cache: false, + defaultExport: commandExistsMock, +}); +mock.module('ioredis', { + cache: false, + defaultExport: { + __esModule: true, + default: Redis, + Redis, + }, + namedExports: { + Redis, + }, +}); + +export * from './logger.js'; +export * from './redis.js'; diff --git a/test/mocks/logger.ts b/test/mocks/logger.ts index 00d88cc..046df68 100644 --- a/test/mocks/logger.ts +++ b/test/mocks/logger.ts @@ -26,5 +26,5 @@ export const logger: any = { log() {}, info() {}, warn() {}, - error() {} + error() {}, }; diff --git a/test/mocks/redis.ts b/test/mocks/redis.ts index bea2b0e..11e833d 100644 --- a/test/mocks/redis.ts +++ b/test/mocks/redis.ts @@ -21,12 +21,11 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import * as mock from 'mock-require'; -import { EventEmitter } from 'events'; -import * as crypto from 'crypto'; +import { EventEmitter } from 'node:events'; +import { createHash, type Hash } from 'node:crypto'; function sha1(str: string) { - let sha: crypto.Hash = crypto.createHash('sha1'); + const sha: Hash = createHash('sha1'); sha.update(str); return sha.digest('hex'); } @@ -71,7 +70,9 @@ export class RedisClientMock extends EventEmitter { RedisClientMock.__keys[key] !== undefined ) { const cb = args.pop(); - typeof cb === 'function' && cb(null, 0); + if (typeof cb === 'function') { + cb(null, 0); + } return true; } @@ -81,11 +82,15 @@ export class RedisClientMock extends EventEmitter { if (units === 'EX') { expire *= 1000; } - setTimeout(() => { delete RedisClientMock.__keys[key] }, expire); + setTimeout(() => { + delete RedisClientMock.__keys[key]; + }, expire); } const cb = args.pop(); - typeof cb === 'function' && cb(null, 1); + if (typeof cb === 'function') { + cb(null, 1); + } return true; } @@ -93,7 +98,9 @@ export class RedisClientMock extends EventEmitter { const [key] = args; const val = RedisClientMock.__keys[key]; const cb = args.pop(); - typeof cb === 'function' && cb(null, val); + if (typeof cb === 'function') { + cb(null, val); + } return val; } @@ -102,7 +109,7 @@ export class RedisClientMock extends EventEmitter { const self = RedisClientMock; const key = args.shift(); let result = 0; - if (/:watch:lock$/.test(key)) { + if (key.endsWith(':watch:lock')) { if (typeof self.__keys[key] === 'undefined') { self.__keys[key] = args.shift(); result = 1; @@ -129,12 +136,15 @@ export class RedisClientMock extends EventEmitter { const [key, timeout, cb] = args; const q = RedisClientMock.__queues__[key] || []; if (!q.length) { - this.__rt && clearTimeout(this.__rt); + if (this.__rt) { + clearTimeout(this.__rt); + } return new Promise(resolve => { - this.__rt = setTimeout(() => resolve(this.brpop( - key, timeout, cb, - )), timeout || 100); + this.__rt = setTimeout( + () => resolve(this.brpop(key, timeout, cb)), + timeout || 100, + ); }); } else { const result = [key, q.shift()]; @@ -149,23 +159,28 @@ export class RedisClientMock extends EventEmitter { from: string, to: string, timeout: number, - cb?: Function + cb?: Function, ): Promise { - const fromQ = RedisClientMock.__queues__[from] = - RedisClientMock.__queues__[from] || []; - const toQ = RedisClientMock.__queues__[to] = - RedisClientMock.__queues__[to] || []; + const fromQ = (RedisClientMock.__queues__[from] = + RedisClientMock.__queues__[from] || []); + const toQ = (RedisClientMock.__queues__[to] = + RedisClientMock.__queues__[to] || []); if (!fromQ.length) { - this.__rt && clearTimeout(this.__rt); + if (this.__rt) { + clearTimeout(this.__rt); + } return new Promise(resolve => { - this.__rt = setTimeout(() => resolve(this.brpoplpush( - from, to, timeout, cb, - )), timeout || 100); + this.__rt = setTimeout( + () => resolve(this.brpoplpush(from, to, timeout, cb)), + timeout || 100, + ); }); } else { toQ.push(fromQ.shift()); - cb && cb(null, '1'); + if (cb) { + cb(null, '1'); + } return '1'; } @@ -178,8 +193,8 @@ export class RedisClientMock extends EventEmitter { stop: number, cb?: Function, ): boolean { - const q = RedisClientMock.__queues__[key] = - RedisClientMock.__queues__[key] || []; + const q = (RedisClientMock.__queues__[key] = + RedisClientMock.__queues__[key] || []); const result = q.splice(start, stop); this.cbExecute(cb, null, result); return result; @@ -210,13 +225,17 @@ export class RedisClientMock extends EventEmitter { if (cmd === 'LOAD') { const hash = sha1(scriptOrHash); RedisClientMock.__scripts[hash] = scriptOrHash; - isCb && cb(null, hash); + if (isCb) { + cb(null, hash); + } return hash; } if (cmd === 'EXISTS') { const hash = RedisClientMock.__scripts[scriptOrHash] !== undefined; - isCb && cb(null, hash); + if (isCb) { + cb(null, hash); + } return [Number(hash)]; } @@ -233,13 +252,12 @@ export class RedisClientMock extends EventEmitter { if (cmd === 'LIST') { const result = Object.keys(self.__clientList) - .map((name: string, id: number) => `id=${id} name=${name}`) - .join('\n'); + .map((name: string, id: number) => `id=${id} name=${name}`) + .join('\n'); this.cbExecute(cb, null, result); return result; - } - else if (cmd === 'SETNAME') { + } else if (cmd === 'SETNAME') { this.__name = name; self.__clientList[name] = true; } @@ -291,7 +309,7 @@ export class RedisClientMock extends EventEmitter { const [key, score, value, cb] = args; const timeout = score - Date.now(); setTimeout(() => { - const toKey = key.split(/:/).slice(0,2).join(':'); + const toKey = key.split(/:/).slice(0, 2).join(':'); this.lpush(toKey, value); }, timeout); this.cbExecute(cb); @@ -320,13 +338,4 @@ export class RedisClientMock extends EventEmitter { } } -const Redis = RedisClientMock; - -mock('ioredis', { Redis, default: Redis }); - -// @ts-ignore -export * from 'ioredis'; - -export { Redis }; - -export default Redis; +export const Redis = RedisClientMock; diff --git a/test/src/client.ts b/test/src/client.spec.ts similarity index 71% rename from test/src/client.ts rename to test/src/client.spec.ts index fc465b3..fa20ed1 100644 --- a/test/src/client.ts +++ b/test/src/client.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import * as client from '../../src/client'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import * as client from '../../src/client.js'; describe('client', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('client'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.builder).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('client')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.builder, 'function'); }); }); diff --git a/test/src/client/generate.ts b/test/src/client/generate.spec.ts similarity index 71% rename from test/src/client/generate.ts rename to test/src/client/generate.spec.ts index dcda508..9424a9a 100644 --- a/test/src/client/generate.ts +++ b/test/src/client/generate.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/client/generate'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/client/generate.js'; describe('client generate', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('generate'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('generate')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/test/src/completions.ts b/test/src/completions.spec.ts similarity index 71% rename from test/src/completions.ts rename to test/src/completions.spec.ts index 24a9053..028a093 100644 --- a/test/src/completions.ts +++ b/test/src/completions.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import * as client from '../../src/completions'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import * as client from '../../src/completions.js'; describe('completions', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('completions'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.builder).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('completions')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.builder, 'function'); }); }); diff --git a/test/src/completions/off.ts b/test/src/completions/off.spec.ts similarity index 71% rename from test/src/completions/off.ts rename to test/src/completions/off.spec.ts index 3577e71..400fff1 100644 --- a/test/src/completions/off.ts +++ b/test/src/completions/off.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/completions/off'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/completions/off.js'; describe('completions off', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('off'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('off')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/test/src/completions/on.ts b/test/src/completions/on.spec.ts similarity index 71% rename from test/src/completions/on.ts rename to test/src/completions/on.spec.ts index 04047eb..03e617f 100644 --- a/test/src/completions/on.ts +++ b/test/src/completions/on.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/completions/on'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/completions/on.js'; describe('completions on', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('on'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('on')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/test/src/config.ts b/test/src/config.spec.ts similarity index 71% rename from test/src/config.ts rename to test/src/config.spec.ts index a9702bd..e0c709c 100644 --- a/test/src/config.ts +++ b/test/src/config.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import * as client from '../../src/config'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import * as client from '../../src/config.js'; describe('config', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('config'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.builder).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('config')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.builder, 'function'); }); }); diff --git a/test/src/config/check.ts b/test/src/config/check.spec.ts similarity index 71% rename from test/src/config/check.ts rename to test/src/config/check.spec.ts index 2fedd99..635f411 100644 --- a/test/src/config/check.ts +++ b/test/src/config/check.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as config from '../../../src/config/check'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as config from '../../../src/config/check.js'; describe('config check', () => { it('should be a valid command definition', () => { - expect(typeof config.command).equals('string'); - expect(config.command).contains('check'); - expect(typeof config.describe).equals('string'); - expect(config.describe).not.to.be.empty; - expect(typeof config.handler).equals('function'); + assert.equal(typeof config.command, 'string'); + assert.ok(config.command.includes('check')); + assert.equal(typeof config.describe, 'string'); + assert.notEqual(config.describe.length, 0); + assert.equal(typeof config.handler, 'function'); }); }); diff --git a/test/src/config/get.ts b/test/src/config/get.spec.ts similarity index 71% rename from test/src/config/get.ts rename to test/src/config/get.spec.ts index 28d13e8..34f37fc 100644 --- a/test/src/config/get.ts +++ b/test/src/config/get.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/config/get'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/config/get.js'; describe('config get', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('get'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('get')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/test/src/config/init.ts b/test/src/config/init.spec.ts similarity index 71% rename from test/src/config/init.ts rename to test/src/config/init.spec.ts index 4613a9b..a1ac625 100644 --- a/test/src/config/init.ts +++ b/test/src/config/init.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as config from '../../../src/config/init'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as config from '../../../src/config/init.js'; describe('config init', () => { it('should be a valid command definition', () => { - expect(typeof config.command).equals('string'); - expect(config.command).contains('init'); - expect(typeof config.describe).equals('string'); - expect(config.describe).not.to.be.empty; - expect(typeof config.handler).equals('function'); + assert.equal(typeof config.command, 'string'); + assert.ok(config.command.includes('init')); + assert.equal(typeof config.describe, 'string'); + assert.notEqual(config.describe.length, 0); + assert.equal(typeof config.handler, 'function'); }); }); diff --git a/test/src/config/set.ts b/test/src/config/set.spec.ts similarity index 71% rename from test/src/config/set.ts rename to test/src/config/set.spec.ts index e598ea5..736d768 100644 --- a/test/src/config/set.ts +++ b/test/src/config/set.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/config/set'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/config/set.js'; describe('config set', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('set'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('set')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/test/src/service.ts b/test/src/service.spec.ts similarity index 71% rename from test/src/service.ts rename to test/src/service.spec.ts index 2b5b8ad..1e0e11c 100644 --- a/test/src/service.ts +++ b/test/src/service.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../mocks'; -import { expect } from 'chai'; -import * as client from '../../src/service'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../mocks/index.js'; +import * as client from '../../src/service.js'; describe('service', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('service'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.builder).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('service')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.builder, 'function'); }); }); diff --git a/test/src/service/create.ts b/test/src/service/create.spec.ts similarity index 71% rename from test/src/service/create.ts rename to test/src/service/create.spec.ts index 99620a5..b42b7ec 100644 --- a/test/src/service/create.ts +++ b/test/src/service/create.spec.ts @@ -21,16 +21,17 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import '../../mocks'; -import { expect } from 'chai'; -import * as client from '../../../src/service/create'; +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import '../../mocks/index.js'; +import * as client from '../../../src/service/create.js'; describe('service create', () => { it('should be a valid command definition', () => { - expect(typeof client.command).equals('string'); - expect(client.command).contains('create'); - expect(typeof client.describe).equals('string'); - expect(client.describe).not.to.be.empty; - expect(typeof client.handler).equals('function'); + assert.equal(typeof client.command, 'string'); + assert.ok(client.command.includes('create')); + assert.equal(typeof client.describe, 'string'); + assert.notEqual(client.describe.length, 0); + assert.equal(typeof client.handler, 'function'); }); }); diff --git a/tsconfig.json b/tsconfig.json index 24914b9..beaa969 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,30 @@ { "compilerOptions": { - "module": "commonjs", + "target": "es2024", + "lib": ["es2024", "esnext.decorators"], + "moduleDetection": "force", + + "module": "nodenext", + "moduleResolution": "nodenext", + "resolveJsonModule": true, + "esModuleInterop": true, + "verbatimModuleSyntax": true, + + "types": ["node"], + + "isolatedModules": true, + "declaration": true, - "noImplicitAny": true, - "strictNullChecks": true, - "removeComments": false, - "noUnusedLocals": false, - "noUnusedParameters": false, - "moduleResolution": "node", "sourceMap": true, "inlineSources": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "target": "es2017", - "lib": [ - "dom", - "es2017" - ], - "allowSyntheticDefaultImports": true + "removeComments": false, + "newLine": "lf", + + "skipLibCheck": true, + + "strict": true, + "strictPropertyInitialization": false, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true } } From 288fcb382aa5eef6289dc070ca897463fad51584 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 08:54:12 +0200 Subject: [PATCH 02/12] fix: modernize service update-version detection and repair its bugs - service detection now resolves the package entry (exports map, main, index.js fallback) and loads it with dynamic import(), so both CJS and ESM services are supported - inheritance check walks the whole prototype chain instead of comparing only the direct parent class name - detection no longer stops at the first '*Service' export (e.g. a ServiceOptions export no longer hides the real service class) - working directory and console.log are now restored in finally: before, a detected service or a thrown import left the process chdir'ed into the service folder and/or console.log suppressed - spawn failures without stderr (e.g. ENOENT) no longer crash the reporter - containsServiceClass/resolveServiceEntry exported and covered with unit tests (11 new tests) --- src/service/update-version.ts | 116 +++++++++++++----- test/src/service/update-version.spec.ts | 153 ++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 33 deletions(-) create mode 100644 test/src/service/update-version.spec.ts diff --git a/src/service/update-version.ts b/src/service/update-version.ts index ece2403..44566ff 100644 --- a/src/service/update-version.ts +++ b/src/service/update-version.ts @@ -25,12 +25,10 @@ import { type Argv, type Arguments } from 'yargs'; import chalk from 'chalk'; import { printError } from '../../lib/index.js'; import { spawnSync, type SpawnSyncReturns } from 'child_process'; -import { resolve } from 'path'; -import { readdirSync } from 'fs'; +import { join, resolve } from 'path'; +import { readdirSync, readFileSync } from 'fs'; import { Console } from 'console'; -import { createRequire } from 'node:module'; - -const require = createRequire(import.meta.url); +import { pathToFileURL } from 'node:url'; const BASE_SERVICE_NAME = 'IMQService'; let PROGRAM: string = ''; @@ -41,38 +39,85 @@ let ROOT_DIRECTORY = process.cwd(); */ const logger = new Console(process.stdout, process.stderr); +/** + * Checks if any of the given module exports is a class derived (directly + * or transitively) from IMQService + * + * @param {object} moduleExports - loaded module namespace or exports object + * @returns {boolean} - true if a service class export is found + */ +export function containsServiceClass(moduleExports: object): boolean { + for (const [prop, exported] of Object.entries(moduleExports)) { + if (!prop.includes('Service') || typeof exported !== 'function') { + continue; + } + + let parent = Object.getPrototypeOf(exported); + + while (typeof parent === 'function' && parent.name) { + if (parent.name === BASE_SERVICE_NAME) { + return true; + } + + parent = Object.getPrototypeOf(parent); + } + } + + return false; +} + +/** + * Resolves the entry module of a package directory to a file URL, honoring + * the exports map when present and falling back to main / index.js + * + * @param {string} servicePath - path to directory, which contains service + * @returns {string | null} - entry file URL or null if not a package + */ +export function resolveServiceEntry(servicePath: string): string | null { + try { + const pkg = JSON.parse( + readFileSync(join(servicePath, 'package.json'), 'utf8'), + ); + const dot = pkg.exports?.['.']; + const entry = + (typeof dot === 'string' ? dot : (dot?.import ?? dot?.default)) ?? + pkg.main ?? + 'index.js'; + + return pathToFileURL(resolve(servicePath, entry)).href; + } catch { + return null; + } +} + /** * Checks if directory contains service * @param {string} servicePath - path to directory, which contains service - * @returns {boolean} - + * @returns {Promise} - * returns true if directory contains service, or false instead */ -function isFolderContainsService(servicePath: string): boolean { +async function isFolderContainsService(servicePath: string): Promise { + const entryUrl = resolveServiceEntry(servicePath); + + if (!entryUrl) { + return false; + } + const originalLogger = console.log; try { - console.log = () => {}; + console.log = () => undefined; process.chdir(servicePath); - const service = require(servicePath); - - for (const [prop, func] of Object.entries(service)) { - if (!prop.includes('Service')) { - continue; - } - - // noinspection TypeScriptUnresolvedVariable - return (func as any).__proto__.name === BASE_SERVICE_NAME; - } + const service = await import(entryUrl); + return containsServiceClass(service); + } catch { + return false; + } finally { + console.log = originalLogger; process.chdir(ROOT_DIRECTORY); - } catch (err) { - /* ignore */ } - - console.log = originalLogger; - - return false; } /** @@ -159,9 +204,15 @@ function gitPush(servicePath: string): SpawnSyncReturns { function handleSpawnResponse( response: SpawnSyncReturns, ): number | null { - if (response.status !== 0 || (response.error && response.stderr)) { + if (response.status !== 0 || response.error) { // noinspection TypeScriptValidateTypes - logger.log(chalk.red(response.stderr.toString())); + logger.log( + chalk.red( + response.stderr?.toString() || + response.error?.message || + `Command failed with status ${response.status}`, + ), + ); } return response.status; @@ -210,21 +261,20 @@ function execGitFlow(servicePath: string, args: Arguments): void { * Walks through folders and check if each folder contains service * * @param {string} path - path to root folder with services - * @returns {string[]} - array of folders with services + * @returns {Promise} - array of folders with services */ -function getServicesFolders(path: string): string[] { +async function getServicesFolders(path: string): Promise { const folders: string[] = []; path = resolve(path); // NOTE: Check if we call update-version from service folder - if (isFolderContainsService(path)) { + if (await isFolderContainsService(path)) { folders.push(path); } else { for (const dir of readdirSync(path)) { const pathToService = resolve(path, dir); - const containsService = isFolderContainsService(pathToService); - if (containsService) { + if (await isFolderContainsService(pathToService)) { folders.push(pathToService); } } @@ -257,9 +307,9 @@ export const { command, describe, builder, handler } = { .describe('path', 'Path to directory containing services.'); }, - handler(argv: Arguments) { + async handler(argv: Arguments) { try { - const folders = getServicesFolders(argv.path as string); + const folders = await getServicesFolders(argv.path as string); walkThroughFolders(folders, argv); } catch (err) { printError(err as Error); diff --git a/test/src/service/update-version.spec.ts b/test/src/service/update-version.spec.ts new file mode 100644 index 0000000..5758475 --- /dev/null +++ b/test/src/service/update-version.spec.ts @@ -0,0 +1,153 @@ +/*! + * I'm Queue Software Project + * Copyright (C) 2026 imqueue.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * If you want to use this code in a closed source (commercial) project, you can + * purchase a proprietary commercial license. Please contact us at + * to get commercial licensing options. + */ +import '../../mocks/index.js'; +import { after, before, describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import * as updateVersion from '../../../src/service/update-version.js'; + +const { containsServiceClass, resolveServiceEntry } = updateVersion; + +describe('service update-version', () => { + it('should be a valid command definition', () => { + assert.equal(typeof updateVersion.command, 'string'); + assert.ok(updateVersion.command.includes('update-version')); + assert.equal(typeof updateVersion.describe, 'string'); + assert.equal(typeof updateVersion.handler, 'function'); + }); + + describe('containsServiceClass()', () => { + class IMQService {} + class DirectService extends IMQService {} + class Intermediate extends IMQService {} + class DeepService extends Intermediate {} + class UnrelatedService {} + + it('should detect a direct IMQService subclass', () => { + assert.equal(containsServiceClass({ DirectService }), true); + }); + + it('should detect a transitive IMQService subclass', () => { + assert.equal(containsServiceClass({ DeepService }), true); + }); + + it('should keep scanning past non-service *Service exports', () => { + assert.equal( + containsServiceClass({ + ServiceOptions: { some: 'object' }, + UnrelatedService, + DirectService, + }), + true, + ); + }); + + it('should return false when nothing derives IMQService', () => { + assert.equal( + containsServiceClass({ + UnrelatedService, + helper: () => undefined, + CONSTANT: 42, + }), + false, + ); + }); + + it('should ignore non-Service-named exports', () => { + assert.equal( + containsServiceClass({ Something: DirectService }), + false, + ); + }); + }); + + describe('resolveServiceEntry()', () => { + let dir: string; + + before(() => { + dir = mkdtempSync(join(tmpdir(), 'imq-cli-test-')); + }); + after(() => { + rmSync(dir, { recursive: true, force: true }); + }); + + function pkgDir(name: string, pkg: object): string { + const path = join(dir, name); + + mkdirSync(path, { recursive: true }); + writeFileSync(join(path, 'package.json'), JSON.stringify(pkg)); + + return path; + } + + it('should return null for a non-package directory', () => { + const path = join(dir, 'not-a-package'); + + mkdirSync(path, { recursive: true }); + + assert.equal(resolveServiceEntry(path), null); + }); + + it('should resolve via main field', () => { + const path = pkgDir('with-main', { main: 'lib/entry.js' }); + const entry = resolveServiceEntry(path); + + assert.ok(entry); + assert.equal(fileURLToPath(entry), join(path, 'lib', 'entry.js')); + }); + + it('should prefer the exports map over main', () => { + const path = pkgDir('with-exports', { + main: 'wrong.js', + exports: { '.': { import: './right.js' } }, + }); + + assert.equal( + fileURLToPath(resolveServiceEntry(path) as string), + join(path, 'right.js'), + ); + }); + + it('should support a string-valued exports dot entry', () => { + const path = pkgDir('with-string-exports', { + exports: { '.': './entry.mjs' }, + }); + + assert.equal( + fileURLToPath(resolveServiceEntry(path) as string), + join(path, 'entry.mjs'), + ); + }); + + it('should fall back to index.js without main or exports', () => { + const path = pkgDir('bare', { name: 'bare' }); + + assert.equal( + fileURLToPath(resolveServiceEntry(path) as string), + join(path, 'index.js'), + ); + }); + }); +}); From 0670c0d90fdb9969cb6e1a515f91ab89a5f07dde Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:17:00 +0200 Subject: [PATCH 03/12] chore: drop unused direct @imqueue/core dependency Nothing in the cli imports @imqueue/core directly; it remains available transitively through @imqueue/rpc. --- package-lock.json | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03b22c1..71089aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "3.0.0", "license": "GPL-3.0-only", "dependencies": { - "@imqueue/core": "^3.2.1", "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", "@octokit/rest": "^22.0.1", diff --git a/package.json b/package.json index 875a8d5..ef06526 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "author": "imqueue.com (https://imqueue.com)", "license": "GPL-3.0-only", "dependencies": { - "@imqueue/core": "^3.2.1", "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", "@octokit/rest": "^22.0.1", From 8e7b57db2d7538575e8df353eae0d50a9a74a77d Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:19:50 +0200 Subject: [PATCH 04/12] chore: replace dotenv with native process.loadEnvFile() Node 22 loads .env files natively; the only dotenv usage was the (live-API, skipped) github spec. loadEnvFile() throws when no .env exists, so it is wrapped to keep dotenv's silent no-op semantics. --- package-lock.json | 13 ------------- package.json | 1 - test/lib/github.spec.ts | 8 ++++++-- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 71089aa..4202c6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@octokit/rest": "^22.0.1", "chalk": "^5.4.1", "command-exists": "^1.2.9", - "dotenv": "^17.0.0", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "node-rsa": "^1.1.1", @@ -1793,18 +1792,6 @@ "node": ">=0.10" } }, - "node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", diff --git a/package.json b/package.json index ef06526..f079c2b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@octokit/rest": "^22.0.1", "chalk": "^5.4.1", "command-exists": "^1.2.9", - "dotenv": "^17.0.0", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "node-rsa": "^1.1.1", diff --git a/test/lib/github.spec.ts b/test/lib/github.spec.ts index 8c6b74a..b63654f 100644 --- a/test/lib/github.spec.ts +++ b/test/lib/github.spec.ts @@ -26,9 +26,13 @@ import assert from 'node:assert/strict'; import '../mocks/index.js'; import { randomUUID as uuid } from 'node:crypto'; import * as github from '../../lib/github.js'; -import { config as envConfig } from 'dotenv'; -envConfig(); +try { + // native replacement for dotenv; throws when no .env file exists + process.loadEnvFile(); +} catch { + /* no .env file - rely on the process environment */ +} describe.skip('github', () => { const token = String(process.env.GITHUB_AUTH_TOKEN); From afb0d2966d710661e1048a1dc1940c8bcd39ea34 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:28:38 +0200 Subject: [PATCH 05/12] chore: replace chalk, node-rsa, word-wrap and command-exists with native code - chalk -> util.styleText (respects NO_COLOR/FORCE_COLOR natively) - node-rsa -> crypto.publicEncrypt with RSA_PKCS1_PADDING (same RSAES-PKCS1-v1_5 scheme travis expects) - word-wrap -> small native paragraph-aware wrap() implementation - command-exists -> native probe in lib/node.ts (command -v / where); the IMQ_CLI_MISSING_COMMANDS env var replaces the module mock as the test seam, and the command-exists module mock is gone from test setup Runtime deps are now rpc, travis, octokit, inquirer(+autocomplete), semver and yargs. --- lib/error.ts | 6 +-- lib/node.ts | 33 ++++++++++++++ lib/template.ts | 25 ++++++++--- lib/travis.ts | 16 ++++--- package-lock.json | 59 ------------------------- package.json | 6 --- src/client/generate.ts | 8 ++-- src/completions/off.ts | 8 ++-- src/completions/on.ts | 15 ++++--- src/config/get.ts | 17 +++++--- src/config/init.ts | 81 ++++++++++++++++++++++++----------- src/config/set.ts | 10 ++--- src/service/create.ts | 15 +++---- src/service/update-version.ts | 9 ++-- test/lib/template.spec.ts | 6 +-- test/mocks/command-exists.ts | 30 ------------- test/mocks/index.ts | 5 --- 17 files changed, 168 insertions(+), 181 deletions(-) delete mode 100644 test/mocks/command-exists.ts diff --git a/lib/error.ts b/lib/error.ts index d07b18a..651b339 100644 --- a/lib/error.ts +++ b/lib/error.ts @@ -21,7 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import chalk from 'chalk'; +import { styleText } from 'node:util'; // that is just a printing function, no need to do specific tests // istanbul ignore next @@ -46,9 +46,9 @@ export function printError(err: Error, withStackTrace: boolean = false) { /* ignore */ } - process.stderr.write(chalk.bold.red(message) + '\n'); + process.stderr.write(styleText(['bold', 'red'], message) + '\n'); if (withStackTrace && err.stack) { - process.stderr.write(chalk.cyan(err.stack) + '\n'); + process.stderr.write(styleText('cyan', err.stack) + '\n'); } } diff --git a/lib/node.ts b/lib/node.ts index 295a120..e54bc59 100644 --- a/lib/node.ts +++ b/lib/node.ts @@ -21,9 +21,42 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { spawnSync } from 'node:child_process'; import * as semver from 'semver'; +const RX_COMMAND_NAME = /^[\w.-]+$/; const RX_VERSION_CLEAN = /^v/; + +// noinspection JSUnusedGlobalSymbols +/** + * Checks if the given executable is available on this system. Replaces the + * command-exists package with a native probe. The IMQ_CLI_MISSING_COMMANDS + * environment variable (comma-separated command names) forces a negative + * answer and serves as a test seam. + * + * @param {string} command - executable name to look up + * @return {boolean} + */ +export function commandExists(command: string): boolean { + const missing = process.env.IMQ_CLI_MISSING_COMMANDS; + + if (missing && missing.split(',').includes(command)) { + return false; + } + + if (!RX_COMMAND_NAME.test(command)) { + return false; + } + + const probe = + process.platform === 'win32' + ? spawnSync('where', [command], { stdio: 'ignore' }) + : spawnSync('sh', ['-c', `command -v -- ${command}`], { + stdio: 'ignore', + }); + + return probe.status === 0; +} const RX_ESCAPE = /\./g; let nodeVersions: NodeVersion[]; diff --git a/lib/template.ts b/lib/template.ts index de5d4b9..53a7a01 100644 --- a/lib/template.ts +++ b/lib/template.ts @@ -22,7 +22,6 @@ * to get commercial licensing options. */ import inquirer from 'inquirer'; -import { createRequire } from 'node:module'; import { TPL_HOME, CUSTOM_TPL_HOME, @@ -32,10 +31,7 @@ import { } from './index.js'; import * as fs from 'fs'; import { execSync } from 'child_process'; - -const require = createRequire(import.meta.url); -const commandExists = require('command-exists').sync; -const wordWrap = require('word-wrap'); +import { commandExists } from './node.js'; /** * Wraps words of given text to match given char width, using given indentation @@ -46,7 +42,24 @@ const wordWrap = require('word-wrap'); * @return {string} */ export function wrap(text: string, width = 80, indent = '') { - return wordWrap(text, { width, indent }); + const lines: string[] = []; + + for (const paragraph of String(text).split('\n')) { + let line = ''; + + for (const word of paragraph.split(/\s+/).filter(Boolean)) { + if (line && line.length + 1 + word.length > width) { + lines.push(line); + line = word; + } else { + line = line ? `${line} ${word}` : word; + } + } + + lines.push(line); + } + + return lines.map(line => indent + line).join('\n'); } /** diff --git a/lib/travis.ts b/lib/travis.ts index 8238921..82d67d4 100644 --- a/lib/travis.ts +++ b/lib/travis.ts @@ -21,8 +21,8 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import NodeRSA from 'node-rsa'; import { TravisClient } from '@imqueue/travis'; +import { constants as cryptoConstants, publicEncrypt } from 'node:crypto'; import { sleep } from './node.js'; /** @@ -48,12 +48,16 @@ export async function travisEncrypt( const [owner, repo] = repository.split('/'); const pem = await travis.repos(owner, repo).key.get(); - const rsa = new NodeRSA(); - rsa.setOptions({ encryptionScheme: 'pkcs1' }); - rsa.importKey(pem.key); - - return rsa.encrypt(Buffer.from(data, 'utf8'), 'base64'); + // travis expects RSAES-PKCS1-v1_5 encryption with the repository + // public key (what node-rsa's encryptionScheme: 'pkcs1' produced) + return publicEncrypt( + { + key: pem.key, + padding: cryptoConstants.RSA_PKCS1_PADDING, + }, + Buffer.from(data, 'utf8'), + ).toString('base64'); } // istanbul ignore next diff --git a/package-lock.json b/package-lock.json index 4202c6b..d3c484e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,13 +12,9 @@ "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", "@octokit/rest": "^22.0.1", - "chalk": "^5.4.1", - "command-exists": "^1.2.9", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", - "node-rsa": "^1.1.1", "semver": "^7.7.2", - "word-wrap": "^1.2.5", "yargs": "^17.7.2" }, "bin": { @@ -28,11 +24,9 @@ "imqup": "bin/updep.sh" }, "devDependencies": { - "@types/command-exists": "^1.2.3", "@types/inquirer": "^8.2.12", "@types/inquirer-autocomplete-prompt": "^1.3.5", "@types/node": "^24.9.1", - "@types/node-rsa": "^1.1.4", "@types/semver": "^7.7.0", "@types/yargs": "^17.0.33", "oxfmt": "0.57.0", @@ -964,13 +958,6 @@ "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", "license": "MIT" }, - "node_modules/@types/command-exists": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.3.tgz", - "integrity": "sha512-PpbaE2XWLaWYboXD6k70TcXO/OdOyyRFq5TVpmlUELNxdkkmXU9fkImNosmXU1DtsNrqdUgWd/nJQYXgwmtdXQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/inquirer": { "version": "8.2.13", "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.13.tgz", @@ -1001,16 +988,6 @@ "undici-types": "~7.18.0" } }, - "node_modules/@types/node-rsa": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/node-rsa/-/node-rsa-1.1.4.tgz", - "integrity": "sha512-dB0ECel6JpMnq5ULvpUTunx3yNm8e/dIkv8Zu9p2c8me70xIRUUG3q+qXRwcSf9rN3oqamv4116iHy90dJGRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/request": { "version": "2.48.13", "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", @@ -1578,18 +1555,6 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "license": "Apache-2.0" }, - "node_modules/chalk": { - "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" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/chardet": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", @@ -1708,12 +1673,6 @@ "node": ">= 0.8" } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "license": "MIT" - }, "node_modules/content-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", @@ -2450,15 +2409,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "license": "ISC" }, - "node_modules/node-rsa": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", - "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", - "license": "MIT", - "dependencies": { - "asn1": "^0.2.4" - } - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -3061,15 +3011,6 @@ "defaults": "^1.0.3" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", diff --git a/package.json b/package.json index f079c2b..ba1d7e8 100644 --- a/package.json +++ b/package.json @@ -42,22 +42,16 @@ "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", "@octokit/rest": "^22.0.1", - "chalk": "^5.4.1", - "command-exists": "^1.2.9", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", - "node-rsa": "^1.1.1", "semver": "^7.7.2", - "word-wrap": "^1.2.5", "yargs": "^17.7.2" }, "preferGlobal": true, "devDependencies": { - "@types/command-exists": "^1.2.3", "@types/inquirer": "^8.2.12", "@types/inquirer-autocomplete-prompt": "^1.3.5", "@types/node": "^24.9.1", - "@types/node-rsa": "^1.1.4", "@types/semver": "^7.7.0", "@types/yargs": "^17.0.33", "oxfmt": "0.57.0", diff --git a/src/client/generate.ts b/src/client/generate.ts index b1c0c72..37cc0f3 100644 --- a/src/client/generate.ts +++ b/src/client/generate.ts @@ -21,12 +21,12 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Argv, type Arguments } from 'yargs'; import { IMQClient } from '@imqueue/rpc'; import * as fs from 'fs'; import * as p from 'path'; import inquirer, { type QuestionCollection } from 'inquirer'; -import chalk from 'chalk'; import { printError } from '../../lib/index.js'; // noinspection JSUnusedGlobalSymbols @@ -59,7 +59,7 @@ export const { command, describe, builder, promptOverride, handler } = { if (!write) { process.stdout.write( - chalk.yellow('File exists, overwrite disabled, exit...'), + styleText('yellow', 'File exists, overwrite disabled, exit...'), ); process.exit(0); } @@ -81,8 +81,8 @@ export const { command, describe, builder, promptOverride, handler } = { }); process.stdout.write( - chalk.green('Successfully created. Path: ') + - chalk.cyan(filePath) + + styleText('green', 'Successfully created. Path: ') + + styleText('cyan', filePath) + '\n', ); } catch (err) { diff --git a/src/completions/off.ts b/src/completions/off.ts index 04eec35..7595621 100644 --- a/src/completions/off.ts +++ b/src/completions/off.ts @@ -21,6 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Argv } from 'yargs'; import { existsSync as exists, @@ -28,7 +29,6 @@ import { writeFileSync as write, } from 'fs'; import { resolve, printError, IS_ZSH } from '../../lib/index.js'; -import chalk from 'chalk'; let PROGRAM: string = ''; let RX_REPLACE: RegExp; @@ -42,12 +42,12 @@ let RX_REPLACE: RegExp; */ function printSuccess(rcFilename: string) { process.stdout.write( - chalk.green('Completions removed from ') + - chalk.cyan(`${rcFilename}`) + + styleText('green', 'Completions removed from ') + + styleText('cyan', `${rcFilename}`) + '\n' + 'To have these changes to take effect, please, run:\n\n' + ' $ ' + - chalk.cyan(`source ${rcFilename}`) + + styleText('cyan', `source ${rcFilename}`) + '\n\n', ); } diff --git a/src/completions/on.ts b/src/completions/on.ts index 9fd8fdb..b964f9e 100644 --- a/src/completions/on.ts +++ b/src/completions/on.ts @@ -21,6 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Argv } from 'yargs'; import { existsSync as exists, @@ -28,7 +29,6 @@ import { readFileSync as read, } from 'fs'; import { resolve, touch, printError, IS_ZSH } from '../../lib/index.js'; -import chalk from 'chalk'; let PROGRAM: string = ''; let RX_EXISTS: RegExp; @@ -42,12 +42,12 @@ let RX_EXISTS: RegExp; */ function printAdded(rcFilename: string) { process.stdout.write( - chalk.green(`Completion script added to `) + - chalk.cyan(rcFilename) + + styleText('green', `Completion script added to `) + + styleText('cyan', rcFilename) + '\n' + 'To have these changes to take effect, please, run:\n\n' + ' $ ' + - chalk.cyan(`source ${rcFilename}`) + + styleText('cyan', `source ${rcFilename}`) + '\n\n', ); } @@ -86,13 +86,14 @@ complete -F _yargs_completions ${PROGRAM} */ function printExists(rcFilename: string) { process.stdout.write( - chalk.yellow.bold( + styleText( + ['bold', 'yellow'], `Completion script already exists in your ${rcFilename}.`, ) + '\n' + 'If it does not work, please try one of:\n\n' + - chalk.cyan(' 1. Reload your shell\n') + - chalk.cyan(` 2. Run source ${rcFilename}\n\n`), + styleText('cyan', ' 1. Reload your shell\n') + + styleText('cyan', ` 2. Run source ${rcFilename}\n\n`), ); } diff --git a/src/config/get.ts b/src/config/get.ts index 8f57b3e..7f38cf5 100644 --- a/src/config/get.ts +++ b/src/config/get.ts @@ -21,8 +21,8 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Argv, type Arguments } from 'yargs'; -import chalk from 'chalk'; import { printError, loadConfig } from '../../lib/index.js'; let PROGRAM: string = ''; @@ -57,11 +57,12 @@ export const { command, describe, builder, handler } = { if (!options.length) { return process.stdout.write( - chalk.bold.yellow( + styleText( + ['bold', 'yellow'], 'Config is empty. Try to init if first by running:', ) + '\n\n $ ' + - chalk.cyan(`${PROGRAM} config init`) + + styleText('cyan', `${PROGRAM} config init`) + '\n\n', ); } @@ -72,19 +73,21 @@ export const { command, describe, builder, handler } = { ); } - process.stdout.write(chalk.bold.green('IMQ CLI Config:') + '\n'); + process.stdout.write( + styleText(['bold', 'green'], 'IMQ CLI Config:') + '\n', + ); if ((argv as any).json) { return process.stdout.write( - chalk.cyan(JSON.stringify(config, null, 2)) + '\n', + styleText('cyan', JSON.stringify(config, null, 2)) + '\n', ); } for (let option of options) { process.stdout.write( - chalk.yellow(`${option}`) + + styleText('yellow', `${option}`) + ' = ' + - chalk.cyan(JSON.stringify(config[option])) + + styleText('cyan', JSON.stringify(config[option])) + '\n', ); } diff --git a/src/config/init.ts b/src/config/init.ts index 20bc5e3..4da8f9b 100644 --- a/src/config/init.ts +++ b/src/config/init.ts @@ -21,6 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import * as originalInquirer from 'inquirer'; import { CONFIG_PATH, @@ -35,7 +36,6 @@ import { loadTemplate, licensingOptions, } from '../../lib/index.js'; -import chalk from 'chalk'; import * as fs from 'fs'; const inquirer = originalInquirer as unknown as typeof originalInquirer.default; @@ -149,7 +149,8 @@ export async function templateOptions(config: IMQCLIConfig) { if (templates[tplName]) { config.template = templates[tplName]; return console.log( - chalk.green( + styleText( + 'green', `New services set to be created from template "${ tplName }" (${config.template})`, @@ -183,7 +184,8 @@ export async function versionSystemOptions( config.useGit = true; console.log( - chalk.cyan( + styleText( + 'cyan', wrap( '\nTo publish git repository you need to provide base url ' + 'where your git repositories published to. It is recommended ' + @@ -206,13 +208,15 @@ export async function versionSystemOptions( ]); if (!/^[-_a-z0-9]+$/i.test(answer.url)) { - console.log(chalk.red('Wrong user or organization name.')); + console.log(styleText('red', 'Wrong user or organization name.')); return await versionSystemOptions(config); } config.gitBaseUrl = `git@github.com:${answer.url}`; - console.log(chalk.green(`Base git URL is set to "${config.gitBaseUrl}"`)); + console.log( + styleText('green', `Base git URL is set to "${config.gitBaseUrl}"`), + ); answer = await inquirer.prompt<{ saveGitHubToken: boolean }>([ { @@ -230,7 +234,8 @@ export async function versionSystemOptions( } console.log( - chalk.cyan( + styleText( + 'cyan', wrap( 'To make GitHub integration work you must provide a valid token ' + 'which grants permission to create repository for a specified ' + @@ -250,7 +255,8 @@ export async function versionSystemOptions( if (!answer.gitHubAuthToken.trim()) { console.log( - chalk.red( + styleText( + 'red', 'Given token is empty, you will be prompted to enter it on ' + 'service create command', ), @@ -261,7 +267,9 @@ export async function versionSystemOptions( config.gitHubAuthToken = answer.gitHubAuthToken.trim(); - console.log(chalk.green('GitHub auth token stored in local config file')); + console.log( + styleText('green', 'GitHub auth token stored in local config file'), + ); answer = await inquirer.prompt<{ isPrivate: boolean }>([ { @@ -276,7 +284,8 @@ export async function versionSystemOptions( config.gitRepoPrivate = answer.isPrivate; console.log( - chalk.green( + styleText( + 'green', `Service on GitHub will be created as ${ config.gitRepoPrivate ? 'private' : 'public' } repository.`, @@ -295,14 +304,17 @@ export async function authorName(config: IMQCLIConfig): Promise { ]); if (!answer.author.trim()) { - console.log(chalk.red(`Given name is invalid, please, try again.`)); + console.log( + styleText('red', `Given name is invalid, please, try again.`), + ); return await authorName(config); } config.author = answer.author.trim(); console.log( - chalk.green( + styleText( + 'green', `Auto-generated code will be authored by "${config.author}"`, ), ); @@ -319,14 +331,17 @@ export async function authorEmail(config: IMQCLIConfig) { ]); if (!/^[-a-z0-9.]+@[-a-z0-9.]+$/i.test(answer.email.trim())) { - console.log(chalk.red(`Given email is invalid, please, try again.`)); + console.log( + styleText('red', `Given email is invalid, please, try again.`), + ); return await authorName(config); } config.email = answer.email.trim(); console.log( - chalk.green( + styleText( + 'green', `Generated code will be referred to given contact: ${config.email}`, ), ); @@ -358,14 +373,20 @@ export async function dockerCredentials(config: IMQCLIConfig): Promise { if (!answer.dockerHubUser.trim()) { console.log( - chalk.red('Given docker hub user name is empty, please try again'), + styleText( + 'red', + 'Given docker hub user name is empty, please try again', + ), ); return dockerCredentials(config); } if (!answer.dockerHubPassword.trim()) { console.log( - chalk.red('Given docker hub password is empty, please try again'), + styleText( + 'red', + 'Given docker hub password is empty, please try again', + ), ); return dockerCredentials(config); } @@ -374,7 +395,10 @@ export async function dockerCredentials(config: IMQCLIConfig): Promise { config.dockerHubPassword = answer.dockerHubPassword.trim(); console.log( - chalk.green('Docker hub credentials saved in a local config file.'), + styleText( + 'green', + 'Docker hub credentials saved in a local config file.', + ), ); } @@ -404,7 +428,8 @@ export async function dockerQuestions(config: IMQCLIConfig): Promise { if (!answer.dockerHubNamespace.trim()) { console.log( - chalk.red( + styleText( + 'red', 'Given docker hub namespace is invalid, please, try again...', ), ); @@ -441,7 +466,8 @@ export async function serviceQuestions(config: IMQCLIConfig) { config.license = id; console.log( - chalk.green( + styleText( + 'green', `Selected "${name}" to be a license for IMQ generated code and services`, ), ); @@ -459,8 +485,11 @@ export const { command, describe, handler } = { try { if (!configEmpty()) { process.stdout.write( - chalk.bold.yellow('Config already initialized, path: ') + - chalk.cyan(CONFIG_PATH) + + styleText( + ['bold', 'yellow'], + 'Config already initialized, path: ', + ) + + styleText('cyan', CONFIG_PATH) + '\n', ); @@ -479,7 +508,8 @@ export const { command, describe, handler } = { } console.log( - chalk.cyan( + styleText( + 'cyan', wrap( "Let's define global config options " + 'for IMQ command line runs. These options will be used as ' + @@ -490,21 +520,24 @@ export const { command, describe, handler } = { ); console.log( - chalk.yellow( + styleText( + 'yellow', wrap( '- You can skip this step by pressing ' + '[^C].\n- You can proceed to this step later by running:', ), ), ); - console.log(chalk.magenta('\n $ imq config init\n')); + console.log(styleText('magenta', '\n $ imq config init\n')); const config = loadConfig(); await serviceQuestions(config); saveConfig(config); - console.log(chalk.magenta('IMQ-CLI successfully configured!')); + console.log( + styleText('magenta', 'IMQ-CLI successfully configured!'), + ); } catch (err) { printError(err as Error); console.error(err); diff --git a/src/config/set.ts b/src/config/set.ts index f50f349..08cdee5 100644 --- a/src/config/set.ts +++ b/src/config/set.ts @@ -21,8 +21,8 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Arguments } from 'yargs'; -import chalk from 'chalk'; import { printError, loadConfig, @@ -45,10 +45,10 @@ export const { command, describe, handler } = { saveConfig(config); process.stdout.write( - chalk.green('Option ') + - chalk.cyan(`${(argv as any).option}`) + - chalk.green(' is set to ') + - chalk.cyan(`${(argv as any).value}`) + + styleText('green', 'Option ') + + styleText('cyan', `${(argv as any).option}`) + + styleText('green', ' is set to ') + + styleText('cyan', `${(argv as any).value}`) + '\n', ); } catch (err) { diff --git a/src/service/create.ts b/src/service/create.ts index aa1d9b5..d8814b5 100644 --- a/src/service/create.ts +++ b/src/service/create.ts @@ -21,15 +21,15 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import * as path from 'path'; import { type Argv } from 'yargs'; import * as fs from 'fs'; import * as os from 'os'; -import chalk from 'chalk'; import * as semver from 'semver'; import inquirer, { type QuestionCollection } from 'inquirer'; -import { createRequire } from 'node:module'; import { + commandExists, type IMQCLIConfig, loadConfig, printError, @@ -55,8 +55,6 @@ import { } from '../../lib/index.js'; import { execSync } from 'child_process'; -const require = createRequire(import.meta.url); -const commandExists = require('command-exists').sync; const DEFAULT_SERVICE_VERSION = '1.0.0-0'; let config: IMQCLIConfig; @@ -506,7 +504,8 @@ async function enableTravisBuilds(argv: any) { if (!enabled) { // noinspection TypeScriptValidateJSTypes console.log( - (chalk as any).red( + styleText( + 'red', 'There was a problem enabling builds for this service. Please ' + 'go to http://travis-ci.org/ and enable builds manually.', ), @@ -813,7 +812,7 @@ async function createGitRepo(argv: any) { // istanbul ignore next async function installPackages(argv: any) { - if (!commandExists('npm' as any)) { + if (!commandExists('npm')) { throw new Error('npm command is not installed!'); } @@ -859,7 +858,7 @@ async function commit(argv: any) { process.chdir(path); - if (!commandExists('git' as any)) { + if (!commandExists('git')) { throw new Error('Git command expected, but is not installed!'); } @@ -1008,7 +1007,7 @@ export const { command, describe, builder, handler } = { } // noinspection TypeScriptValidateJSTypes - console.log((chalk as any).green('Service successfully created!')); + console.log(styleText('green', 'Service successfully created!')); } catch (err) { if (argv.path && !~['', '.', './'].indexOf(argv.path.trim())) { // cleanup service dir diff --git a/src/service/update-version.ts b/src/service/update-version.ts index 44566ff..e12a9c2 100644 --- a/src/service/update-version.ts +++ b/src/service/update-version.ts @@ -21,8 +21,8 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ +import { styleText } from 'node:util'; import { type Argv, type Arguments } from 'yargs'; -import chalk from 'chalk'; import { printError } from '../../lib/index.js'; import { spawnSync, type SpawnSyncReturns } from 'child_process'; import { join, resolve } from 'path'; @@ -130,7 +130,7 @@ async function isFolderContainsService(servicePath: string): Promise { function walkThroughFolders(paths: string[], args: Arguments) { for (const path of paths) { // noinspection TypeScriptValidateTypes - logger.log(chalk.blue('\nService:', path)); + logger.log(styleText('blue', `\nService: ${path}`)); execGitFlow(path, args); } } @@ -207,7 +207,8 @@ function handleSpawnResponse( if (response.status !== 0 || response.error) { // noinspection TypeScriptValidateTypes logger.log( - chalk.red( + styleText( + 'red', response.stderr?.toString() || response.error?.message || `Command failed with status ${response.status}`, @@ -254,7 +255,7 @@ function execGitFlow(servicePath: string, args: Arguments): void { return; } // noinspection TypeScriptValidateTypes - logger.log(chalk.green('Done!')); + logger.log(styleText('green', 'Done!')); } /** diff --git a/test/lib/template.spec.ts b/test/lib/template.spec.ts index 6da7bc2..7ef16b3 100644 --- a/test/lib/template.spec.ts +++ b/test/lib/template.spec.ts @@ -73,19 +73,19 @@ describe('template', () => { describe('checkGit()', () => { after(() => { - (global).checkGitResult = true; + delete process.env.IMQ_CLI_MISSING_COMMANDS; }); it('should be a function', () => { assert.equal(typeof checkGit, 'function'); }); it('should not throw if git command exists', () => { - (global).checkGitResult = true; + delete process.env.IMQ_CLI_MISSING_COMMANDS; assert.doesNotThrow(() => checkGit()); }); it('should throw if git command does not exist', () => { - (global).checkGitResult = false; + process.env.IMQ_CLI_MISSING_COMMANDS = 'git'; assert.throws(() => checkGit()); }); }); diff --git a/test/mocks/command-exists.ts b/test/mocks/command-exists.ts deleted file mode 100644 index 5874560..0000000 --- a/test/mocks/command-exists.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*! - * IMQ-CLI Unit Test Mocks: command-exists - * - * I'm Queue Software Project - * Copyright (C) 2025 imqueue.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * If you want to use this code in a closed source (commercial) project, you can - * purchase a proprietary commercial license. Please contact us at - * to get commercial licensing options. - */ -(global as any).checkGitResult = true; - -export function commandExistsMock(): boolean { - return (global as any).checkGitResult; -} - -(commandExistsMock as any).sync = commandExistsMock; diff --git a/test/mocks/index.ts b/test/mocks/index.ts index 4b73434..8aab40d 100644 --- a/test/mocks/index.ts +++ b/test/mocks/index.ts @@ -25,15 +25,10 @@ process.env.IMQ_CLI_HOME = '/tmp'; const { mock } = await import('node:test'); -const { commandExistsMock } = await import('./command-exists.js'); const { Redis } = await import('./redis.js'); // preloaded via `node --import ./test/mocks/index.js` so mocks are // registered before any test file graph links (see package.json scripts) -mock.module('command-exists', { - cache: false, - defaultExport: commandExistsMock, -}); mock.module('ioredis', { cache: false, defaultExport: { From f13a149d8d07a418f60bbf36334a1aad1864ea35 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:34:03 +0200 Subject: [PATCH 06/12] chore: replace @octokit/rest with a native fetch GitHub client The cli uses four GitHub endpoints (org info, org teams, repo lookup, repo creation in org), now served by a ~60-line fetch client with bearer auth, api-version pinning and GithubApiError carrying the HTTP status. Exported function signatures (getInstance/getTeam/getOrg/ createRepository) are unchanged. Adds 12 offline specs exercising the client against a stubbed fetch (auth header, error mapping, the already-exists and non-404 rethrow flows); live specs stay skipped. --- lib/github.ts | 117 ++++++++++++++++++++---- package-lock.json | 187 -------------------------------------- package.json | 1 - test/lib/github.spec.ts | 192 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 284 insertions(+), 213 deletions(-) diff --git a/lib/github.ts b/lib/github.ts index a18b271..ad9b385 100644 --- a/lib/github.ts +++ b/lib/github.ts @@ -2,7 +2,7 @@ * IMQ-CLI library: github * * I'm Queue Software Project - * Copyright (C) 2025 imqueue.com + * Copyright (C) 2026 imqueue.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,10 +21,90 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { Octokit as Github } from '@octokit/rest'; - +const GITHUB_API_URL = 'https://api.github.com'; const RX_DEPRECATION = /Deprecation:/; +/** + * Error thrown for non-successful GitHub API responses, carrying the HTTP + * status code of the response + */ +export class GithubApiError extends Error { + public constructor( + message: string, + public readonly status: number, + ) { + super(message); + this.name = 'GithubApiError'; + } +} + +/** + * Minimal GitHub REST v3 client over native fetch, covering the few + * endpoints this cli uses (replaces @octokit/rest) + */ +export class Github { + public constructor(private readonly token: string) { + if (!token) { + throw new TypeError( + 'Github auth token required, but was not given!', + ); + } + } + + /** + * Performs a GitHub API request and returns the parsed JSON body. + * Throws GithubApiError with the response status on non-2xx replies. + * + * @param {string} method - HTTP method to use + * @param {string} path - API path, e.g. '/repos/{owner}/{repo}' + * @param {object} [body] - JSON-serializable request payload + * @return {Promise} + */ + public async request( + method: string, + path: string, + body?: object, + ): Promise { + const res = await fetch(`${GITHUB_API_URL}${path}`, { + method, + headers: { + accept: 'application/vnd.github+json', + authorization: `Bearer ${this.token}`, + 'user-agent': '@imqueue/cli', + 'x-github-api-version': '2022-11-28', + ...(body ? { 'content-type': 'application/json' } : {}), + }, + ...(body ? { body: JSON.stringify(body) } : {}), + }); + + const data = + res.status === 204 + ? undefined + : await res.json().catch(() => undefined); + + if (!res.ok) { + throw new GithubApiError( + (data as any)?.message || `HTTP ${res.status}`, + res.status, + ); + } + + return data; + } + + public get(path: string): Promise { + return this.request('GET', path); + } + + public post(path: string, body: object): Promise { + return this.request('POST', path, body); + } + + public delete(path: string): Promise { + return this.request('DELETE', path); + } +} + /** * Returns a team data for given organization, using github API * object which is already authenticated under some user @@ -35,14 +115,12 @@ const RX_DEPRECATION = /Deprecation:/; */ export async function getTeam(github: Github, owner: string): Promise { try { - return ( - ( - (await github.teams.list({ - org: owner, - })) || /* istanbul ignore next */ ({} as any) - ).data || /* istanbul ignore next */ [] - ).shift(); - } catch (err) { + const teams = await github.get( + `/orgs/${encodeURIComponent(owner)}/teams`, + ); + + return (teams || /* istanbul ignore next */ []).shift() || null; + } catch { return null; } } @@ -57,8 +135,8 @@ export async function getTeam(github: Github, owner: string): Promise { */ export async function getOrg(github: Github, owner: string): Promise { try { - return (await github.orgs.get({ org: owner })).data; - } catch (err) { + return await github.get(`/orgs/${encodeURIComponent(owner)}`); + } catch { return null; } } @@ -70,7 +148,7 @@ export async function getOrg(github: Github, owner: string): Promise { * @return {Promise} */ export async function getInstance(token: string): Promise { - return new Github({ auth: token }); + return new Github(token); } /** @@ -99,23 +177,24 @@ export async function createRepository( const github = await getInstance(token); try { - const repository = await github.repos.get({ owner, repo }); + const repository = await github.get( + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`, + ); // istanbul ignore else - if (repository && repository.data && repository.data.name === repo) { + if (repository && repository.name === repo) { // noinspection ExceptionCaughtLocallyJS throw new Error('Repository already exists!'); } } catch (err) { - const status = (err as any).status ?? (err as any).code; + const status = (err as GithubApiError).status; if (status !== 404 && !RX_DEPRECATION.test((err as Error).message)) { throw err; } } - await github.repos.createInOrg({ - org: owner, + await github.post(`/orgs/${encodeURIComponent(owner)}/repos`, { name: repo, private: isPrivate, auto_init: false, diff --git a/package-lock.json b/package-lock.json index d3c484e..52dbfdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", - "@octokit/rest": "^22.0.1", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "semver": "^7.7.2", @@ -103,161 +102,6 @@ "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", "license": "MIT" }, - "node_modules/@octokit/auth-token": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", - "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/core": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", - "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^6.0.0", - "@octokit/graphql": "^9.0.3", - "@octokit/request": "^10.0.6", - "@octokit/request-error": "^7.0.2", - "@octokit/types": "^16.0.0", - "before-after-hook": "^4.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/endpoint": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", - "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/graphql": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", - "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", - "license": "MIT", - "dependencies": { - "@octokit/request": "^10.0.6", - "@octokit/types": "^16.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "27.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", - "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", - "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", - "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", - "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/request": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.11.tgz", - "integrity": "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==", - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^11.0.3", - "@octokit/request-error": "^7.0.2", - "@octokit/types": "^16.0.0", - "content-type": "^2.0.0", - "json-with-bigint": "^3.5.3", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/request-error": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", - "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^16.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/rest": { - "version": "22.0.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.1.tgz", - "integrity": "sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==", - "license": "MIT", - "dependencies": { - "@octokit/core": "^7.0.6", - "@octokit/plugin-paginate-rest": "^14.0.0", - "@octokit/plugin-request-log": "^6.0.0", - "@octokit/plugin-rest-endpoint-methods": "^17.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", - "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^27.0.0" - } - }, "node_modules/@oxfmt/binding-android-arm-eabi": { "version": "0.57.0", "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.57.0.tgz", @@ -1495,12 +1339,6 @@ "tweetnacl": "^0.14.3" } }, - "node_modules/before-after-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", - "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", - "license": "Apache-2.0" - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -1673,19 +1511,6 @@ "node": ">= 0.8" } }, - "node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2299,12 +2124,6 @@ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "license": "ISC" }, - "node_modules/json-with-bigint": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz", - "integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==", - "license": "MIT" - }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -2957,12 +2776,6 @@ "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "license": "MIT" }, - "node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "license": "ISC" - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index ba1d7e8..bfd4c29 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "dependencies": { "@imqueue/rpc": "^3.2.1", "@imqueue/travis": "^1.3.0", - "@octokit/rest": "^22.0.1", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "semver": "^7.7.2", diff --git a/test/lib/github.spec.ts b/test/lib/github.spec.ts index b63654f..f84e3e3 100644 --- a/test/lib/github.spec.ts +++ b/test/lib/github.spec.ts @@ -21,7 +21,7 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { describe, it } from 'node:test'; +import { afterEach, describe, it, mock } from 'node:test'; import assert from 'node:assert/strict'; import '../mocks/index.js'; import { randomUUID as uuid } from 'node:crypto'; @@ -34,6 +34,186 @@ try { /* no .env file - rely on the process environment */ } +function stubFetch( + handler: (url: string, init: any) => { status: number; body?: any }, +) { + return mock.method(globalThis, 'fetch', async (url: any, init: any) => { + const { status, body } = handler(String(url), init); + + return { + ok: status >= 200 && status < 300, + status, + json: async () => { + if (body === undefined) { + throw new Error('no body'); + } + return body; + }, + } as any; + }); +} + +describe('github (offline)', () => { + afterEach(() => mock.restoreAll()); + + describe('getInstance()', () => { + it('should throw on empty token', async () => { + await assert.rejects(() => github.getInstance(''), TypeError); + }); + + it('should return a client for a non-empty token', async () => { + const client = await github.getInstance('secret'); + + assert.ok(client instanceof github.Github); + }); + }); + + describe('Github.request()', () => { + it('should send bearer auth and parse json replies', async () => { + let seen: any; + stubFetch((url, init) => { + seen = { url, init }; + return { status: 200, body: { hello: 'world' } }; + }); + + const client = new github.Github('secret'); + const data = await client.get('/orgs/imqueue'); + + assert.deepEqual(data, { hello: 'world' }); + assert.equal(seen.url, 'https://api.github.com/orgs/imqueue'); + assert.equal(seen.init.headers.authorization, 'Bearer secret'); + }); + + it('should throw GithubApiError with status on failure', async () => { + stubFetch(() => ({ + status: 404, + body: { message: 'Not Found' }, + })); + + const client = new github.Github('secret'); + + await assert.rejects( + () => client.get('/repos/a/b'), + (err: any) => { + assert.ok(err instanceof github.GithubApiError); + assert.equal(err.status, 404); + assert.equal(err.message, 'Not Found'); + return true; + }, + ); + }); + }); + + describe('getTeam() [offline]', () => { + it('should return the first team', async () => { + stubFetch(() => ({ + status: 200, + body: [{ id: 1, slug: 'devs' }, { id: 2 }], + })); + + const client = new github.Github('secret'); + + assert.deepEqual(await github.getTeam(client, 'imqueue'), { + id: 1, + slug: 'devs', + }); + }); + + it('should return null on api errors', async () => { + stubFetch(() => ({ status: 404, body: { message: 'nope' } })); + + const client = new github.Github('secret'); + + assert.equal(await github.getTeam(client, 'unknown'), null); + }); + }); + + describe('getOrg() [offline]', () => { + it('should return org data', async () => { + stubFetch(() => ({ status: 200, body: { login: 'imqueue' } })); + + const client = new github.Github('secret'); + + assert.deepEqual(await github.getOrg(client, 'imqueue'), { + login: 'imqueue', + }); + }); + + it('should return null on api errors', async () => { + stubFetch(() => ({ status: 404, body: { message: 'nope' } })); + + const client = new github.Github('secret'); + + assert.equal(await github.getOrg(client, 'unknown'), null); + }); + }); + + describe('createRepository() [offline]', () => { + it('should throw on invalid url', async () => { + await assert.rejects( + () => github.createRepository('j032', 'secret', 'x'), + TypeError, + ); + }); + + it('should create the repository when it does not exist', async () => { + const calls: any[] = []; + stubFetch((url, init) => { + calls.push({ url, init }); + if (init.method === 'GET') { + return { status: 404, body: { message: 'Not Found' } }; + } + return { status: 201, body: { name: 'repo' } }; + }); + + await github.createRepository( + 'git@github.com:imqueue/repo', + 'secret', + 'test repo', + ); + + const post = calls.find(c => c.init.method === 'POST'); + + assert.ok(post); + assert.equal(post.url, 'https://api.github.com/orgs/imqueue/repos'); + assert.deepEqual(JSON.parse(post.init.body), { + name: 'repo', + private: true, + auto_init: false, + description: 'test repo', + }); + }); + + it('should throw if the repository already exists', async () => { + stubFetch(() => ({ status: 200, body: { name: 'repo' } })); + + await assert.rejects( + () => + github.createRepository( + 'git@github.com:imqueue/repo', + 'secret', + 'test repo', + ), + { message: 'Repository already exists!' }, + ); + }); + + it('should rethrow non-404 api errors', async () => { + stubFetch(() => ({ status: 401, body: { message: 'Bad creds' } })); + + await assert.rejects( + () => + github.createRepository( + 'git@github.com:imqueue/repo', + 'secret', + 'test repo', + ), + { message: 'Bad creds' }, + ); + }); + }); +}); + describe.skip('github', () => { const token = String(process.env.GITHUB_AUTH_TOKEN); @@ -122,14 +302,14 @@ describe.skip('github', () => { try { await github.createRepository(url, token, 'IMQ-CLI test repo'); - const data = await git.repos.get({ owner, repo }); + const data = await git.get(`/repos/${owner}/${repo}`); assert.ok(data); assert.equal(data.name, repo); assert.equal(data.owner.login, owner); } catch (err) {} try { // cleanup - await git.repos.delete({ owner, repo }); + await git.delete(`/repos/${owner}/${repo}`); } catch (err) { console.error(err); } @@ -148,14 +328,14 @@ describe.skip('github', () => { 'IMQ-CLI test repo', false, ); - const data = await git.repos.get({ owner, repo }); + const data = await git.get(`/repos/${owner}/${repo}`); assert.ok(data); assert.equal(data.name, repo); assert.equal(data.owner.login, owner); } catch (err) {} try { // cleanup - await git.repos.delete({ owner, repo }); + await git.delete(`/repos/${owner}/${repo}`); } catch (err) { console.error(err); } @@ -189,7 +369,7 @@ describe.skip('github', () => { } try { // cleanup - await git.repos.delete({ owner, repo }); + await git.delete(`/repos/${owner}/${repo}`); } catch (err) { console.error(err); } From 6110d2df6f2de072d9e09edd473efbd956d1d7ab Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:47:57 +0200 Subject: [PATCH 07/12] chore: replace @imqueue/travis with a native fetch Travis client The cli uses four Travis API v2 endpoints (github token exchange, repo public key, user sync, hooks get/update), now served by a small fetch client with TravisApiError carrying the HTTP status. travisEncrypt, trySyncBuilds and enableBuilds keep their signatures; the client exposes explicit methods (getRepositoryKey/syncUsers/getHooks/ updateHook) instead of the old chained proxy API. Adds 6 offline specs against a stubbed fetch, including a full RSA roundtrip: travisEncrypt output is decrypted back with the generated repository private key, proving the RSAES-PKCS1-v1_5 scheme matches. The cli now has zero HTTP-client dependencies; runtime deps are rpc, inquirer(+autocomplete), semver and yargs. --- lib/travis.ts | 159 +++++++++- package-lock.json | 689 +--------------------------------------- package.json | 1 - test/lib/travis.spec.ts | 175 +++++++++- 4 files changed, 325 insertions(+), 699 deletions(-) diff --git a/lib/travis.ts b/lib/travis.ts index 82d67d4..c24a30c 100644 --- a/lib/travis.ts +++ b/lib/travis.ts @@ -2,7 +2,7 @@ * IMQ-CLI library: travis * * I'm Queue Software Project - * Copyright (C) 2025 imqueue.com + * Copyright (C) 2026 imqueue.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,10 +21,151 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { TravisClient } from '@imqueue/travis'; import { constants as cryptoConstants, publicEncrypt } from 'node:crypto'; import { sleep } from './node.js'; +/** + * Error thrown for non-successful Travis API responses, carrying the HTTP + * status code of the response + */ +export class TravisApiError extends Error { + public constructor( + message: string, + public readonly status: number, + ) { + super(message); + this.name = 'TravisApiError'; + } +} + +export interface TravisClientOptions { + /** + * Use the pro endpoint (api.travis-ci.com) instead of the open-source + * one (api.travis-ci.org) + */ + pro?: boolean; +} + +/** + * Minimal Travis CI API client over native fetch, covering the few + * endpoints this cli uses (replaces the @imqueue/travis package) + */ +export class TravisClient { + private readonly baseUrl: string; + private accessToken?: string; + + public constructor(options?: TravisClientOptions) { + this.baseUrl = options?.pro + ? 'https://api.travis-ci.com' + : 'https://api.travis-ci.org'; + } + + /** + * Performs a Travis API request and returns the parsed JSON body. + * Throws TravisApiError with the response status on non-2xx replies. + * + * @param {string} method - HTTP method to use + * @param {string} path - API path, e.g. '/repos/{owner}/{repo}/key' + * @param {object} [body] - JSON-serializable request payload + * @return {Promise} + */ + public async request( + method: string, + path: string, + body?: object, + ): Promise { + const res = await fetch(`${this.baseUrl}${path}`, { + method, + headers: { + accept: 'application/vnd.travis-ci.2.1+json', + 'user-agent': 'Travis @imqueue/cli', + ...(this.accessToken + ? { authorization: `token ${this.accessToken}` } + : {}), + ...(body ? { 'content-type': 'application/json' } : {}), + }, + ...(body ? { body: JSON.stringify(body) } : {}), + }); + + const data = + res.status === 204 + ? undefined + : await res.json().catch(() => undefined); + + if (!res.ok) { + throw new TravisApiError( + (data as any)?.error_message || + (data as any)?.error || + `HTTP ${res.status}`, + res.status, + ); + } + + return data; + } + + /** + * Exchanges a github token for a travis access token and uses it for + * all subsequent requests + * + * @param {{ github_token: string }} params + * @return {Promise} + */ + public async authenticate(params: { github_token: string }): Promise { + const data = await this.request('POST', '/auth/github', params); + + this.accessToken = (data || {}).access_token; + } + + /** + * Returns the repository public key used for encrypting secure values + * + * @param {string} owner + * @param {string} repo + * @return {Promise<{ key: string }>} + */ + public getRepositoryKey( + owner: string, + repo: string, + ): Promise<{ key: string }> { + return this.request( + 'GET', + `/repos/${encodeURIComponent(owner)}/${encodeURIComponent( + repo, + )}/key`, + ); + } + + /** + * Triggers synchronization of the authenticated user's repositories + * + * @return {Promise} + */ + public syncUsers(): Promise { + return this.request('POST', '/users/sync'); + } + + /** + * Returns the authenticated user's repository hooks + * + * @return {Promise<{ hooks: any[] }>} + */ + public getHooks(): Promise<{ hooks: any[] }> { + return this.request('GET', '/hooks'); + } + + /** + * Updates the given hook's active state + * + * @param {number} id - hook identifier + * @param {boolean} active - desired state + * @return {Promise} + */ + public updateHook(id: number, active: boolean): Promise { + return this.request('PUT', `/hooks/${id}`, { hook: { id, active } }); + } +} + /** * Returns encrypted secure key for travis sensitive data. * @@ -47,10 +188,10 @@ export async function travisEncrypt( } const [owner, repo] = repository.split('/'); - const pem = await travis.repos(owner, repo).key.get(); + const pem = await travis.getRepositoryKey(owner, repo); // travis expects RSAES-PKCS1-v1_5 encryption with the repository - // public key (what node-rsa's encryptionScheme: 'pkcs1' produced) + // public key return publicEncrypt( { key: pem.key, @@ -76,9 +217,9 @@ export async function trySyncBuilds( delay: number = 2000, ): Promise { try { - await travis.users.sync.post(); + await travis.syncUsers(); await sleep(delay); - } catch (err) { + } catch { if (retry < maxRetries) { await sleep(delay); @@ -111,8 +252,8 @@ export async function enableBuilds( await travis.authenticate({ github_token }); await trySyncBuilds(travis); - const hook = (await travis.hooks.get()).hooks.find( - (hook: any) => hook.owner_name === owner && hook.name === repo, + const hook = (await travis.getHooks()).hooks.find( + (item: any) => item.owner_name === owner && item.name === repo, ); if (!hook) { @@ -121,7 +262,7 @@ export async function enableBuilds( return true; } - await travis.hooks(hook.id).put({ hook: { id: hook.id, active: true } }); + await travis.updateHook(hook.id, true); return true; } diff --git a/package-lock.json b/package-lock.json index 52dbfdd..89e2383 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "GPL-3.0-only", "dependencies": { "@imqueue/rpc": "^3.2.1", - "@imqueue/travis": "^1.3.0", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "semver": "^7.7.2", @@ -62,19 +61,6 @@ "node": ">=22.12.0" } }, - "node_modules/@imqueue/travis": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@imqueue/travis/-/travis-1.3.0.tgz", - "integrity": "sha512-bMh2a1HPtIjpXf5Ji8H3SduGpkR5fJMcg3sLyHIXYLdgyFA07sbWSMk11IbWvAmFHrFANrxnClqOvCu2cV0j+w==", - "license": "ISC", - "dependencies": { - "@types/request": "^2.48.12", - "request": "^2.88.2" - }, - "bin": { - "travis": "bin/travis-cli.js" - } - }, "node_modules/@inquirer/external-editor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", @@ -796,12 +782,6 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", - "license": "MIT" - }, "node_modules/@types/inquirer": { "version": "8.2.13", "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.13.tgz", @@ -827,23 +807,12 @@ "version": "24.13.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" } }, - "node_modules/@types/request": { - "version": "2.48.13", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", - "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", - "license": "MIT", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.5" - } - }, "node_modules/@types/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", @@ -861,12 +830,6 @@ "@types/node": "*" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "license": "MIT" - }, "node_modules/@types/yargs": { "version": "17.0.35", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", @@ -1216,22 +1179,6 @@ "node": ">=0.4.0" } }, - "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1271,45 +1218,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "license": "MIT" - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1330,15 +1238,6 @@ ], "license": "MIT" }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -1374,25 +1273,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "license": "Apache-2.0" - }, "node_modules/chardet": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", @@ -1499,36 +1379,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "license": "MIT" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1558,15 +1408,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -1576,81 +1417,12 @@ "node": ">=0.10" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "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/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1669,33 +1441,6 @@ "node": ">=0.8.0" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -1711,41 +1456,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.6.tgz", - "integrity": "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1755,87 +1465,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1845,60 +1474,6 @@ "node": ">=8" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/iconv-lite": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", @@ -2076,12 +1651,6 @@ "node": ">=8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "license": "MIT" - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2094,51 +1663,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "license": "MIT" - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", @@ -2177,36 +1701,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -2228,15 +1722,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "license": "ISC" }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -2392,42 +1877,6 @@ } } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "license": "MIT" - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", - "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -2463,52 +1912,6 @@ "node": ">=4" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2593,31 +1996,6 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -2687,43 +2065,12 @@ "node": "^20.0.0 || >=22.0.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "license": "Unlicense" - }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -2774,47 +2121,15 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "devOptional": true, "license": "MIT" }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index bfd4c29..0b59419 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "license": "GPL-3.0-only", "dependencies": { "@imqueue/rpc": "^3.2.1", - "@imqueue/travis": "^1.3.0", "inquirer": "^8.2.6", "inquirer-autocomplete-prompt": "^1.4.0", "semver": "^7.7.2", diff --git a/test/lib/travis.spec.ts b/test/lib/travis.spec.ts index 54557e6..39b1983 100644 --- a/test/lib/travis.spec.ts +++ b/test/lib/travis.spec.ts @@ -21,12 +21,183 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -import { describe, it } from 'node:test'; +import { afterEach, describe, it, mock } from 'node:test'; import assert from 'node:assert/strict'; import '../mocks/index.js'; -import { travisEncrypt } from '../../lib/index.js'; +import { + constants as cryptoConstants, + generateKeyPairSync, + privateDecrypt, +} from 'node:crypto'; +import { + enableBuilds, + travisEncrypt, + TravisApiError, + TravisClient, +} from '../../lib/index.js'; describe('travis', () => { + describe('TravisClient (offline)', () => { + afterEach(() => mock.restoreAll()); + + function stubFetch( + handler: (url: string, init: any) => { status: number; body?: any }, + ) { + const calls: Array<{ url: string; init: any }> = []; + + mock.method(globalThis, 'fetch', async (url: any, init: any) => { + calls.push({ url: String(url), init }); + const { status, body } = handler(String(url), init); + + return { + ok: status >= 200 && status < 300, + status, + json: async () => { + if (body === undefined) { + throw new Error('no body'); + } + return body; + }, + } as any; + }); + + return calls; + } + + it('should target org endpoint by default and pro when asked', async () => { + const calls = stubFetch(() => ({ status: 200, body: {} })); + + await new TravisClient().request('GET', '/hooks'); + await new TravisClient({ pro: true }).request('GET', '/hooks'); + + assert.ok(calls[0].url.startsWith('https://api.travis-ci.org/')); + assert.ok(calls[1].url.startsWith('https://api.travis-ci.com/')); + }); + + it('should exchange github token and send it as auth header', async () => { + const calls = stubFetch((url, init) => { + if (url.endsWith('/auth/github')) { + assert.equal( + JSON.parse(init.body).github_token, + 'gh-secret', + ); + return { + status: 200, + body: { access_token: 'travis-token' }, + }; + } + return { status: 200, body: { hooks: [] } }; + }); + const travis = new TravisClient({ pro: true }); + + await travis.authenticate({ github_token: 'gh-secret' }); + await travis.getHooks(); + + assert.equal( + calls[1].init.headers.authorization, + 'token travis-token', + ); + }); + + it('should throw TravisApiError with status on failures', async () => { + stubFetch(() => ({ + status: 403, + body: { error_message: 'access denied' }, + })); + + await assert.rejects( + () => new TravisClient().getRepositoryKey('a', 'b'), + (err: any) => { + assert.ok(err instanceof TravisApiError); + assert.equal(err.status, 403); + assert.equal(err.message, 'access denied'); + return true; + }, + ); + }); + + it( + 'should encrypt data decryptable with the repository private ' + + 'key', + async () => { + const { publicKey, privateKey } = generateKeyPairSync('rsa', { + modulusLength: 2048, + publicKeyEncoding: { type: 'pkcs1', format: 'pem' }, + privateKeyEncoding: { type: 'pkcs1', format: 'pem' }, + }); + stubFetch(url => { + assert.ok(url.endsWith('/repos/imqueue/cli/key')); + return { status: 200, body: { key: publicKey } }; + }); + + const encrypted = await travisEncrypt('imqueue/cli', 'A=B'); + const decrypted = privateDecrypt( + { + key: privateKey, + padding: cryptoConstants.RSA_PKCS1_PADDING, + }, + Buffer.from(encrypted, 'base64'), + ); + + assert.equal(decrypted.toString('utf8'), 'A=B'); + }, + ); + + it('should enable an inactive hook through the hooks api', async () => { + const calls = stubFetch((url, init) => { + if (url.endsWith('/auth/github')) { + return { status: 200, body: { access_token: 't' } }; + } + if (url.endsWith('/users/sync')) { + return { status: 200, body: {} }; + } + if (url.endsWith('/hooks') && init.method === 'GET') { + return { + status: 200, + body: { + hooks: [ + { + id: 7, + owner_name: 'imqueue', + name: 'cli', + active: false, + }, + ], + }, + }; + } + return { status: 200, body: {} }; + }); + + const enabled = await enableBuilds('imqueue', 'cli', 'gh', false); + + assert.equal(enabled, true); + const put = calls.find(call => call.init.method === 'PUT'); + assert.ok(put); + assert.ok(put.url.endsWith('/hooks/7')); + assert.deepEqual(JSON.parse(put.init.body), { + hook: { id: 7, active: true }, + }); + }); + + it('should report false when the repository hook is missing', async () => { + stubFetch(url => { + if (url.endsWith('/auth/github')) { + return { status: 200, body: { access_token: 't' } }; + } + if (url.endsWith('/hooks')) { + return { status: 200, body: { hooks: [] } }; + } + return { status: 200, body: {} }; + }); + + assert.equal( + await enableBuilds('imqueue', 'missing', 'gh', false), + false, + ); + }); + }); + describe('travisEncrypt()', () => { it('should be a function', () => { assert.equal(typeof travisEncrypt, 'function'); From 9e9fb1d2ca05e23d8ee5522660cef2fe2a043662 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 16:57:42 +0200 Subject: [PATCH 08/12] chore: align version with the last published release (2.0.2) The migration commit had pre-set 3.0.0, which would make the usual 'npm version major' release flow skip to 4.0.0. Align back to the published 2.0.2 so the release flow itself produces 3.0.0 with its tag and commit. --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89e2383..7abde76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@imqueue/cli", - "version": "3.0.0", + "version": "2.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@imqueue/cli", - "version": "3.0.0", + "version": "2.0.2", "license": "GPL-3.0-only", "dependencies": { "@imqueue/rpc": "^3.2.1", diff --git a/package.json b/package.json index 0b59419..d063b04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@imqueue/cli", - "version": "3.0.0", + "version": "2.0.2", "description": "Command Line Interface for IMQ", "keywords": [ "command-line-tool", From 30ed115257a391c1b65788fd451247337dc2b8f6 Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 17:01:59 +0200 Subject: [PATCH 09/12] style: resolve all oxlint warnings - console.log added to the allowed console methods in .oxlintrc.json: stdout printing is this package's user interface, not debug leftovers - unused catch bindings dropped (bare catch) - dead PROGRAM variable removed from service update-version (assigned from yargs argv but never read); its builder no longer needs async - isGuthubToken import in validate spec was unused because the function had no tests - covered now instead of dropping the import --- .oxlintrc.json | 2 +- lib/autoupdate.ts | 4 +- lib/error.ts | 3 +- lib/fs.ts | 3 +- lib/license.ts | 1 - lib/template.ts | 3 -- lib/travis.ts | 5 +-- package-lock.json | 80 +++++++---------------------------- src/completions/off.ts | 1 - src/completions/on.ts | 3 -- src/config/init.ts | 9 ---- src/service/create.ts | 36 +--------------- src/service/update-version.ts | 9 +--- test/lib/config.spec.ts | 12 +++--- test/lib/fs.spec.ts | 2 +- test/lib/github.spec.ts | 4 +- test/lib/validate.spec.ts | 12 +++++- test/mocks/logger.ts | 1 - test/mocks/redis.ts | 17 -------- 19 files changed, 45 insertions(+), 162 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 2757f3e..d9aad02 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -5,7 +5,7 @@ }, "rules": { "no-debugger": "error", - "no-console": ["warn", { "allow": ["warn", "error", "info"] }], + "no-console": ["warn", { "allow": ["log", "warn", "error", "info"] }], "no-unused-vars": "warn" }, "ignorePatterns": [ diff --git a/lib/autoupdate.ts b/lib/autoupdate.ts index 318e267..ccffd8d 100644 --- a/lib/autoupdate.ts +++ b/lib/autoupdate.ts @@ -30,7 +30,6 @@ const require = createRequire(import.meta.url); const pkg = require('../package.json'); -// istanbul ignore next /** * Performs check if local version is latest */ @@ -66,12 +65,11 @@ export async function checkForUpdate() { update(); } } - } catch (err) { + } catch { /* ignore */ } } -// istanbul ignore next /** * Executes update command for this package */ diff --git a/lib/error.ts b/lib/error.ts index 651b339..255f050 100644 --- a/lib/error.ts +++ b/lib/error.ts @@ -24,7 +24,6 @@ import { styleText } from 'node:util'; // that is just a printing function, no need to do specific tests -// istanbul ignore next /** * Prints error message to standard error output * @@ -42,7 +41,7 @@ export function printError(err: Error, withStackTrace: boolean = false) { .map((err: any) => err.message) .join('\n')}`; } - } catch (err) { + } catch { /* ignore */ } diff --git a/lib/fs.ts b/lib/fs.ts index d3ccedd..ded2a90 100644 --- a/lib/fs.ts +++ b/lib/fs.ts @@ -108,8 +108,7 @@ export function mkdirp(path: string): void { */ export function touch( path: string, - // istanbul ignore next - content: string = '', + content: string = '', ): void { if (!fs.existsSync(path)) { mkdirp(p.dirname(path)); diff --git a/lib/license.ts b/lib/license.ts index 52fbf04..cfb8c89 100644 --- a/lib/license.ts +++ b/lib/license.ts @@ -60,7 +60,6 @@ export function findLicense(name: string): any { return null; } -// istanbul ignore next /** * Queries user for license selection * diff --git a/lib/template.ts b/lib/template.ts index 53a7a01..045a5c9 100644 --- a/lib/template.ts +++ b/lib/template.ts @@ -74,7 +74,6 @@ export function checkGit() { } // due to problematic testing of user-interaction -// istanbul ignore next /** * Load IMQ templates from templates git repository * @@ -103,7 +102,6 @@ export async function loadTemplates() { } // due to problematic testing of user-interaction -// istanbul ignore next /** * Updates local copy of templates repo from remote source * @@ -122,7 +120,6 @@ export async function updateTemplates() { } // due to problematic testing of user-interaction -// istanbul ignore next /** * Loads custom template from a given git repository * diff --git a/lib/travis.ts b/lib/travis.ts index c24a30c..3e86649 100644 --- a/lib/travis.ts +++ b/lib/travis.ts @@ -182,8 +182,7 @@ export async function travisEncrypt( ): Promise { const travis = new TravisClient({ pro: !!github_token }); - // istanbul ignore next - if (github_token) { + if (github_token) { await travis.authenticate({ github_token }); } @@ -201,7 +200,6 @@ export async function travisEncrypt( ).toString('base64'); } -// istanbul ignore next /** * Tries perform travis sync * @@ -232,7 +230,6 @@ export async function trySyncBuilds( return true; } -// istanbul ignore next /** * Enables builds for a given repository * diff --git a/package-lock.json b/package-lock.json index 7abde76..e0f2ba5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1273,6 +1273,22 @@ "ieee754": "^1.1.13" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/chardet": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", @@ -1561,22 +1577,6 @@ "inquirer": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/inquirer-autocomplete-prompt/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/inquirer-autocomplete-prompt/node_modules/rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -1595,22 +1595,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/ioredis": { "version": "5.11.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", @@ -1685,22 +1669,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -1760,22 +1728,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/oxfmt": { "version": "0.57.0", "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.57.0.tgz", diff --git a/src/completions/off.ts b/src/completions/off.ts index 7595621..99e505b 100644 --- a/src/completions/off.ts +++ b/src/completions/off.ts @@ -33,7 +33,6 @@ import { resolve, printError, IS_ZSH } from '../../lib/index.js'; let PROGRAM: string = ''; let RX_REPLACE: RegExp; -// istanbul ignore next /** * Prints script removal success message to the user * diff --git a/src/completions/on.ts b/src/completions/on.ts index b964f9e..d1a0ac3 100644 --- a/src/completions/on.ts +++ b/src/completions/on.ts @@ -33,7 +33,6 @@ import { resolve, touch, printError, IS_ZSH } from '../../lib/index.js'; let PROGRAM: string = ''; let RX_EXISTS: RegExp; -// istanbul ignore next /** * Prints add script success message to user * @@ -52,7 +51,6 @@ function printAdded(rcFilename: string) { ); } -// istanbul ignore next /** * Returns completions script for user's shell * @@ -78,7 +76,6 @@ complete -F _yargs_completions ${PROGRAM} ###-end-${PROGRAM}-completions-###\n`; } -// istanbul ignore next /** * Prints script exists message to the user * diff --git a/src/config/init.ts b/src/config/init.ts index 4da8f9b..3afadbd 100644 --- a/src/config/init.ts +++ b/src/config/init.ts @@ -42,7 +42,6 @@ const inquirer = originalInquirer as unknown as typeof originalInquirer.default; // we are going to ignore almost all code here because it's very hard to test // command line user interaction -// istanbul ignore next export async function selectTemplate(type: string): Promise<{ [name: string]: string; }> { @@ -102,7 +101,6 @@ export async function selectTemplate(type: string): Promise<{ return { [name]: path }; } -// istanbul ignore next export async function templateOptions(config: IMQCLIConfig) { let answer: any = await inquirer.prompt<{ useDefault: boolean }>([ { @@ -161,7 +159,6 @@ export async function templateOptions(config: IMQCLIConfig) { } } -// istanbul ignore next export async function versionSystemOptions( config: IMQCLIConfig, ): Promise { @@ -293,7 +290,6 @@ export async function versionSystemOptions( ); } -// istanbul ignore next export async function authorName(config: IMQCLIConfig): Promise { const answer = await inquirer.prompt<{ author: string }>([ { @@ -320,7 +316,6 @@ export async function authorName(config: IMQCLIConfig): Promise { ); } -// istanbul ignore next export async function authorEmail(config: IMQCLIConfig) { const answer = await inquirer.prompt<{ email: string }>([ { @@ -347,13 +342,11 @@ export async function authorEmail(config: IMQCLIConfig) { ); } -// istanbul ignore next export async function authorOptions(config: IMQCLIConfig) { await authorName(config); await authorEmail(config); } -// istanbul ignore next export async function dockerCredentials(config: IMQCLIConfig): Promise { const answer = await inquirer.prompt<{ dockerHubUser: string; @@ -402,7 +395,6 @@ export async function dockerCredentials(config: IMQCLIConfig): Promise { ); } -// istanbul ignore next export async function dockerQuestions(config: IMQCLIConfig): Promise { let answer: any = await inquirer.prompt<{ useDocker: boolean }>([ { @@ -457,7 +449,6 @@ export async function dockerQuestions(config: IMQCLIConfig): Promise { await dockerCredentials(config); } -// istanbul ignore next export async function serviceQuestions(config: IMQCLIConfig) { await authorOptions(config); await templateOptions(config); diff --git a/src/service/create.ts b/src/service/create.ts index d8814b5..071bc3d 100644 --- a/src/service/create.ts +++ b/src/service/create.ts @@ -59,7 +59,6 @@ const DEFAULT_SERVICE_VERSION = '1.0.0-0'; let config: IMQCLIConfig; -// istanbul ignore next async function ensureTemplate(template: string) { if (fs.existsSync(template)) { return template; @@ -80,7 +79,6 @@ async function ensureTemplate(template: string) { return templates[template]; } -// istanbul ignore next function updateLicenseText( text: string, author: string, @@ -103,7 +101,6 @@ function updateLicenseText( return text; } -// istanbul ignore next async function ensureLicense( path: string, license: string, @@ -165,7 +162,7 @@ Please, refer to LICENSE file in project's root directory for details.`; try { fs.unlinkSync(resolve(path, 'LICENSE')); - } catch (err) { + } catch { /* ignore */ } touch(resolve(path, 'LICENSE'), wrap(text)); @@ -173,7 +170,6 @@ Please, refer to LICENSE file in project's root directory for details.`; return { text, header, name, tag }; } -// istanbul ignore next function ensureName(name: string) { if (!name.trim()) { throw new TypeError(`Service name expected, but was not given!`); @@ -182,7 +178,6 @@ function ensureName(name: string) { return dashed(name.trim()); } -// istanbul ignore next function ensureVersion(version: string) { if (!version.trim()) { version = DEFAULT_SERVICE_VERSION; @@ -198,12 +193,10 @@ function ensureVersion(version: string) { return version; } -// istanbul ignore next function ensureDescription(description: string, name: string) { return description || `${dashed(name)} - IMQ based service`; } -// istanbul ignore next function ensureServiceRepo(owner: string, name: string) { if (!owner) { return ''; @@ -215,7 +208,6 @@ function ensureServiceRepo(owner: string, name: string) { },\n`; } -// istanbul ignore next function ensureServicePages(argv: any): { home: string; bugs: string; @@ -239,7 +231,6 @@ function ensureServicePages(argv: any): { }; } -// istanbul ignore next async function ensureAuthorName(name: string) { name = name.trim(); @@ -261,7 +252,6 @@ async function ensureAuthorName(name: string) { return name; } -// istanbul ignore next async function ensureAuthorEmail(email: string) { email = email.trim(); @@ -288,7 +278,6 @@ async function ensureAuthorEmail(email: string) { return email; } -// istanbul ignore next async function ensureTravisTags(argv: any): Promise { if (argv.n instanceof Array && argv.n.length) { return argv.n; @@ -320,7 +309,6 @@ async function ensureTravisTags(argv: any): Promise { return tags; } -// istanbul ignore next async function ensureDockerNamespace(argv: any) { let ns = (argv.N || '').trim(); let dockerize = argv.D || config.useDocker; @@ -372,7 +360,6 @@ async function ensureDockerNamespace(argv: any) { return ns; } -// istanbul ignore next async function ensureDockerTag(argv: any) { if (argv.L.trim()) { return argv.L.trim(); @@ -388,7 +375,6 @@ async function ensureDockerTag(argv: any) { return version; } -// istanbul ignore next async function ensureDockerSecrets(argv: any) { const owner = argv.u.trim(); const name = ensureName(argv.name); @@ -461,7 +447,6 @@ async function ensureDockerSecrets(argv: any) { ]; } -// istanbul ignore next function stripDockerization(argv: any) { const path = resolve(argv.path as string); const travis = resolve(path, '.travis.yml'); @@ -485,7 +470,6 @@ function stripDockerization(argv: any) { } } -// istanbul ignore next async function enableTravisBuilds(argv: any) { console.log('Enabling travis builds...'); let enabled = false; @@ -497,7 +481,7 @@ async function enableTravisBuilds(argv: any) { config.gitHubAuthToken, argv.p, ); - } catch (err) { + } catch { /* ignore */ } @@ -513,7 +497,6 @@ async function enableTravisBuilds(argv: any) { } } -// istanbul ignore next async function buildDockerCi(argv: any): Promise { const dockerNs = await ensureDockerNamespace(argv); const dockerize = !!( @@ -548,7 +531,6 @@ async function buildDockerCi(argv: any): Promise { compileTemplate(resolve(argv.path), tags); } -// istanbul ignore next async function buildTags(path: string, argv: any) { const name = ensureName(argv.name); const author = await ensureAuthorName(argv.author); @@ -581,7 +563,6 @@ async function buildTags(path: string, argv: any) { }; } -// istanbul ignore next function createServiceFile(path: string, tags: any) { console.log('Creating main service file...'); @@ -620,7 +601,6 @@ export class ${tags.SERVICE_CLASS_NAME} extends IMQService { ); } -// istanbul ignore next function createServiceTestFile(path: string, tags: any) { console.log('Creating main service test file...'); @@ -660,7 +640,6 @@ describe('${tags.SERVICE_CLASS_NAME}', () => { ); } -// istanbul ignore next function compileTemplateFile(text: string, tags: any): string { for (let tag of Object.keys(tags)) { text = text.replace(new RegExp(`%${tag}`, 'g'), tags[tag]); @@ -669,7 +648,6 @@ function compileTemplateFile(text: string, tags: any): string { return text; } -// istanbul ignore next function compileTemplate(path: string, tags: any) { fs.readdirSync(path).forEach((file: string) => { const filePath = resolve(path, file); @@ -687,7 +665,6 @@ function compileTemplate(path: string, tags: any) { }); } -// istanbul ignore next async function makeService(path: string, argv: any) { const tags = await buildTags(path, argv); @@ -696,7 +673,6 @@ async function makeService(path: string, argv: any) { createServiceTestFile(path, tags); } -// istanbul ignore next async function buildFromTemplate(argv: any) { const template = await ensureTemplate(argv.template); const path = resolve(argv.path); @@ -707,7 +683,6 @@ async function buildFromTemplate(argv: any) { await makeService(path, argv); } -// istanbul ignore next async function ensureGitRepo(argv: any) { if (!isNamespace(argv.u)) { const answer: { gitNs: string } = await inquirer.prompt<{ @@ -734,7 +709,6 @@ async function ensureGitRepo(argv: any) { let gitRepoInitialized = false; -// istanbul ignore next async function createGitRepo(argv: any) { const useGit = argv.g || config.useGit; @@ -810,7 +784,6 @@ async function createGitRepo(argv: any) { gitRepoInitialized = true; } -// istanbul ignore next async function installPackages(argv: any) { if (!commandExists('npm')) { throw new Error('npm command is not installed!'); @@ -819,9 +792,7 @@ async function installPackages(argv: any) { const cwd = process.cwd(); const path = resolve(argv.path); const pkg: any = require(resolve(path, 'package.json')); - // noinspection TypeScriptUnresolvedVariable const deps = Object.keys(pkg.dependencies); - // noinspection TypeScriptUnresolvedVariable const devDeps = Object.keys(pkg.devDependencies); process.chdir(path); @@ -839,7 +810,6 @@ async function installPackages(argv: any) { process.chdir(cwd); } -// istanbul ignore next async function commit(argv: any) { const path = resolve(argv.path); const name = ensureName(argv.name); @@ -877,7 +847,6 @@ git push origin master --tags`); process.chdir(cwd); } -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'create [name] [path]', describe: @@ -997,7 +966,6 @@ export const { command, describe, builder, handler } = { await createGitRepo(argv); await buildDockerCi(argv); - // noinspection TypeScriptUnresolvedVariable if (!argv.noInstall) { await installPackages(argv); } diff --git a/src/service/update-version.ts b/src/service/update-version.ts index e12a9c2..3868022 100644 --- a/src/service/update-version.ts +++ b/src/service/update-version.ts @@ -31,7 +31,6 @@ import { Console } from 'console'; import { pathToFileURL } from 'node:url'; const BASE_SERVICE_NAME = 'IMQService'; -let PROGRAM: string = ''; let ROOT_DIRECTORY = process.cwd(); /** @@ -129,7 +128,6 @@ async function isFolderContainsService(servicePath: string): Promise { */ function walkThroughFolders(paths: string[], args: Arguments) { for (const path of paths) { - // noinspection TypeScriptValidateTypes logger.log(styleText('blue', `\nService: ${path}`)); execGitFlow(path, args); } @@ -205,7 +203,6 @@ function handleSpawnResponse( response: SpawnSyncReturns, ): number | null { if (response.status !== 0 || response.error) { - // noinspection TypeScriptValidateTypes logger.log( styleText( 'red', @@ -254,7 +251,7 @@ function execGitFlow(servicePath: string, args: Arguments): void { if (handleSpawnResponse(response)) { return; } - // noinspection TypeScriptValidateTypes + logger.log(styleText('green', 'Done!')); } @@ -284,15 +281,13 @@ async function getServicesFolders(path: string): Promise { return folders; } -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'update-version [branch] [version]', describe: 'Updates services under given path with new version tag ' + 'and automatically pushes changes to repository, triggering builds.', - async builder(yargs: Argv) { - PROGRAM = (await yargs.argv).$0; + builder(yargs: Argv) { return yargs .option('b', { alias: 'branch', diff --git a/test/lib/config.spec.ts b/test/lib/config.spec.ts index 2bf0a76..9936c8e 100644 --- a/test/lib/config.spec.ts +++ b/test/lib/config.spec.ts @@ -39,12 +39,12 @@ describe('config', () => { beforeEach(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); afterEach(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); it('should be a function', () => { @@ -76,12 +76,12 @@ describe('config', () => { before(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); after(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); it('should be a function', () => { @@ -146,12 +146,12 @@ describe('config', () => { before(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); after(() => { try { fs.unlinkSync(CONFIG_PATH); - } catch (e) {} + } catch {} }); it('should be a function', () => { diff --git a/test/lib/fs.spec.ts b/test/lib/fs.spec.ts index 4e90112..740297f 100644 --- a/test/lib/fs.spec.ts +++ b/test/lib/fs.spec.ts @@ -38,7 +38,7 @@ describe('fs', () => { after(() => { try { rmdir(TEMP_DIR); - } catch (e) {} + } catch {} }); describe('cpr()', () => { diff --git a/test/lib/github.spec.ts b/test/lib/github.spec.ts index f84e3e3..ccecd5b 100644 --- a/test/lib/github.spec.ts +++ b/test/lib/github.spec.ts @@ -306,7 +306,7 @@ describe.skip('github', () => { assert.ok(data); assert.equal(data.name, repo); assert.equal(data.owner.login, owner); - } catch (err) {} + } catch {} try { // cleanup await git.delete(`/repos/${owner}/${repo}`); @@ -332,7 +332,7 @@ describe.skip('github', () => { assert.ok(data); assert.equal(data.name, repo); assert.equal(data.owner.login, owner); - } catch (err) {} + } catch {} try { // cleanup await git.delete(`/repos/${owner}/${repo}`); diff --git a/test/lib/validate.spec.ts b/test/lib/validate.spec.ts index ff6c70e..d57c930 100644 --- a/test/lib/validate.spec.ts +++ b/test/lib/validate.spec.ts @@ -26,7 +26,17 @@ import assert from 'node:assert/strict'; import '../mocks/index.js'; import { isEmail, isNamespace, isGuthubToken } from '../../lib/index.js'; -describe('validate', function () { +describe('validate', () => { + describe('isGuthubToken()', () => { + it('should accept any non-empty token string', () => { + assert.equal(isGuthubToken('ghp_abc123'), true); + }); + + it('should reject an empty string', () => { + assert.equal(isGuthubToken(''), false); + }); + }); + describe('isEmail()', () => { it('should be a function', () => { assert.equal(typeof isEmail, 'function'); diff --git a/test/mocks/logger.ts b/test/mocks/logger.ts index 046df68..759959d 100644 --- a/test/mocks/logger.ts +++ b/test/mocks/logger.ts @@ -21,7 +21,6 @@ * purchase a proprietary commercial license. Please contact us at * to get commercial licensing options. */ -// noinspection JSUnusedGlobalSymbols export const logger: any = { log() {}, info() {}, diff --git a/test/mocks/redis.ts b/test/mocks/redis.ts index 11e833d..73aa617 100644 --- a/test/mocks/redis.ts +++ b/test/mocks/redis.ts @@ -40,7 +40,6 @@ export class RedisClientMock extends EventEmitter { private static __keys: any = {}; private static __scripts: any = {}; private __name: string = ''; - // noinspection JSUnusedGlobalSymbols public connected: boolean = true; public status = 'ready'; @@ -56,12 +55,9 @@ export class RedisClientMock extends EventEmitter { } } - // noinspection JSUnusedGlobalSymbols public end() {} - // noinspection JSUnusedGlobalSymbols public quit() {} - // noinspection JSMethodCanBeStatic public async set(...args: any[]): Promise { let [key, val, units, expire, nx] = args; @@ -104,7 +100,6 @@ export class RedisClientMock extends EventEmitter { return val; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public setnx(...args: any[]): number { const self = RedisClientMock; const key = args.shift(); @@ -121,7 +116,6 @@ export class RedisClientMock extends EventEmitter { return result; } - // noinspection TypescriptExplicitMemberType,JSMethodCanBeStatic public lpush(key: string, value: any, cb?: any): number { const self = RedisClientMock; if (!self.__queues__[key]) { @@ -186,7 +180,6 @@ export class RedisClientMock extends EventEmitter { } } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public lrange( key: string, start: number, @@ -200,7 +193,6 @@ export class RedisClientMock extends EventEmitter { return result; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public scan(...args: any[]): (string | string[])[] { const cb = args.pop(); const qs = RedisClientMock.__queues__; @@ -215,7 +207,6 @@ export class RedisClientMock extends EventEmitter { return result; } - // noinspection JSMethodCanBeStatic public script(...args: any[]): unknown { const cmd = args.shift(); const scriptOrHash = args.shift(); @@ -243,7 +234,6 @@ export class RedisClientMock extends EventEmitter { return [0]; } - // noinspection JSUnusedGlobalSymbols public client(...args: any[]): string | boolean { const self = RedisClientMock; const cmd = args.shift(); @@ -266,7 +256,6 @@ export class RedisClientMock extends EventEmitter { return true; } - // noinspection JSMethodCanBeStatic public exists(...args: any[]): boolean { const key = args.shift(); const result = RedisClientMock.__keys[key] !== undefined; @@ -274,19 +263,16 @@ export class RedisClientMock extends EventEmitter { return result; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public psubscribe(...args: any[]): number { this.cbExecute(args.pop(), null, 1); return 1; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public evalsha(...args: any[]): boolean { this.cbExecute(args.pop()); return true; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public del(...args: any[]): number { const self = RedisClientMock; let count = 0; @@ -304,7 +290,6 @@ export class RedisClientMock extends EventEmitter { return count; } - // noinspection JSUnusedGlobalSymbols public zadd(...args: any[]): boolean { const [key, score, value, cb] = args; const timeout = score - Date.now(); @@ -316,7 +301,6 @@ export class RedisClientMock extends EventEmitter { return true; } - // noinspection JSUnusedGlobalSymbols public disconnect(): boolean { delete RedisClientMock.__clientList[this.__name]; if (this.__rt) { @@ -326,7 +310,6 @@ export class RedisClientMock extends EventEmitter { return true; } - // noinspection JSUnusedGlobalSymbols,JSMethodCanBeStatic public config(): boolean { return true; } From dfb23703ecd00ab0f1b5a011a8a327793597301e Mon Sep 17 00:00:00 2001 From: Serhiy Morenko Date: Fri, 10 Jul 2026 17:04:52 +0200 Subject: [PATCH 10/12] fix: linting some redundant ignores and noinspection --- lib/config.ts | 2 -- lib/fs.ts | 2 -- lib/github.ts | 6 ++---- lib/license.ts | 1 - lib/node.ts | 19 +++++++------------ src/client.ts | 1 - src/client/generate.ts | 1 - src/completions.ts | 1 - src/completions/off.ts | 1 - src/completions/on.ts | 1 - src/config.ts | 1 - src/config/check.ts | 1 - src/config/get.ts | 1 - src/config/init.ts | 1 - src/config/set.ts | 1 - src/service.ts | 1 - src/service/create.ts | 4 ---- 17 files changed, 9 insertions(+), 36 deletions(-) diff --git a/lib/config.ts b/lib/config.ts index adb0e13..2cf02f9 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -103,8 +103,6 @@ export function prepareConfigValue(value: any) { return undefined; } - // istanbul ignore else - // noinspection RegExpSingleCharAlternation,RegExpRedundantEscape if (/^\s*(\[|\{)/.test(value)) { return JSON.parse(value); } diff --git a/lib/fs.ts b/lib/fs.ts index ded2a90..df12e7c 100644 --- a/lib/fs.ts +++ b/lib/fs.ts @@ -60,7 +60,6 @@ export function cpr(from: string, to: string) { export function rmdir(path: string) { let files = []; - // istanbul ignore else if (fs.existsSync(path)) { files = fs.readdirSync(path); @@ -92,7 +91,6 @@ export function mkdirp(path: string): void { return mkdirp(path); } - // istanbul ignore if if (!fs.statSync(path).isDirectory()) { throw err; } diff --git a/lib/github.ts b/lib/github.ts index ad9b385..4dd77a1 100644 --- a/lib/github.ts +++ b/lib/github.ts @@ -119,7 +119,7 @@ export async function getTeam(github: Github, owner: string): Promise { `/orgs/${encodeURIComponent(owner)}/teams`, ); - return (teams || /* istanbul ignore next */ []).shift() || null; + return (teams || []).shift() || null; } catch { return null; } @@ -167,7 +167,7 @@ export async function createRepository( isPrivate: boolean = true, ) { const [owner, repo] = ( - url.split(':').reverse().shift() || /* istanbul ignore next */ '' + url.split(':').reverse().shift() || '' ).split('/'); if (!(repo && owner)) { @@ -181,9 +181,7 @@ export async function createRepository( `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`, ); - // istanbul ignore else if (repository && repository.name === repo) { - // noinspection ExceptionCaughtLocallyJS throw new Error('Repository already exists!'); } } catch (err) { diff --git a/lib/license.ts b/lib/license.ts index cfb8c89..9b5e208 100644 --- a/lib/license.ts +++ b/lib/license.ts @@ -31,7 +31,6 @@ const require = createRequire(import.meta.url); const LICENSES: any = require('./licenses.json'); -// noinspection RegExpRedundantEscape const RX_ESCAPE = /[-[\]/{}()*+?.\\^$|]/g; /** diff --git a/lib/node.ts b/lib/node.ts index e54bc59..b7e7abf 100644 --- a/lib/node.ts +++ b/lib/node.ts @@ -27,7 +27,6 @@ import * as semver from 'semver'; const RX_COMMAND_NAME = /^[\w.-]+$/; const RX_VERSION_CLEAN = /^v/; -// noinspection JSUnusedGlobalSymbols /** * Checks if the given executable is available on this system. Replaces the * command-exists package with a native probe. The IMQ_CLI_MISSING_COMMANDS @@ -104,20 +103,18 @@ export function semverCompare(a: string, b: string) { export async function getNodeVersions( force: boolean = false, ): Promise { - // istanbul ignore if if (!force && nodeVersions) { return nodeVersions; } const res = await fetch('https://nodejs.org/dist/index.json'); - // istanbul ignore if if (!res.ok) { throw new Error(`Failed to fetch node versions: HTTP ${res.status}`); } nodeVersions = ( - ((await res.json()) as NodeVersion[]) || /* istanbul ignore next */ [] + ((await res.json()) as NodeVersion[]) || [] ).sort((a: NodeVersion, b: NodeVersion) => semverCompare( a.version.replace(RX_VERSION_CLEAN, ''), @@ -142,9 +139,8 @@ export async function nodeVersion(tag: string) { case 'latest': { return ( ( - (versions || /* istanbul ignore next */ [])[0] || - /* istanbul ignore next */ {} - ).version || /* istanbul ignore next */ '' + (versions || [])[0] || {} + ).version || '' ).replace(RX_VERSION_CLEAN, ''); } case 'stable': @@ -152,9 +148,8 @@ export async function nodeVersion(tag: string) { case 'lts/*': { return ( ( - versions.find(version => !!version.lts) || - /* istanbul ignore next */ {} - ).version || /* istanbul ignore next */ '' + versions.find(version => !!version.lts) || {} + ).version || '' ).replace(RX_VERSION_CLEAN, ''); } default: { @@ -164,8 +159,8 @@ export async function nodeVersion(tag: string) { new RegExp(`^v${tag.replace(RX_ESCAPE, '\\.')}`).test( version.version, ), - ) /* istanbul ignore next */ || {} - ).version || /* istanbul ignore next */ '' + ) || {} + ).version || '' ).replace(RX_VERSION_CLEAN, ''); } } diff --git a/src/client.ts b/src/client.ts index d57d3e4..9435634 100644 --- a/src/client.ts +++ b/src/client.ts @@ -24,7 +24,6 @@ import { type Argv } from 'yargs'; import * as generate from './client/generate.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { command: 'client', describe: 'Manage IMQ client', diff --git a/src/client/generate.ts b/src/client/generate.ts index 37cc0f3..84c25b6 100644 --- a/src/client/generate.ts +++ b/src/client/generate.ts @@ -29,7 +29,6 @@ import * as p from 'path'; import inquirer, { type QuestionCollection } from 'inquirer'; import { printError } from '../../lib/index.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, promptOverride, handler } = { command: 'generate [path]', describe: 'Generates IMQ-RPC client for a specified service', diff --git a/src/completions.ts b/src/completions.ts index 0d687c4..38afe4f 100644 --- a/src/completions.ts +++ b/src/completions.ts @@ -25,7 +25,6 @@ import { type Argv } from 'yargs'; import * as off from './completions/off.js'; import * as on from './completions/on.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { command: 'completions', describe: 'Generates completions script for your shell', diff --git a/src/completions/off.ts b/src/completions/off.ts index 99e505b..e8b6ed8 100644 --- a/src/completions/off.ts +++ b/src/completions/off.ts @@ -51,7 +51,6 @@ function printSuccess(rcFilename: string) { ); } -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'off', describe: 'Disables completions for this program in your shell', diff --git a/src/completions/on.ts b/src/completions/on.ts index d1a0ac3..8895e8a 100644 --- a/src/completions/on.ts +++ b/src/completions/on.ts @@ -94,7 +94,6 @@ function printExists(rcFilename: string) { ); } -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'on', describe: 'Enables completions for this program in your shell', diff --git a/src/config.ts b/src/config.ts index c1d3e28..51541b2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,7 +27,6 @@ import * as get from './config/get.js'; import * as init from './config/init.js'; import * as set from './config/set.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder } = { command: 'config', describe: 'Manage IMQ CLI settings', diff --git a/src/config/check.ts b/src/config/check.ts index b2ada83..e7c27d8 100644 --- a/src/config/check.ts +++ b/src/config/check.ts @@ -23,7 +23,6 @@ */ import { configEmpty } from '../../lib/index.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, handler } = { command: 'check', describe: 'Exits with 0 if config initialized, with 1 otherwise', diff --git a/src/config/get.ts b/src/config/get.ts index 7f38cf5..84f6d96 100644 --- a/src/config/get.ts +++ b/src/config/get.ts @@ -27,7 +27,6 @@ import { printError, loadConfig } from '../../lib/index.js'; let PROGRAM: string = ''; -// noinspection JSUnusedGlobalSymbols export const { command, describe, builder, handler } = { command: 'get [option]', describe: diff --git a/src/config/init.ts b/src/config/init.ts index 3afadbd..5d38e00 100644 --- a/src/config/init.ts +++ b/src/config/init.ts @@ -467,7 +467,6 @@ export async function serviceQuestions(config: IMQCLIConfig) { await dockerQuestions(config); } -// noinspection JSUnusedGlobalSymbols export const { command, describe, handler } = { command: 'init', describe: 'Interactively initializes IMQ CLI configuration file', diff --git a/src/config/set.ts b/src/config/set.ts index 08cdee5..8ccb3d0 100644 --- a/src/config/set.ts +++ b/src/config/set.ts @@ -30,7 +30,6 @@ import { prepareConfigValue, } from '../../lib/index.js'; -// noinspection JSUnusedGlobalSymbols export const { command, describe, handler } = { command: 'set