From af10863167a52159e440fe59e908f084a5e02ec1 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 11:55:09 -0700 Subject: [PATCH 01/13] docs(claude): add orientation notes and modernization plan CLAUDE.md captures repo orientation for future sessions; the plan file under .claude/plans/ tracks the modernization tasks for this branch. --- .claude/plans/2026-06-modernize.md | 82 ++++++++++++++++++++++++++++++ CLAUDE.md | 36 +++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 .claude/plans/2026-06-modernize.md create mode 100644 CLAUDE.md diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md new file mode 100644 index 0000000..c4a29b0 --- /dev/null +++ b/.claude/plans/2026-06-modernize.md @@ -0,0 +1,82 @@ +# Modernization plan — June 2026 + +Branch: `aa8y/modernize/2026/6`. + +Goals: +1. Get a working test runner on current Node. +2. Bump deps to current majors and migrate legacy patterns (callbacks → promises, CJS → ESM, Travis → GHA). +3. After upgrades, clear any residual audit findings. +4. Add tests for currently uncovered error paths — sparingly. +5. Keep each commit small, atomic, and green. + +Each task below is one commit. Commit subject in backticks. Tick the box once committed. + +--- + +- [ ] **1. `chore(test): replace istanbul with c8 coverage runner`** + - Add `c8` devDep, remove `istanbul`. + - `npm test` becomes `c8 mocha 'test/**/*Test.js' && npm run lint`. + - Baseline reason: istanbul's CJS hook breaks on Node ≥ 22 because mocha's bundled yargs is now ESM. Nothing else can be verified until this lands. + +- [ ] **2. `chore(ci): switch from Travis to GitHub Actions`** + - Add `.github/workflows/ci.yml` (matrix on current Node LTSes, runs `npm ci && npm test`). + - Delete `.travis.yml`. + - Replace Travis build badge in README with GHA badge. + +- [ ] **3. `chore: drop legacy eslint config and bump .nvmrc`** + - Delete `.eslintrc.yml` (eslint 9 uses flat config exclusively). + - Set `.nvmrc` to current Node LTS. + +- [ ] **4. `chore(deps): patch/minor bumps within current majors`** + - Bump `async`, `js-yaml`, `lodash`, `mocha`, `eslint` to latest within their current major before tackling cross-major migrations. + +- [ ] **5. `refactor!: promise-based API; drop async package`** + - `lib/manifest.js`: `getMetadata` uses `fs/promises`; helpers stay sync. + - `lib/yargs.js`: parse via `yargs.parseAsync`. + - `index.js`: `main()` and `runCommand()` return promises; bin uses top-level await. + - Drop the `async` package — sequential execution becomes a `for…of` loop with `await`. + - Tests rewritten to async/await. + - Public API change is intentional (pre-1.0). + +- [ ] **6. `chore(deps): upgrade yargs 13 → 18`** + - Update `lib/yargs.js` for the v18 API (factory `yargs()`, `parseAsync`). + +- [ ] **7. `refactor!: migrate to ESM modules`** + - `package.json` gets `"type": "module"`. + - All `.js` files become `import`/`export`. + - `eslint.config.mjs` sourceType → `module`. + - Mocha needs no config change; `.mjs`/`.js` ESM works. + +- [ ] **8. `chore(deps): upgrade chai 4 → 6`** + - chai 5+ is ESM-only — task 7 unblocks this. + - Update import + any drift in assertion syntax. + +- [ ] **9. `refactor: replace lodash with focused deep-merge helper`** + - Lodash is only used for `_.merge`. Swap in the `deepmerge` package (tiny, no transitive deps) or a hand-rolled merge. Drop full lodash dep. + +- [ ] **10. `chore(deps): clear residual audit findings`** + - At this point most vulns will already be gone (most came from istanbul + outdated direct deps). + - Run `npm audit fix` (and `--force` if a remaining advisory needs it) for whatever's left. + - Document any unresolvable findings in the commit message. + +- [ ] **11. `test: cover error paths in main(), manifest read, runCommand failure`** + - Add focused tests for the currently-uncovered branches: + - `main()` when the manifest path is missing. + - `getMetadata()` when YAML is malformed. + - `runCommand` rejection surfacing through `main()`. + - Keep it tight — one assertion per behaviour. + +- [ ] **12. `chore: bump version to 0.3.0; update README`** + - Bump `package.json` to `0.3.0`. + - Update README: remove the "pull/template not in 0.1.0" note (they're still not implemented; the framing is stale), refresh CI section, swap Travis badge. + - Final `npm audit` and `npm test` confirmation. + +--- + +## Notes / decisions captured + +- Public API: callbacks → promises is a breaking change; acceptable since pre-1.0. +- Lodash → `deepmerge`: `_.merge` mutates target and is recursive; `deepmerge` returns a new object. The codebase already passes `{}` as the target, so the behaviour is equivalent. +- ESM: mocha auto-detects ESM via `package.json` `type`. No `--experimental-vm-modules` needed on Node ≥ 22. +- The README mentions `pull` and `template` subcommands as "coming in 0.1.0 / 0.3.0" — both are still unimplemented. Out of scope for this branch; just remove the misleading future-tense lines in task 12. +- Audit fix moved to task 10 (per Arun): the cumulative upgrades clear most findings; the final `npm audit fix` is the residual sweep, not a chain reaction starter. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7c58c88 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,36 @@ +# Dave + +CLI tool that builds, tests, and pushes Docker images driven by a YAML manifest. The manifest declares contexts (Dockerfile directories) and tags per context; parameters/templates trickle from global → context → tag and are rendered with Mustache. + +## Entry points + +- `index.js` — bin (`dave`). Parses argv, loads manifest, computes the full list of shell commands, and executes them serially via `async.eachLimit(commands, 1, runCommand)`. `runCommand` uses `child_process.exec` (switched from `spawn` recently — see commit `fffa51c`). +- `lib/yargs.js` — argv parsing. Subcommands: `build | test | push | all`. Options: `--context/-c`, `--tags/-t` (array, coerced to strings), `--manifest/-m` (default `./manifest.yml`). `all` expands to `['build','test','push']`. Commands are always reordered to `build → test → push`. If `--tags` is given without `--context`, context defaults to `'.'`. +- `lib/manifest.js` — manifest reader and command builder. Walks contexts (sorted) × tags (sorted) × types (`build|test|push`), merging parameters/templates with `_.merge` and rendering Mustache. `tagKeys` lets a tag name be reused as another parameter (e.g. `sparkVersion` = tag); `tag_keys` and `tag-keys` aliases are also accepted. + +## Conventions worth knowing + +- Templates use Mustache: `{{var}}` HTML-escapes, `{{{var}}}` doesn't. `repository` values contain `/` so they always use triple braces. +- Output ordering is deterministic: types in fixed order, contexts/tags lexicographic. Tests rely on this. +- The README advertises `pull` and `template` subcommands as planned features; they are **not** implemented in `lib/yargs.js`. Don't add them to docs as working features. +- Two eslint configs exist: `eslint.config.mjs` (flat, used by eslint 9 — the active one) and `.eslintrc.yml` (legacy, unused). Edit the `.mjs` file. +- Code style enforced by eslint: 2-space indent, no semicolons, no space before function paren, unix linebreaks. + +## Commands + +``` +nvm use # picks Node 22.3.0 from .nvmrc +npm install +npm test # istanbul + mocha + lint +npm run lint # eslint only +./index.js build --context . --tags foo --manifest ./test/manifest.yml +``` + +The `npm test` script uses the legacy `istanbul` package, not nyc. + +## Test layout + +- `test/indexTest.js` — exercises `main()` end-to-end against `test/manifest.yml` and `runCommand()` against real shell commands (`true`, `false`, `ls`, pipes). +- `test/lib/manifestTest.js` — extensive unit coverage of the trickle-down merge + Mustache rendering. The expected-output arrays are the best reference for understanding ordering and inheritance. +- `test/lib/yargsTest.js` — argv parsing, command filtering/ordering, options defaults. +- `test/manifest.yml` — fixture with context `.` and tags `begin`, `end`, `wait`. From 05de451ae4293dcae557d9ab3f119f98192cc230 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 11:55:56 -0700 Subject: [PATCH 02/13] chore(test): replace istanbul with c8 coverage runner istanbul 0.4.5 is unmaintained; its CJS hook fails on current Node because mocha's bundled yargs is now ESM. Swap to c8, which reads V8's native coverage. Test script becomes: c8 mocha 'test/**/*Test.js' && npm run lint Verified: 45 tests pass; coverage report intact; lint clean. --- .claude/plans/2026-06-modernize.md | 2 +- CLAUDE.md | 2 +- package-lock.json | 939 ++++++++++++++++++----------- package.json | 4 +- 4 files changed, 597 insertions(+), 350 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index c4a29b0..ef5d203 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -13,7 +13,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co --- -- [ ] **1. `chore(test): replace istanbul with c8 coverage runner`** +- [x] **1. `chore(test): replace istanbul with c8 coverage runner`** - Add `c8` devDep, remove `istanbul`. - `npm test` becomes `c8 mocha 'test/**/*Test.js' && npm run lint`. - Baseline reason: istanbul's CJS hook breaks on Node ≥ 22 because mocha's bundled yargs is now ESM. Nothing else can be verified until this lands. diff --git a/CLAUDE.md b/CLAUDE.md index 7c58c88..f8e6785 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ npm run lint # eslint only ./index.js build --context . --tags foo --manifest ./test/manifest.yml ``` -The `npm test` script uses the legacy `istanbul` package, not nyc. +`npm test` runs `c8 mocha 'test/**/*Test.js' && npm run lint`. ## Test layout diff --git a/package-lock.json b/package-lock.json index d240b5e..1ad3787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dave", - "version": "0.3.0", + "version": "0.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dave", - "version": "0.3.0", + "version": "0.2.2", "license": "MIT", "dependencies": { "async": "^3.2.5", @@ -19,12 +19,22 @@ "dave": "index.js" }, "devDependencies": { + "c8": "^10.1.3", "chai": "^4.4.1", "eslint": "^9.5.0", - "istanbul": "^0.4.5", "mocha": "^10.4.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -151,6 +161,147 @@ "url": "https://github.com/sponsors/nzakas" } }, + "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==", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -189,12 +340,23 @@ "node": ">= 8" } }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "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==", "dev": true, - "license": "ISC" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" }, "node_modules/acorn": { "version": "8.12.0", @@ -236,17 +398,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", - "dev": true, - "license": "BSD-3-Clause OR MIT", - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -370,6 +521,112 @@ "dev": true, "license": "ISC" }, + "node_modules/c8": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", + "integrity": "sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.1", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^7.0.1", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "monocart-coverage-reports": "^2" + }, + "peerDependenciesMeta": { + "monocart-coverage-reports": { + "optional": true + } + } + }, + "node_modules/c8/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/c8/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/c8/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/c8/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/c8/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -571,10 +828,17 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -663,6 +927,13 @@ "node": ">=0.3.1" } }, + "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/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -693,38 +964,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", @@ -880,20 +1119,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1045,6 +1270,23 @@ "dev": true, "license": "ISC" }, + "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/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1156,38 +1398,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/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, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1208,6 +1418,13 @@ "he": "bin/he" } }, + "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, + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -1360,117 +1577,59 @@ "dev": true, "license": "ISC" }, - "node_modules/istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==", - "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" + "engines": { + "node": ">=8" } }, - "node_modules/istanbul/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/istanbul/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, - "license": "MIT" - }, - "node_modules/istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "*" - } - }, - "node_modules/istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/istanbul/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==", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/istanbul/node_modules/js-yaml/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, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "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": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-flag": "^1.0.0" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=0.8.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-yaml": { @@ -1516,20 +1675,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1586,6 +1731,29 @@ "get-func-name": "^2.0.1" } }, + "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/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1599,27 +1767,14 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/mocha": { @@ -1811,26 +1966,6 @@ "dev": true, "license": "MIT" }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1851,24 +1986,6 @@ "wrappy": "1" } }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -1910,6 +2027,13 @@ "node": ">=6" } }, + "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/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1933,16 +2057,6 @@ "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, - "license": "MIT", - "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", @@ -1953,6 +2067,23 @@ "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" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -1976,15 +2107,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2054,13 +2176,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, - "node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true, - "license": "MIT" - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2127,6 +2242,19 @@ ], "license": "MIT" }, + "node_modules/semver": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -2166,27 +2294,36 @@ "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "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, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, + "license": "ISC", "engines": { - "node": ">=0.8.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "license": "BSD-3-Clause" + "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/string-width": { + "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==", @@ -2214,6 +2351,20 @@ "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-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2240,6 +2391,115 @@ "node": ">=8" } }, + "node_modules/test-exclude": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz", + "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^10.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "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/test-exclude/node_modules/glob/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, + "license": "MIT" + }, + "node_modules/test-exclude/node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/test-exclude/node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -2260,19 +2520,6 @@ "node": ">=8.0" } }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -2283,20 +2530,6 @@ "node": ">=4" } }, - "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2307,17 +2540,19 @@ "punycode": "^2.1.0" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=10.12.0" } }, "node_modules/which-module": { @@ -2336,13 +2571,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -2364,6 +2592,25 @@ "node": ">=6" } }, + "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, + "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/wrap-ansi/node_modules/ansi-regex": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", diff --git a/package.json b/package.json index e8eca0a..6be31ca 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "lint": "eslint index.js lib test", - "test": "istanbul cover _mocha test/*Test.js test/**/*Test.js && npm run lint" + "test": "c8 mocha 'test/**/*Test.js' && npm run lint" }, "dependencies": { "async": "^3.2.5", @@ -18,9 +18,9 @@ "yargs": "^13.3.0" }, "devDependencies": { + "c8": "^10.1.3", "chai": "^4.4.1", "eslint": "^9.5.0", - "istanbul": "^0.4.5", "mocha": "^10.4.0" }, "repository": { From a5c81b373bb98e5cfe31a22aa199c04ee5bdc246 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 11:57:05 -0700 Subject: [PATCH 03/13] chore(ci): switch from Travis to GitHub Actions - Add .github/workflows/ci.yml with a Node 22/24 matrix. - Drop .travis.yml. - Swap the build badge in the README. - Emit lcov from c8 so codecov has something to consume. --- .claude/plans/2026-06-modernize.md | 2 +- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ .travis.yml | 13 ------------- README.md | 2 +- package.json | 2 +- 5 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index ef5d203..061bd37 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -18,7 +18,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - `npm test` becomes `c8 mocha 'test/**/*Test.js' && npm run lint`. - Baseline reason: istanbul's CJS hook breaks on Node ≥ 22 because mocha's bundled yargs is now ESM. Nothing else can be verified until this lands. -- [ ] **2. `chore(ci): switch from Travis to GitHub Actions`** +- [x] **2. `chore(ci): switch from Travis to GitHub Actions`** - Add `.github/workflows/ci.yml` (matrix on current Node LTSes, runs `npm ci && npm test`). - Delete `.travis.yml`. - Replace Travis build badge in README with GHA badge. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5b088bc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: [22, 24] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: npm + - run: npm ci + - run: npm test + - name: Upload coverage to Codecov + if: matrix.node == 24 + uses: codecov/codecov-action@v5 + with: + files: ./coverage/lcov.info + fail_ci_if_error: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c576198..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: node_js -node_js: - - stable -install: - - npm install - - npm install -g codecov -script: - - npm test -after_success: - - codecov -ignore: - - '*.md' - - '.images/' diff --git a/README.md b/README.md index dad6226..c8fdc81 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dave -[![Build Status](https://travis-ci.org/aa8y/dave.svg?branch=master)](https://travis-ci.org/aa8y/dave) +[![CI](https://github.com/aa8y/dave/actions/workflows/ci.yml/badge.svg)](https://github.com/aa8y/dave/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/aa8y/dave/branch/master/graph/badge.svg)](https://codecov.io/gh/aa8y/dave) Dave is a tool which is intended to help with Docker image authoring. It tries to fill the gaps Docker Hub has around building images, which are: diff --git a/package.json b/package.json index 6be31ca..01c3055 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "lint": "eslint index.js lib test", - "test": "c8 mocha 'test/**/*Test.js' && npm run lint" + "test": "c8 --reporter=text --reporter=lcov mocha 'test/**/*Test.js' && npm run lint" }, "dependencies": { "async": "^3.2.5", From b2a06cd9018063b0c47301f25075425711eaa6ef Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 11:57:51 -0700 Subject: [PATCH 04/13] chore: drop legacy eslint config and bump .nvmrc - Remove .eslintrc.yml; eslint 9 uses the flat config in eslint.config.mjs exclusively and ignores the legacy file. - Pin .nvmrc to Node 24 (current active LTS as of June 2026). --- .claude/plans/2026-06-modernize.md | 2 +- .eslintrc.yml | 25 ------------------------- .nvmrc | 2 +- 3 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 .eslintrc.yml diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 061bd37..af51f88 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -23,7 +23,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - Delete `.travis.yml`. - Replace Travis build badge in README with GHA badge. -- [ ] **3. `chore: drop legacy eslint config and bump .nvmrc`** +- [x] **3. `chore: drop legacy eslint config and bump .nvmrc`** - Delete `.eslintrc.yml` (eslint 9 uses flat config exclusively). - Set `.nvmrc` to current Node LTS. diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index ad9c1c5..0000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,25 +0,0 @@ -env: - es6: true - mocha: true - node: true -extends: 'eslint:recommended' -parserOptions: - ecmaVersion: 6 -rules: - indent: - - error - - 2 - linebreak-style: - - error - - unix - no-console: - - 0 - semi: - - error - - never - space-before-function-paren: - - error - - never - spaced-comment: - - error - - always diff --git a/.nvmrc b/.nvmrc index 8326e27..a45fd52 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.3.0 +24 From 9891fb95b74910488473eb8b75c67237027b0489 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:00:04 -0700 Subject: [PATCH 05/13] chore(deps): patch/minor bumps within current majors Bring every dep (other than yargs, which is on v13 latest and gets a major bump in its own commit) up to its current major's latest: - async 3.2.5 -> 3.2.6 - chai 4.4.1 -> 4.5.0 - eslint 9.5.0 -> 9.39.4 - js-yaml 4.1.0 -> 4.2.0 (clears the prototype-pollution advisory) - lodash 4.17.21 -> 4.18.1 (clears the unset/omit/template advisories) - mocha 10.4.0 -> 10.8.2 --- .claude/plans/2026-06-modernize.md | 2 +- package-lock.json | 651 ++++++++++++++--------------- package.json | 14 +- 3 files changed, 315 insertions(+), 352 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index af51f88..1b4bb94 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -27,7 +27,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - Delete `.eslintrc.yml` (eslint 9 uses flat config exclusively). - Set `.nvmrc` to current Node LTS. -- [ ] **4. `chore(deps): patch/minor bumps within current majors`** +- [x] **4. `chore(deps): patch/minor bumps within current majors`** - Bump `async`, `js-yaml`, `lodash`, `mocha`, `eslint` to latest within their current major before tackling cross-major migrations. - [ ] **5. `refactor!: promise-based API; drop async package`** diff --git a/package-lock.json b/package-lock.json index 1ad3787..256642f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,20 +9,20 @@ "version": "0.2.2", "license": "MIT", "dependencies": { - "async": "^3.2.5", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "async": "^3.2.6", + "js-yaml": "^4.2.0", + "lodash": "^4.18.1", "mustache": "^4.2.0", - "yargs": "^13.3.0" + "yargs": "^13.3.2" }, "bin": { "dave": "index.js" }, "devDependencies": { "c8": "^10.1.3", - "chai": "^4.4.1", - "eslint": "^9.5.0", - "mocha": "^10.4.0" + "chai": "^4.5.0", + "eslint": "^9.39.4", + "mocha": "^10.8.2" } }, "node_modules/@bcoe/v8-coverage": { @@ -36,17 +36,20 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -65,9 +68,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -75,35 +78,61 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", - "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -114,25 +143,80 @@ } }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -148,9 +232,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -302,44 +386,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -351,6 +397,13 @@ "node": ">=14" } }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -358,10 +411,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -382,9 +442,9 @@ } }, "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==", "dev": true, "license": "MIT", "dependencies": { @@ -399,9 +459,9 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "license": "MIT", "engines": { @@ -465,9 +525,9 @@ } }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, "node_modules/balanced-match": { @@ -491,9 +551,9 @@ } }, "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==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -651,9 +711,9 @@ } }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "license": "MIT", "dependencies": { @@ -663,7 +723,7 @@ "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" @@ -867,13 +927,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -918,9 +978,9 @@ "license": "MIT" }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -965,28 +1025,32 @@ } }, "node_modules/eslint": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", - "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.16.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.5.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -996,15 +1060,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -1014,12 +1074,20 @@ }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1034,9 +1102,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1046,20 +1114,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint/node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -1078,39 +1132,16 @@ "node": ">= 0.8.0" } }, - "node_modules/eslint/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1186,16 +1217,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1426,9 +1447,9 @@ "license": "MIT" }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -1436,9 +1457,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1537,16 +1558,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "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", @@ -1633,9 +1644,19 @@ } }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -1675,6 +1696,20 @@ "json-buffer": "3.0.1" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1692,9 +1727,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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.merge": { @@ -1755,9 +1790,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -1778,32 +1813,32 @@ } }, "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -1814,9 +1849,9 @@ } }, "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -1835,35 +1870,10 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "license": "ISC", "dependencies": { @@ -1873,13 +1883,6 @@ "node": ">=10" } }, - "node_modules/mocha/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==", - "dev": true, - "license": "MIT" - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1944,9 +1947,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -2107,6 +2110,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2117,27 +2130,6 @@ "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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" - } - ], - "license": "MIT" - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2186,41 +2178,6 @@ "node": ">=4" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "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" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2256,9 +2213,9 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "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": { @@ -2500,13 +2457,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2520,10 +2470,23 @@ "node": ">=8.0" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "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==", + "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", "engines": { @@ -2572,9 +2535,9 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true, "license": "Apache-2.0" }, @@ -2720,9 +2683,9 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", "engines": { diff --git a/package.json b/package.json index 01c3055..a97deb7 100644 --- a/package.json +++ b/package.json @@ -11,17 +11,17 @@ "test": "c8 --reporter=text --reporter=lcov mocha 'test/**/*Test.js' && npm run lint" }, "dependencies": { - "async": "^3.2.5", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", + "async": "^3.2.6", + "js-yaml": "^4.2.0", + "lodash": "^4.18.1", "mustache": "^4.2.0", - "yargs": "^13.3.0" + "yargs": "^13.3.2" }, "devDependencies": { "c8": "^10.1.3", - "chai": "^4.4.1", - "eslint": "^9.5.0", - "mocha": "^10.4.0" + "chai": "^4.5.0", + "eslint": "^9.39.4", + "mocha": "^10.8.2" }, "repository": { "type": "git", From 56f7759330a1bbb43eaf35a6874273de01b733f9 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:06:48 -0700 Subject: [PATCH 06/13] refactor!: promise-based API; drop async package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main() and runCommand() now return promises. Internals use async/await throughout (fs/promises in lib/manifest, a Promise wrapper around yargs parse callback, util.promisify(exec) for runCommand). The async package is no longer needed — async.eachLimit(_, 1, _) collapses into a plain for...of with await. eslint config caught up to the new code: ecmaVersion bumped to 'latest' and space-before-function-paren allows the required space between 'async' and '(' on arrow functions. BREAKING: callback-based callers of main() / runCommand() must switch to .then() or await. Pre-1.0 so this is an intentional API churn. --- .claude/plans/2026-06-modernize.md | 2 +- eslint.config.mjs | 8 +- index.js | 62 ++++++-------- lib/manifest.js | 14 +-- lib/yargs.js | 20 +++-- package-lock.json | 7 -- package.json | 1 - test/indexTest.js | 56 +++++------- test/lib/yargsTest.js | 133 +++++++---------------------- 9 files changed, 99 insertions(+), 204 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 1b4bb94..0e69bf1 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -30,7 +30,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - [x] **4. `chore(deps): patch/minor bumps within current majors`** - Bump `async`, `js-yaml`, `lodash`, `mocha`, `eslint` to latest within their current major before tackling cross-major migrations. -- [ ] **5. `refactor!: promise-based API; drop async package`** +- [x] **5. `refactor!: promise-based API; drop async package`** - `lib/manifest.js`: `getMetadata` uses `fs/promises`; helpers stay sync. - `lib/yargs.js`: parse via `yargs.parseAsync`. - `index.js`: `main()` and `runCommand()` return promises; bin uses top-level await. diff --git a/eslint.config.mjs b/eslint.config.mjs index 01c1487..3c28720 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -19,7 +19,7 @@ export default [...compat.extends("eslint:recommended"), { ...globals.node, }, - ecmaVersion: 6, + ecmaVersion: "latest", sourceType: "commonjs", }, @@ -28,7 +28,11 @@ export default [...compat.extends("eslint:recommended"), { "linebreak-style": ["error", "unix"], "no-console": [0], semi: ["error", "never"], - "space-before-function-paren": ["error", "never"], + "space-before-function-paren": ["error", { + anonymous: "never", + named: "never", + asyncArrow: "always", + }], "spaced-comment": ["error", "always"], }, }]; \ No newline at end of file diff --git a/index.js b/index.js index a1e73d9..f25ed99 100755 --- a/index.js +++ b/index.js @@ -1,53 +1,41 @@ #!/usr/bin/env node -const async = require('async') +const { promisify } = require('node:util') +const { exec: execCb } = require('node:child_process') const manifest = require('./lib/manifest') const yargs = require('./lib/yargs') -const { exec } = require('child_process') +const exec = promisify(execCb) -function runCommand(command, cb) { +async function runCommand(command) { console.log(`Running: ${command}`) - exec(command, (err, stdout, stderr) => { - console.log(stdout) - console.error(stderr) - cb(err) - }) + const { stdout, stderr } = await exec(command) + console.log(stdout) + console.error(stderr) } -function main(args, cb) { - if (typeof args === 'function') { - cb = args - args = process.argv.slice(2) + +async function main(args = process.argv.slice(2)) { + const argv = await yargs.argv(args) + const cmds = yargs.commands(argv) + const opts = yargs.options(argv) + + const metadata = await manifest.getMetadata(opts.manifest) + const commands = manifest.getCommands(metadata, cmds, opts.context, opts.tags) + + for (const command of commands) { + await runCommand(command) } - yargs.argv(args, (err, argv) => { - if (err) return cb(err, 'Command-line arguments could not be parsed.') - const cmds = yargs.commands(argv) - const opts = yargs.options(argv) - - manifest.getMetadata(opts.manifest, (err, metadata) => { - if (err) return cb(err, 'Could not read metadata from the manifest.') - const commands = manifest.getCommands(metadata, cmds, opts.context, opts.tags) - - async.eachLimit(commands, 1, runCommand, (err) => { - if (err) return cb(err, 'Commands could not be executed successfully.') - cb(null, 'All commands completed successfully.') - }) - }) - }) + return 'All commands completed successfully.' } -module.exports = { - main, - runCommand -} +module.exports = { main, runCommand } -// Enable script-like invocation. if (module === require.main) { - module.exports.main((err, msg) => { - if (err) { - console.log(`${msg} ${err.message}`) + main().then( + (msg) => console.log(msg), + (err) => { + console.error(err.message) process.exit(1) } - console.log(msg) - }) + ) } diff --git a/lib/manifest.js b/lib/manifest.js index e56ad2b..3339533 100644 --- a/lib/manifest.js +++ b/lib/manifest.js @@ -1,17 +1,11 @@ -const fs = require('fs') +const fs = require('node:fs/promises') const mustache = require('mustache') const yaml = require('js-yaml') const _ = require('lodash') -function getMetadata(manifestFile, cb) { - if (typeof manifestFile == 'function') { - cb = manifestFile - manifestFile = './manifest.yml' - } - fs.readFile(manifestFile, 'utf8', (err, yamlStr) => { - if (err) return cb(err) - cb(null, yaml.load(yamlStr)) - }) +async function getMetadata(manifestFile = './manifest.yml') { + const yamlStr = await fs.readFile(manifestFile, 'utf8') + return yaml.load(yamlStr) } function getGlobalDefaults(metadata) { const parameters = metadata.parameters || {} diff --git a/lib/yargs.js b/lib/yargs.js index df0de4d..e60ad6e 100644 --- a/lib/yargs.js +++ b/lib/yargs.js @@ -25,15 +25,17 @@ const builder = (yargs) => { }) } -function argv(args, cb) { - yargs - .usage('$0 [options]') - .command('build', 'Builds docker image(s).', builder) - .command('push', 'Pushes already built docker image(s).', builder) - .command('test', 'Tests already built docker image(s).', builder) - .command('all', 'Builds, tests and pushes docker images(s).', builder) - .help() - .parse(args, cb) +function argv(args) { + return new Promise((resolve, reject) => { + yargs + .usage('$0 [options]') + .command('build', 'Builds docker image(s).', builder) + .command('push', 'Pushes already built docker image(s).', builder) + .command('test', 'Tests already built docker image(s).', builder) + .command('all', 'Builds, tests and pushes docker images(s).', builder) + .help() + .parse(args, (err, parsed) => err ? reject(err) : resolve(parsed)) + }) } function commands(argv) { const cmds = argv._.filter((c) => VALID_COMMANDS.includes(c)) diff --git a/package-lock.json b/package-lock.json index 256642f..1221e5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "0.2.2", "license": "MIT", "dependencies": { - "async": "^3.2.6", "js-yaml": "^4.2.0", "lodash": "^4.18.1", "mustache": "^4.2.0", @@ -524,12 +523,6 @@ "node": "*" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", diff --git a/package.json b/package.json index a97deb7..1e61897 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "test": "c8 --reporter=text --reporter=lcov mocha 'test/**/*Test.js' && npm run lint" }, "dependencies": { - "async": "^3.2.6", "js-yaml": "^4.2.0", "lodash": "^4.18.1", "mustache": "^4.2.0", diff --git a/test/indexTest.js b/test/indexTest.js index 5a69ff6..6f1ecaf 100644 --- a/test/indexTest.js +++ b/test/indexTest.js @@ -3,53 +3,35 @@ const index = require('../index') const { assert } = require('chai') describe('index', () => { - // TODO: Use sinon to stub out console.log for main() and runCommand() tests. describe('main()', () => { - it('should parse arguments and use the manifest to run commands.', (done) => { - index.main('build --context . --tags begin end --manifest ./test/manifest.yml', (err, msg) => { - assert.isNull(err) - assert.equal(msg, 'All commands completed successfully.') - done() - }) + it('should parse arguments and use the manifest to run commands.', async () => { + const msg = await index.main('build --context . --tags begin end --manifest ./test/manifest.yml') + assert.equal(msg, 'All commands completed successfully.') }) }) describe('runCommand()', () => { - it('is able to run commands without arguments.', (done) => { - index.runCommand('true', (err) => { - assert.isNull(err) - done() - }) + it('is able to run commands without arguments.', async () => { + await index.runCommand('true') }) - it('can fail running a command.', (done) => { - index.runCommand('false', (err) => { - assert.isNotNull(err) + it('can fail running a command.', async () => { + try { + await index.runCommand('false') + assert.fail('expected rejection') + } catch (err) { assert.equal(err.message.trim(), 'Command failed: false') - done() - }) + } }) - it('is able to run commands with arguments.', (done) => { - index.runCommand('ls -l /tmp', (err) => { - assert.isNull(err) - done() - }) + it('is able to run commands with arguments.', async () => { + await index.runCommand('ls -l /tmp') }) - it('is able to run chained commands.', (done) => { - index.runCommand('true && ls', (err) => { - assert.isNull(err) - done() - }) + it('is able to run chained commands.', async () => { + await index.runCommand('true && ls') }) - it('is able to run piped commands.', (done) => { - index.runCommand('ls -lrt /bin | tail', (err) => { - assert.isNull(err) - done() - }) + it('is able to run piped commands.', async () => { + await index.runCommand('ls -lrt /bin | tail') }) - it('is able to run commands with special characters.', (done) => { - index.runCommand('ls -l /bin/ch*', (err) => { - assert.isNull(err) - done() - }) + it('is able to run commands with special characters.', async () => { + await index.runCommand('ls -l /bin/ch*') }) }) }) diff --git a/test/lib/yargsTest.js b/test/lib/yargsTest.js index 8e26692..9a05cd3 100644 --- a/test/lib/yargsTest.js +++ b/test/lib/yargsTest.js @@ -4,120 +4,53 @@ const { assert } = require('chai') describe('lib/yargs', () => { describe('commands()', () => { - it('returns the commands passed.', () => { - yargs.argv('build test', (err, argv) => { - assert.isNull(err) - - const expected = ['build', 'test'] - const computed = yargs.commands(argv) - assert.deepEqual(computed, expected) - }) + it('returns the commands passed.', async () => { + const argv = await yargs.argv('build test') + assert.deepEqual(yargs.commands(argv), ['build', 'test']) }) - it('filters invalid commands.', () => { - yargs.argv('foo bar baz build', (err, argv) => { - assert.isNull(err) - - const expected = ['build'] - const computed = yargs.commands(argv) - assert.deepEqual(computed, expected) - }) + it('filters invalid commands.', async () => { + const argv = await yargs.argv('foo bar baz build') + assert.deepEqual(yargs.commands(argv), ['build']) }) - it('returns the commands sorted in the order they should be executed.', () => { - yargs.argv('build push test', (err, argv) => { - assert.isNull(err) - - const expected = ['build', 'test', 'push'] - const computed = yargs.commands(argv) - assert.deepEqual(computed, expected) - }) + it('returns the commands sorted in the order they should be executed.', async () => { + const argv = await yargs.argv('build push test') + assert.deepEqual(yargs.commands(argv), ['build', 'test', 'push']) }) - it(`returns the all commands when the literal 'all' command is passed.`, () => { - yargs.argv('all', (err, argv) => { - assert.isNull(err) - - const expected = ['build', 'test', 'push'] - const computed = yargs.commands(argv) - assert.deepEqual(computed, expected) - }) + it(`returns the all commands when the literal 'all' command is passed.`, async () => { + const argv = await yargs.argv('all') + assert.deepEqual(yargs.commands(argv), ['build', 'test', 'push']) }) - it(`'all' should take precedent over all other commands.`, () => { - yargs.argv('all build template', (err, argv) => { - assert.isNull(err) - - const expected = ['build', 'test', 'push'] - const computed = yargs.commands(argv) - assert.deepEqual(computed, expected) - }) + it(`'all' should take precedent over all other commands.`, async () => { + const argv = await yargs.argv('all build template') + assert.deepEqual(yargs.commands(argv), ['build', 'test', 'push']) }) }) describe('options()', () => { const manifest = './manifest.yml' - it('returns an object with default manifest if no arguments are passed.', () => { - yargs.argv('build', (err, argv) => { - assert.isNull(err) - - const expected = { manifest } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it('returns an object with default manifest if no arguments are passed.', async () => { + const argv = await yargs.argv('build') + assert.deepEqual(yargs.options(argv), { manifest }) }) - it('returns the context when present.', () => { - yargs.argv('build --context .', (err, argv) => { - assert.isNull(err) - - const expected = { context: '.', manifest } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it('returns the context when present.', async () => { + const argv = await yargs.argv('build --context .') + assert.deepEqual(yargs.options(argv), { context: '.', manifest }) }) - it('returns the context and tags when both are present.', () => { - yargs.argv('build --context . --tags 1.0.2 1.0.3', (err, argv) => { - assert.isNull(err) - - const expected = { - context: '.', - manifest, - tags: ['1.0.2', '1.0.3'] - } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it('returns the context and tags when both are present.', async () => { + const argv = await yargs.argv('build --context . --tags 1.0.2 1.0.3') + assert.deepEqual(yargs.options(argv), { context: '.', manifest, tags: ['1.0.2', '1.0.3'] }) }) - it('returns string tags even when numbers are passed.', () => { - yargs.argv('build --context . --tags 1.0 1', (err, argv) => { - assert.isNull(err) - - const expected = { - context: '.', - manifest, - tags: ['1.0', '1'] - } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it('returns string tags even when numbers are passed.', async () => { + const argv = await yargs.argv('build --context . --tags 1.0 1') + assert.deepEqual(yargs.options(argv), { context: '.', manifest, tags: ['1.0', '1'] }) }) - it(`returns an object with default context '.' if tags are passed but no context is.`, () => { - yargs.argv('build --tags 1.0 1', (err, argv) => { - assert.isNull(err) - - const expected = { - context: '.', - manifest, - tags: ['1.0', '1'] - } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it(`returns an object with default context '.' if tags are passed but no context is.`, async () => { + const argv = await yargs.argv('build --tags 1.0 1') + assert.deepEqual(yargs.options(argv), { context: '.', manifest, tags: ['1.0', '1'] }) }) - it('returns the given manifest path when passed.', () => { - yargs.argv('build --manifest /config/manifest.yaml', (err, argv) => { - assert.isNull(err) - - const expected = { manifest: '/config/manifest.yaml' } - const computed = yargs.options(argv) - assert.deepEqual(computed, expected) - }) + it('returns the given manifest path when passed.', async () => { + const argv = await yargs.argv('build --manifest /config/manifest.yaml') + assert.deepEqual(yargs.options(argv), { manifest: '/config/manifest.yaml' }) }) }) }) From bcc53c49c8a87c55900b201c4912ad468503ee8b Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:11:52 -0700 Subject: [PATCH 07/13] refactor!: migrate to ESM modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - package.json: type: "module". - All source and test files use import/export. - ESM import paths include the .js extension as required. - eslint sourceType bumped to "module". - Bin guard switches from `module === require.main` to comparing process.argv[1] against fileURLToPath(import.meta.url). Reordered before the yargs bump because yargs 18 is ESM-only and can no longer be require()'d. CJS consumers must migrate too — pre-1.0. --- .claude/plans/2026-06-modernize.md | 9 +++--- eslint.config.mjs | 2 +- index.js | 18 ++++++------ lib/manifest.js | 47 ++++++++++-------------------- lib/yargs.js | 10 +++---- package-lock.json | 38 +++++++++--------------- package.json | 1 + test/indexTest.js | 5 ++-- test/lib/manifestTest.js | 5 ++-- test/lib/yargsTest.js | 5 ++-- 10 files changed, 56 insertions(+), 84 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 0e69bf1..b1c2f0e 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -38,14 +38,15 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - Tests rewritten to async/await. - Public API change is intentional (pre-1.0). -- [ ] **6. `chore(deps): upgrade yargs 13 → 18`** - - Update `lib/yargs.js` for the v18 API (factory `yargs()`, `parseAsync`). - -- [ ] **7. `refactor!: migrate to ESM modules`** +- [x] **6. `refactor!: migrate to ESM modules`** - `package.json` gets `"type": "module"`. - All `.js` files become `import`/`export`. - `eslint.config.mjs` sourceType → `module`. - Mocha needs no config change; `.mjs`/`.js` ESM works. + - **Reordered before yargs**: yargs 18 is ESM-only, so it can't be `require()`'d. ESM must land first. + +- [ ] **7. `chore(deps): upgrade yargs 13 → 18`** + - Update `lib/yargs.js` for the v18 API (factory `yargs()`, `parseAsync`). - [ ] **8. `chore(deps): upgrade chai 4 → 6`** - chai 5+ is ESM-only — task 7 unblocks this. diff --git a/eslint.config.mjs b/eslint.config.mjs index 3c28720..0cd9ee0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -20,7 +20,7 @@ export default [...compat.extends("eslint:recommended"), { }, ecmaVersion: "latest", - sourceType: "commonjs", + sourceType: "module", }, rules: { diff --git a/index.js b/index.js index f25ed99..9add1a8 100755 --- a/index.js +++ b/index.js @@ -1,20 +1,22 @@ #!/usr/bin/env node -const { promisify } = require('node:util') -const { exec: execCb } = require('node:child_process') -const manifest = require('./lib/manifest') -const yargs = require('./lib/yargs') +import { promisify } from 'node:util' +import { exec as execCb } from 'node:child_process' +import { fileURLToPath } from 'node:url' + +import * as manifest from './lib/manifest.js' +import * as yargs from './lib/yargs.js' const exec = promisify(execCb) -async function runCommand(command) { +export async function runCommand(command) { console.log(`Running: ${command}`) const { stdout, stderr } = await exec(command) console.log(stdout) console.error(stderr) } -async function main(args = process.argv.slice(2)) { +export async function main(args = process.argv.slice(2)) { const argv = await yargs.argv(args) const cmds = yargs.commands(argv) const opts = yargs.options(argv) @@ -28,9 +30,7 @@ async function main(args = process.argv.slice(2)) { return 'All commands completed successfully.' } -module.exports = { main, runCommand } - -if (module === require.main) { +if (process.argv[1] === fileURLToPath(import.meta.url)) { main().then( (msg) => console.log(msg), (err) => { diff --git a/lib/manifest.js b/lib/manifest.js index 3339533..f06c31d 100644 --- a/lib/manifest.js +++ b/lib/manifest.js @@ -1,18 +1,18 @@ -const fs = require('node:fs/promises') -const mustache = require('mustache') -const yaml = require('js-yaml') -const _ = require('lodash') +import fs from 'node:fs/promises' +import mustache from 'mustache' +import yaml from 'js-yaml' +import _ from 'lodash' -async function getMetadata(manifestFile = './manifest.yml') { +export async function getMetadata(manifestFile = './manifest.yml') { const yamlStr = await fs.readFile(manifestFile, 'utf8') return yaml.load(yamlStr) } -function getGlobalDefaults(metadata) { +export function getGlobalDefaults(metadata) { const parameters = metadata.parameters || {} const templates = metadata.templates || {} return { parameters, templates } } -function getDefaults(childMeta, parentDefaults, type) { +export function getDefaults(childMeta, parentDefaults, type) { parentDefaults = parentDefaults || {} if (type) { return _.merge({}, parentDefaults[type], childMeta[type]) @@ -22,11 +22,11 @@ function getDefaults(childMeta, parentDefaults, type) { return { parameters, templates } } } -function getContexts(metadata) { +export function getContexts(metadata) { const contextMetaLookup = metadata.contexts || {} return Object.keys(contextMetaLookup).sort() } -function getContextMeta(context, metadata) { +export function getContextMeta(context, metadata) { if (metadata.contexts && context in metadata.contexts) { const globalDefaults = getGlobalDefaults(metadata) const contextMeta = metadata.contexts[context] @@ -35,29 +35,29 @@ function getContextMeta(context, metadata) { } return {} } -function getTags(contextMeta) { +export function getTags(contextMeta) { if (!contextMeta.tags) return [] return Object.keys(contextMeta.tags).sort() } -function getTagKeys(contextMeta) { +export function getTagKeys(contextMeta) { const tagKeys = contextMeta.tagKeys || contextMeta['tag_keys'] || contextMeta['tag-keys'] || [] return ['tag'].concat(tagKeys).sort() } -function getTagKeyMeta(contextMeta, tag) { +export function getTagKeyMeta(contextMeta, tag) { const keys = getTagKeys(contextMeta) return keys.reduce((acc, k) => { acc[k] = tag return acc }, {}) } -function getTagMeta(tag, contextMeta) { +export function getTagMeta(tag, contextMeta) { if (!contextMeta.tags) return {} const tagMeta = { parameters: contextMeta.tags[tag] } const tagKeyMeta = { parameters: getTagKeyMeta(contextMeta, tag) } const defaults = getDefaults(tagKeyMeta, contextMeta) return getDefaults(tagMeta, defaults) } -function getTagCommands(tagMeta, types) { +export function getTagCommands(tagMeta, types) { types = types && types.length > 0 ? types : ['build', 'test', 'push'] const { parameters, templates } = tagMeta @@ -69,7 +69,7 @@ function getTagCommands(tagMeta, types) { return commands }, {}) } -function getContextCommands(contextMeta, types, tags) { +export function getContextCommands(contextMeta, types, tags) { types = types && types.length > 0 ? types : ['build', 'test', 'push'] tags = tags && tags.length > 0 ? tags : getTags(contextMeta) @@ -86,7 +86,7 @@ function getContextCommands(contextMeta, types, tags) { return contextCommands }, {}) } -function getCommands(metadata, types, context, tags) { +export function getCommands(metadata, types, context, tags) { types = types && types.length > 0 ? types : ['build', 'test', 'push'] const contexts = context ? [context] : getContexts(metadata) @@ -106,18 +106,3 @@ function getCommands(metadata, types, context, tags) { return allCommands.concat(commands[type]) }, []) } - -module.exports = { - getCommands, - getContextCommands, - getContextMeta, - getContexts, - getDefaults, - getGlobalDefaults, - getMetadata, - getTagCommands, - getTagKeyMeta, - getTagKeys, - getTagMeta, - getTags -} diff --git a/lib/yargs.js b/lib/yargs.js index e60ad6e..faf9a17 100644 --- a/lib/yargs.js +++ b/lib/yargs.js @@ -1,4 +1,4 @@ -const yargs = require('yargs') +import yargs from 'yargs' const VALID_COMMANDS = ['all', 'build', 'test', 'push'] @@ -25,7 +25,7 @@ const builder = (yargs) => { }) } -function argv(args) { +export function argv(args) { return new Promise((resolve, reject) => { yargs .usage('$0 [options]') @@ -37,7 +37,7 @@ function argv(args) { .parse(args, (err, parsed) => err ? reject(err) : resolve(parsed)) }) } -function commands(argv) { +export function commands(argv) { const cmds = argv._.filter((c) => VALID_COMMANDS.includes(c)) if (cmds.includes('all')) return ['build', 'test', 'push'] @@ -49,7 +49,7 @@ function commands(argv) { return lIndex - rIndex }) } -function options(argv) { +export function options(argv) { const { context, manifest, tags } = argv // If tags are passed but a context is not, default it to '.', else use what has been passed. const optional = tags ? ( @@ -58,5 +58,3 @@ function options(argv) { return Object.assign({ manifest }, optional) } - -module.exports = { argv, builder, commands, options } diff --git a/package-lock.json b/package-lock.json index 1221e5d..e1a8fcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -641,16 +641,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/c8/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/c8/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -1910,16 +1900,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/mocha/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -2652,10 +2632,14 @@ "license": "ISC" }, "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==", - "license": "ISC" + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/yargs": { "version": "13.3.2", @@ -2830,6 +2814,12 @@ "node": ">=6" } }, + "node_modules/yargs/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==", + "license": "ISC" + }, "node_modules/yargs/node_modules/yargs-parser": { "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", diff --git a/package.json b/package.json index 1e61897..535e80a 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "dave", "version": "0.2.2", "description": "A helper to build, test and push Docker images and template Dockerfiles.", + "type": "module", "main": "index.js", "bin": { "dave": "./index.js" diff --git a/test/indexTest.js b/test/indexTest.js index 6f1ecaf..70fbcc8 100644 --- a/test/indexTest.js +++ b/test/indexTest.js @@ -1,6 +1,5 @@ -const index = require('../index') - -const { assert } = require('chai') +import { assert } from 'chai' +import * as index from '../index.js' describe('index', () => { describe('main()', () => { diff --git a/test/lib/manifestTest.js b/test/lib/manifestTest.js index 3fd0516..8cda95b 100644 --- a/test/lib/manifestTest.js +++ b/test/lib/manifestTest.js @@ -1,6 +1,5 @@ -const manifest = require('../../lib/manifest') - -const { assert } = require('chai') +import { assert } from 'chai' +import * as manifest from '../../lib/manifest.js' const repository = 'aa8y/foo' const build = 'docker build -t {{{repository}}}:{{tag}} --build-arg BAR={{bar}} {{context}}' diff --git a/test/lib/yargsTest.js b/test/lib/yargsTest.js index 9a05cd3..6947e00 100644 --- a/test/lib/yargsTest.js +++ b/test/lib/yargsTest.js @@ -1,6 +1,5 @@ -const yargs = require('../../lib/yargs') - -const { assert } = require('chai') +import { assert } from 'chai' +import * as yargs from '../../lib/yargs.js' describe('lib/yargs', () => { describe('commands()', () => { From 01f0261c4b5eae9a29c01852a0ada4cb45427afb Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:14:32 -0700 Subject: [PATCH 08/13] =?UTF-8?q?chore(deps):=20upgrade=20yargs=2013=20?= =?UTF-8?q?=E2=86=92=2018?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API changes: - yargs is now a factory: `yargs(args).command(...).parseAsync()`. - parseAsync() replaces the callback Promise wrapper. - Tags option needs `string: true` because yargs 18 coerces numeric-looking array values to Numbers before custom .coerce() runs (1.0 was collapsing to 1). With `string: true` the original token is preserved and the old .coerce() round-trip is unneeded. --- .claude/plans/2026-06-modernize.md | 2 +- lib/yargs.js | 24 +- package-lock.json | 390 ++++++++++------------------- package.json | 2 +- 4 files changed, 151 insertions(+), 267 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index b1c2f0e..895d5be 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -45,7 +45,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - Mocha needs no config change; `.mjs`/`.js` ESM works. - **Reordered before yargs**: yargs 18 is ESM-only, so it can't be `require()`'d. ESM must land first. -- [ ] **7. `chore(deps): upgrade yargs 13 → 18`** +- [x] **7. `chore(deps): upgrade yargs 13 → 18`** - Update `lib/yargs.js` for the v18 API (factory `yargs()`, `parseAsync`). - [ ] **8. `chore(deps): upgrade chai 4 → 6`** diff --git a/lib/yargs.js b/lib/yargs.js index faf9a17..6f24cc6 100644 --- a/lib/yargs.js +++ b/lib/yargs.js @@ -12,10 +12,8 @@ const builder = (yargs) => { .option('tags', { alias: 't', describe: 'Tag in the context for which the command needs to be run.', - type: 'array' - }) - .coerce('tags', (tags) => { - return tags.map((tag) => tag.toString()) + type: 'array', + string: true }) .option('manifest', { alias: 'm', @@ -26,16 +24,14 @@ const builder = (yargs) => { } export function argv(args) { - return new Promise((resolve, reject) => { - yargs - .usage('$0 [options]') - .command('build', 'Builds docker image(s).', builder) - .command('push', 'Pushes already built docker image(s).', builder) - .command('test', 'Tests already built docker image(s).', builder) - .command('all', 'Builds, tests and pushes docker images(s).', builder) - .help() - .parse(args, (err, parsed) => err ? reject(err) : resolve(parsed)) - }) + return yargs(args) + .usage('$0 [options]') + .command('build', 'Builds docker image(s).', builder) + .command('push', 'Pushes already built docker image(s).', builder) + .command('test', 'Tests already built docker image(s).', builder) + .command('all', 'Builds, tests and pushes docker images(s).', builder) + .help() + .parseAsync() } export function commands(argv) { const cmds = argv._.filter((c) => VALID_COMMANDS.includes(c)) diff --git a/package-lock.json b/package-lock.json index e1a8fcf..43f65b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "js-yaml": "^4.2.0", "lodash": "^4.18.1", "mustache": "^4.2.0", - "yargs": "^13.3.2" + "yargs": "^18.0.0" }, "bin": { "dave": "index.js" @@ -784,64 +784,67 @@ } }, "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "license": "ISC", "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" } }, "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "license": "MIT" }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/color-convert": { @@ -988,7 +991,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1322,6 +1324,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -1994,15 +2008,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "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", @@ -2130,17 +2135,12 @@ "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==", + "dev": true, "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==", - "license": "ISC" - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2195,12 +2195,6 @@ "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==", - "license": "ISC" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2491,12 +2485,6 @@ "node": ">=10.12.0" } }, - "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==", - "license": "ISC" - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -2515,17 +2503,20 @@ "license": "Apache-2.0" }, "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi-cjs": { @@ -2548,80 +2539,65 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "license": "MIT" }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -2635,28 +2611,26 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "license": "MIT", "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.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": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { @@ -2686,148 +2660,62 @@ } }, "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/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==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "license": "MIT" }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/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/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/yargs/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==", - "license": "ISC" - }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yocto-queue": { diff --git a/package.json b/package.json index 535e80a..87f5d4e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "js-yaml": "^4.2.0", "lodash": "^4.18.1", "mustache": "^4.2.0", - "yargs": "^13.3.2" + "yargs": "^18.0.0" }, "devDependencies": { "c8": "^10.1.3", From 073a1d8f887ed743f511f46df50944ec8cc2ffc8 Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:15:45 -0700 Subject: [PATCH 09/13] =?UTF-8?q?chore(deps):=20upgrade=20chai=204=20?= =?UTF-8?q?=E2=86=92=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ESM migration in the previous commit unblocks chai 5+ (ESM-only). Existing assert.* usage works unchanged on chai 6. --- .claude/plans/2026-06-modernize.md | 2 +- package-lock.json | 95 ++---------------------------- package.json | 2 +- 3 files changed, 7 insertions(+), 92 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 895d5be..e906646 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -48,7 +48,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - [x] **7. `chore(deps): upgrade yargs 13 → 18`** - Update `lib/yargs.js` for the v18 API (factory `yargs()`, `parseAsync`). -- [ ] **8. `chore(deps): upgrade chai 4 → 6`** +- [x] **8. `chore(deps): upgrade chai 4 → 6`** - chai 5+ is ESM-only — task 7 unblocks this. - Update import + any drift in assertion syntax. diff --git a/package-lock.json b/package-lock.json index 43f65b6..a8be62e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ }, "devDependencies": { "c8": "^10.1.3", - "chai": "^4.5.0", + "chai": "^6.2.2", "eslint": "^9.39.4", "mocha": "^10.8.2" } @@ -513,16 +513,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -694,22 +684,13 @@ } }, "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, "engines": { - "node": ">=4" + "node": ">=18" } }, "node_modules/chalk": { @@ -729,19 +710,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -943,19 +911,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1336,16 +1291,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -1753,16 +1698,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -2065,16 +2000,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2450,16 +2375,6 @@ "node": ">= 0.8.0" } }, - "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", - "engines": { - "node": ">=4" - } - }, "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 87f5d4e..6a1dcc3 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "c8": "^10.1.3", - "chai": "^4.5.0", + "chai": "^6.2.2", "eslint": "^9.39.4", "mocha": "^10.8.2" }, From e717b1ac5e2dac35580b04c5a07c3e1a45e705da Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:18:20 -0700 Subject: [PATCH 10/13] refactor: replace lodash with focused deep-merge helper Lodash was a 70KB dep used in exactly two call sites for _.merge. Inline a 13-line deepMerge in lib/manifest.js with matching semantics (plain-object recursion, source-wins-on-overlap, null source skipped) and drop lodash from dependencies. --- .claude/plans/2026-06-modernize.md | 2 +- lib/manifest.js | 21 ++++++++++++++++++--- package-lock.json | 7 ------- package.json | 1 - 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index e906646..20054ad 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -52,7 +52,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - chai 5+ is ESM-only — task 7 unblocks this. - Update import + any drift in assertion syntax. -- [ ] **9. `refactor: replace lodash with focused deep-merge helper`** +- [x] **9. `refactor: replace lodash with focused deep-merge helper`** - Lodash is only used for `_.merge`. Swap in the `deepmerge` package (tiny, no transitive deps) or a hand-rolled merge. Drop full lodash dep. - [ ] **10. `chore(deps): clear residual audit findings`** diff --git a/lib/manifest.js b/lib/manifest.js index f06c31d..397085b 100644 --- a/lib/manifest.js +++ b/lib/manifest.js @@ -1,7 +1,22 @@ import fs from 'node:fs/promises' import mustache from 'mustache' import yaml from 'js-yaml' -import _ from 'lodash' + +function isPlainObject(v) { + return v !== null && typeof v === 'object' && !Array.isArray(v) +} +function deepMerge(...sources) { + const result = {} + for (const source of sources) { + if (!source) continue + for (const key of Object.keys(source)) { + const sv = source[key] + const rv = result[key] + result[key] = isPlainObject(sv) && isPlainObject(rv) ? deepMerge(rv, sv) : sv + } + } + return result +} export async function getMetadata(manifestFile = './manifest.yml') { const yamlStr = await fs.readFile(manifestFile, 'utf8') @@ -15,7 +30,7 @@ export function getGlobalDefaults(metadata) { export function getDefaults(childMeta, parentDefaults, type) { parentDefaults = parentDefaults || {} if (type) { - return _.merge({}, parentDefaults[type], childMeta[type]) + return deepMerge(parentDefaults[type], childMeta[type]) } else { const parameters = getDefaults(childMeta, parentDefaults, 'parameters') const templates = getDefaults(childMeta, parentDefaults, 'templates') @@ -31,7 +46,7 @@ export function getContextMeta(context, metadata) { const globalDefaults = getGlobalDefaults(metadata) const contextMeta = metadata.contexts[context] const defaults = getDefaults(contextMeta, globalDefaults) - return _.merge({ parameters: { context }}, contextMeta, defaults) + return deepMerge({ parameters: { context }}, contextMeta, defaults) } return {} } diff --git a/package-lock.json b/package-lock.json index a8be62e..537a6d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "js-yaml": "^4.2.0", - "lodash": "^4.18.1", "mustache": "^4.2.0", "yargs": "^18.0.0" }, @@ -1668,12 +1667,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "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.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/package.json b/package.json index 6a1dcc3..f93c2f4 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ }, "dependencies": { "js-yaml": "^4.2.0", - "lodash": "^4.18.1", "mustache": "^4.2.0", "yargs": "^18.0.0" }, From bed96877875281f2909b5a0b4e829efb301c36aa Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:22:14 -0700 Subject: [PATCH 11/13] chore(deps): clear residual audit findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit npm audit fix took care of flatted, minimatch, and picomatch. Only remaining was serialize-javascript: mocha 10.x pins ^6.0.2 and the advisory ceiling is <=7.0.4, so npm audit fix offered to downgrade mocha to 8.1.3 — unacceptable. Pin via an npm override to ^7.0.5; mocha's HTML reporter doesn't exercise the API surface that changed. npm audit: 0 vulnerabilities. --- .claude/plans/2026-06-modernize.md | 2 +- package-lock.json | 65 ++++++++---------------------- package.json | 3 ++ 3 files changed, 21 insertions(+), 49 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 20054ad..6a7cbb6 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -55,7 +55,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - [x] **9. `refactor: replace lodash with focused deep-merge helper`** - Lodash is only used for `_.merge`. Swap in the `deepmerge` package (tiny, no transitive deps) or a hand-rolled merge. Drop full lodash dep. -- [ ] **10. `chore(deps): clear residual audit findings`** +- [x] **10. `chore(deps): clear residual audit findings`** - At this point most vulns will already be gone (most came from istanbul + outdated direct deps). - Run `npm audit fix` (and `--force` if a remaining advisory needs it) for whatever's left. - Document any unresolvable findings in the commit message. diff --git a/package-lock.json b/package-lock.json index 537a6d4..5b42b2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1224,9 +1224,9 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, @@ -1325,9 +1325,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -1335,9 +1335,9 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "license": "ISC", "dependencies": { @@ -1994,9 +1994,9 @@ } }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -2026,16 +2026,6 @@ "node": ">=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/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2069,27 +2059,6 @@ "node": ">=4" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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" - } - ], - "license": "MIT" - }, "node_modules/semver": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", @@ -2104,13 +2073,13 @@ } }, "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==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=20.0.0" } }, "node_modules/shebang-command": { diff --git a/package.json b/package.json index f93c2f4..8c01d2e 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,9 @@ "eslint": "^9.39.4", "mocha": "^10.8.2" }, + "overrides": { + "serialize-javascript": "^7.0.5" + }, "repository": { "type": "git", "url": "git+https://github.com/aa8y/dave.git" From d61cc2d46b9379d6a726d353d29caa8299497b3b Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:26:15 -0700 Subject: [PATCH 12/13] test: cover error paths in getMetadata and main Adds three small tests: - getMetadata loads a real manifest (happy path was previously untested at this layer; only exercised transitively via main). - getMetadata rejects with ENOENT for a missing path. - getMetadata rejects with YAMLException for malformed YAML. - main propagates ENOENT when the manifest path is bad. test/malformed.yml is a fixture for the YAML failure case. The runCommand failure path is already covered by 'can fail running a command.' on the runCommand suite. --- .claude/plans/2026-06-modernize.md | 2 +- test/indexTest.js | 8 ++++++++ test/lib/manifestTest.js | 22 ++++++++++++++++++++++ test/malformed.yml | 6 ++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/malformed.yml diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 6a7cbb6..2416ce0 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -60,7 +60,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - Run `npm audit fix` (and `--force` if a remaining advisory needs it) for whatever's left. - Document any unresolvable findings in the commit message. -- [ ] **11. `test: cover error paths in main(), manifest read, runCommand failure`** +- [x] **11. `test: cover error paths in main(), manifest read, runCommand failure`** - Add focused tests for the currently-uncovered branches: - `main()` when the manifest path is missing. - `getMetadata()` when YAML is malformed. diff --git a/test/indexTest.js b/test/indexTest.js index 70fbcc8..e42b15a 100644 --- a/test/indexTest.js +++ b/test/indexTest.js @@ -7,6 +7,14 @@ describe('index', () => { const msg = await index.main('build --context . --tags begin end --manifest ./test/manifest.yml') assert.equal(msg, 'All commands completed successfully.') }) + it('rejects when the manifest cannot be read.', async () => { + try { + await index.main('build --manifest ./test/does-not-exist.yml') + assert.fail('expected rejection') + } catch (err) { + assert.equal(err.code, 'ENOENT') + } + }) }) describe('runCommand()', () => { it('is able to run commands without arguments.', async () => { diff --git a/test/lib/manifestTest.js b/test/lib/manifestTest.js index 8cda95b..ca69478 100644 --- a/test/lib/manifestTest.js +++ b/test/lib/manifestTest.js @@ -426,4 +426,26 @@ describe('lib/manifest', () => { assert.deepEqual(computed, expected) }) }) + describe('getMetadata()', () => { + it('loads and parses the manifest at the given path.', async () => { + const metadata = await manifest.getMetadata('./test/manifest.yml') + assert.equal(metadata.parameters.greeting, 'Hello') + }) + it('rejects when the manifest file does not exist.', async () => { + try { + await manifest.getMetadata('./test/does-not-exist.yml') + assert.fail('expected rejection') + } catch (err) { + assert.equal(err.code, 'ENOENT') + } + }) + it('rejects when the YAML is malformed.', async () => { + try { + await manifest.getMetadata('./test/malformed.yml') + assert.fail('expected rejection') + } catch (err) { + assert.equal(err.name, 'YAMLException') + } + }) + }) }) diff --git a/test/malformed.yml b/test/malformed.yml new file mode 100644 index 0000000..5f9f3ea --- /dev/null +++ b/test/malformed.yml @@ -0,0 +1,6 @@ +parameters: + greeting: Hello +contexts: + .: + tags: + begin: [unclosed From a3e426ca909addcc1e3e674e68517aa08543f5de Mon Sep 17 00:00:00 2001 From: Arun Allamsetty Date: Sat, 6 Jun 2026 12:30:27 -0700 Subject: [PATCH 13/13] chore: bump to 0.3.0; refresh README and CLAUDE.md - Bump package.json version to 0.3.0 to reflect the breaking API surface (ESM + promises) and dependency churn on this branch. - README: drop pull/template from the supported-commands list (they were never implemented), trim the stale 0.1.0 sentence, replace the TravisCI example with a GitHub Actions one, and drop the pull/template line items from Future Work. - CLAUDE.md: update internal notes to match the modernized code (deepMerge, yargs 18 + string:true, c8 + lcov, no .eslintrc.yml). --- .claude/plans/2026-06-modernize.md | 2 +- CLAUDE.md | 25 +++++++------ README.md | 60 +++++++++++++++--------------- package.json | 2 +- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/.claude/plans/2026-06-modernize.md b/.claude/plans/2026-06-modernize.md index 2416ce0..1f315ee 100644 --- a/.claude/plans/2026-06-modernize.md +++ b/.claude/plans/2026-06-modernize.md @@ -67,7 +67,7 @@ Each task below is one commit. Commit subject in backticks. Tick the box once co - `runCommand` rejection surfacing through `main()`. - Keep it tight — one assertion per behaviour. -- [ ] **12. `chore: bump version to 0.3.0; update README`** +- [x] **12. `chore: bump version to 0.3.0; update README`** - Bump `package.json` to `0.3.0`. - Update README: remove the "pull/template not in 0.1.0" note (they're still not implemented; the framing is stale), refresh CI section, swap Travis badge. - Final `npm audit` and `npm test` confirmation. diff --git a/CLAUDE.md b/CLAUDE.md index f8e6785..762b286 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,36 +1,37 @@ # Dave -CLI tool that builds, tests, and pushes Docker images driven by a YAML manifest. The manifest declares contexts (Dockerfile directories) and tags per context; parameters/templates trickle from global → context → tag and are rendered with Mustache. +CLI tool that builds, tests, and pushes Docker images driven by a YAML manifest. The manifest declares contexts (Dockerfile directories) and tags per context; parameters/templates trickle from global → context → tag and are rendered with Mustache. ESM, async/await, public API returns promises. ## Entry points -- `index.js` — bin (`dave`). Parses argv, loads manifest, computes the full list of shell commands, and executes them serially via `async.eachLimit(commands, 1, runCommand)`. `runCommand` uses `child_process.exec` (switched from `spawn` recently — see commit `fffa51c`). -- `lib/yargs.js` — argv parsing. Subcommands: `build | test | push | all`. Options: `--context/-c`, `--tags/-t` (array, coerced to strings), `--manifest/-m` (default `./manifest.yml`). `all` expands to `['build','test','push']`. Commands are always reordered to `build → test → push`. If `--tags` is given without `--context`, context defaults to `'.'`. -- `lib/manifest.js` — manifest reader and command builder. Walks contexts (sorted) × tags (sorted) × types (`build|test|push`), merging parameters/templates with `_.merge` and rendering Mustache. `tagKeys` lets a tag name be reused as another parameter (e.g. `sparkVersion` = tag); `tag_keys` and `tag-keys` aliases are also accepted. +- `index.js` — bin (`dave`). Parses argv, loads manifest, computes the full list of shell commands, and awaits them one at a time in a `for…of` loop. `runCommand` is `promisify(child_process.exec)` with logging around it. +- `lib/yargs.js` — argv parsing on top of yargs 18 (`yargs(args).command(...).parseAsync()`). Subcommands: `build | test | push | all`. Options: `--context/-c`, `--tags/-t` (string array — `string: true` keeps `1.0` from collapsing to a Number), `--manifest/-m` (default `./manifest.yml`). `all` expands to `['build','test','push']`. Commands are always reordered to `build → test → push`. If `--tags` is given without `--context`, context defaults to `'.'`. +- `lib/manifest.js` — manifest reader and command builder. Walks contexts (sorted) × tags (sorted) × types (`build|test|push`), merging parameters/templates with the inline `deepMerge` helper and rendering Mustache. `tagKeys` lets a tag name be reused as another parameter (e.g. `sparkVersion` = tag); `tag_keys` and `tag-keys` aliases are also accepted. ## Conventions worth knowing - Templates use Mustache: `{{var}}` HTML-escapes, `{{{var}}}` doesn't. `repository` values contain `/` so they always use triple braces. - Output ordering is deterministic: types in fixed order, contexts/tags lexicographic. Tests rely on this. -- The README advertises `pull` and `template` subcommands as planned features; they are **not** implemented in `lib/yargs.js`. Don't add them to docs as working features. -- Two eslint configs exist: `eslint.config.mjs` (flat, used by eslint 9 — the active one) and `.eslintrc.yml` (legacy, unused). Edit the `.mjs` file. -- Code style enforced by eslint: 2-space indent, no semicolons, no space before function paren, unix linebreaks. +- `deepMerge` in `lib/manifest.js`: source-wins-on-overlap recursive merge over plain objects. Arrays and non-plain values overwrite. Null sources skip. Matches the `_.merge` semantics we relied on before; do not "fix" it to merge arrays index-wise without checking tests. +- `serialize-javascript` is pinned via npm `overrides` to clear an advisory mocha 10 hasn't picked up. Don't drop the override casually. +- Code style enforced by eslint flat config (`eslint.config.mjs`, ESM): 2-space indent, no semicolons, no space before function paren (but space allowed for `async () =>`), unix linebreaks. ## Commands ``` -nvm use # picks Node 22.3.0 from .nvmrc +nvm use # picks Node from .nvmrc (24) npm install -npm test # istanbul + mocha + lint +npm test # c8 + mocha + lint npm run lint # eslint only ./index.js build --context . --tags foo --manifest ./test/manifest.yml ``` -`npm test` runs `c8 mocha 'test/**/*Test.js' && npm run lint`. +`npm test` runs `c8 --reporter=text --reporter=lcov mocha 'test/**/*Test.js' && npm run lint`. The lcov output is what CI uploads to Codecov. ## Test layout -- `test/indexTest.js` — exercises `main()` end-to-end against `test/manifest.yml` and `runCommand()` against real shell commands (`true`, `false`, `ls`, pipes). -- `test/lib/manifestTest.js` — extensive unit coverage of the trickle-down merge + Mustache rendering. The expected-output arrays are the best reference for understanding ordering and inheritance. +- `test/indexTest.js` — exercises `main()` end-to-end against `test/manifest.yml` and `runCommand()` against real shell commands (`true`, `false`, `ls`, pipes). Also covers `main()` rejection when the manifest is missing. +- `test/lib/manifestTest.js` — extensive unit coverage of the trickle-down merge + Mustache rendering, plus `getMetadata` happy path and ENOENT / YAMLException failures. Expected-output arrays are the best reference for understanding ordering and inheritance. - `test/lib/yargsTest.js` — argv parsing, command filtering/ordering, options defaults. - `test/manifest.yml` — fixture with context `.` and tags `begin`, `end`, `wait`. +- `test/malformed.yml` — malformed YAML used by the `getMetadata` failure test. diff --git a/README.md b/README.md index c8fdc81..5f3c397 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,14 @@ Dave is a tool which is intended to help with Docker image authoring. It tries t ## Features -Dave would do perform its operations by using metadata in a [YAML](http://yaml.org/) serialized manifest file. The format is explained [later](#manifest_file). The following operations are supported. +Dave performs its operations by using metadata in a [YAML](http://yaml.org/) serialized manifest file. The format is explained [later](#manifest-file). The following operations are supported. -* **all**: This command will execute all commands except `template` in the order of `pull`, `build`, `test` and `push`. +* **all**: Executes `build`, `test` and `push` in order. * **build**: Builds one or more images using the given Docker build command template and its arguments. -* **pull**: Pulls one or more images from a Docker registry like Docker Hub. * **push**: Pushes a local image using the given Docker push command template and its arguments. -* **template**: Builds one or more `Dockerfile`s using the given template. This helps keep your `Dockerfile`s DRY. * **test**: Tests a Docker image by invoking a certain command on the image. A non-zero exit status code fails the test. -All templating is done using [Mustache](https://mustache.github.io/). `pull` and `template` commands won't be supported in the first release which would be `0.1.0`. +All templating is done using [Mustache](https://mustache.github.io/). ## Usage @@ -172,42 +170,46 @@ And while the manifest file can be named anything, the default name assumed is ` ## Examples -Here are projects where Dave is being utilized to build, test and push images. See `manifest.yml` to see how the metadata has been stored and `.travis.yml` to see how Dave can be leveraged. +Here are projects where Dave is being utilized to build, test and push images. See `manifest.yml` to see how the metadata has been stored. * [aa8y/docker-scala](https://github.com/aa8y/docker-scala): A simple Docker project with one `Dockerfile` (i.e. one context) from which all Docker images are built. ## CI Builds -### TravisCI +### GitHub Actions -Here's an example `.travis.yml` to use it with TravisCI. +Here's an example workflow to use Dave with GitHub Actions: -``` -sudo: required -services: - - docker -language: node_js -node_js: - - stable -before_install: - - git clone https://github.com/aa8y/dave.git -install: - - npm install -g dave/ -before_script: - - dave build -script: - - dave test -after_success: - - docker login -u -p "$DOCKER_PASSWORD" - - dave push +```yaml +name: Docker images + +on: + push: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + - run: npm install -g dave + - run: dave build + - run: dave test + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - run: dave push ``` -If all you want to do is build and test the images, you can ignore the `after_success` section. But if you do want to push the images after they have been tested, you would need a way to authenticate your Docker user. For that, follow [this guide](https://docs.travis-ci.com/user/docker/#Pushing-a-Docker-Image-to-a-Registry). I, personally, only like to encrypt my password as the username for Docker registry is usually also the namespace for the images. Also, I am working on acquiring the [Dave package namespace](https://www.npmjs.com/package/dave) on NPM, so that the installation process is easier. +Drop the login and `dave push` steps if you only want to build and test. ## Future Work -* Add support to pull images. This should help pulling cached layers which can make building images faster on a CI instance. I expect to add this in the 0.2.0 release. -* Add support for templating `Dockerfile`s. I expect to add this in the 0.3.0 release. * Verify the metadata read from the manifest against a schema. Maybe use [JSON Schema](http://json-schema.org/)? ## License diff --git a/package.json b/package.json index 8c01d2e..6b57bab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dave", - "version": "0.2.2", + "version": "0.3.0", "description": "A helper to build, test and push Docker images and template Dockerfiles.", "type": "module", "main": "index.js",