diff --git a/.github/workflows/npmci.yml b/.github/workflows/npmci.yml index 5691960..0a9ddfa 100644 --- a/.github/workflows/npmci.yml +++ b/.github/workflows/npmci.yml @@ -20,16 +20,16 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 - run: npm ci - run: npm test - run: npm run-script build - name: publish if: inputs.publishbuilds - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ github.ref_name }} path: | diff --git a/.gitignore b/.gitignore index d9cd699..162c9ce 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ yarn-error.log **/._* out dist +.claude/ diff --git a/.vscode/launch.json b/.vscode/launch.json index d756b8c..3633785 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "args": ["log"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -24,7 +24,7 @@ "args": ["config"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -36,7 +36,7 @@ "args": ["edit"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -48,7 +48,7 @@ "args": ["resume", "--ask"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -60,7 +60,7 @@ "args": ["stop"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -72,7 +72,7 @@ "args": ["delete"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -84,7 +84,7 @@ "args": ["config"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -96,7 +96,7 @@ "args": ["report", "--last_month", "--query=issues"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" }, { "type": "node", @@ -111,7 +111,7 @@ "--invoiceCurrency", "EUR", "--invoiceCurrencyPerHour", "50", "--invoiceVAT", "0.15", "--invoiceDate", "1.03.2021", "--invoicePositionText", "Position Text"], "program": "${workspaceFolder}/src/gtt.js", "console": "integratedTerminal", - "runtimeExecutable": "${userHome}/.nvm/versions/node/v20.10.0/bin/node" + "runtimeExecutable": "${userHome}/.nvm/versions/node/v24.18.0/bin/node" } ], } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d7b837c..c68cf56 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.16.0-alpine3.21 +FROM node:24.18.0-alpine3.23 RUN addgroup -S gtt && adduser -S gtt -G gtt USER gtt diff --git a/documentation.md b/documentation.md index 499790f..ea32673 100644 --- a/documentation.md +++ b/documentation.md @@ -28,7 +28,7 @@ ### limitations - Time tracking for other work items (e.g. tasks, epics) is currently not supported. See also https://github.com/ndu2/gitlab-time-tracker/issues/33 +Time tracking and reporting for epics is currently not supported. ## requirements @@ -58,7 +58,7 @@ token: 01234567891011 You will need node and npm to build the project -* [node.js](https://nodejs.org/en/download) version >= 22 +* [node.js](https://nodejs.org/en/download) version 24 * [npm](https://github.com/npm/npm) @@ -197,6 +197,17 @@ gtt edit You can omit the id to edit to bring up a list of the latest records to choose from. + +**In-Console edit records** + +```shell +gtt edit -i +gtt edit -i --today +gtt edit -i --this_week +gtt edit -i --last_week +gtt edit -i --week 2026-02-04 +``` + **Delete a local time record by the given id:** ```shell @@ -274,10 +285,9 @@ gtt report example-group example-group-2 --type=group gtt report --output=table gtt report --output=markdown gtt report --output=csv -gtt report --output=xlsx --file=filename.xlsx gtt report --output=invoice --file=invoice.md ``` -Defaults to `table`. `csv` and `markdown` can be printed to stdout, `xlsx` need the file parameter. +Defaults to `table`. `csv` and `markdown` can be printed to stdout. pdf output was dropped. you can use 3rd party tools to convert markdown to pdf, e.g ```shell @@ -319,6 +329,8 @@ There are some quick shorthands: gtt report --today gtt report --this_week gtt report --this_month +gtt report --last_week +gtt report --last_month_ ``` #### Include closed issues/merge requests @@ -390,7 +402,7 @@ gtt report --no_warnings gtt report --date_format="DD.MM.YYYY HH:mm:ss" ``` -*Note: [Click here](http://momentjs.com/docs/#/displaying/format/) for a further documentation on the date format.* +*Note: [Click here](https://day.js.org/docs/en/display/format) for a further documentation on the date format.* #### Set time format for the report @@ -420,9 +432,10 @@ gtt report --record_columns=user --record_columns=date --record_columns=time gtt report --issue_columns=iid --issue_columns=title --issue_columns=time_username ``` -*Note: Available columns to choose from: `id`, `iid`, `title`, `project_id`, -`project_namespace`, `description`, `labels`, `milestone`, `assignee`, `author`, -`closed`, `updated_at`, `created_at`, `due_date`, `state`, `spent`, `total_spent`, `total_estimate`* +*Note: Available columns to choose from: `id`, `iid`, `title`, `project_id`, `type`, +`project_namespace`, `project_name`, `description`, `labels`, `milestone`, `assignee`, `author`, +`closed`, `updated_at`, `created_at`, `due_date`, `state`, `spent`, `total_spent`, `total_estimate`, +`time_`, `timeSpent`. `total_estimate_s`, `total_spent_s`* *You can also include columns that show the total time spent by a specific user by following this convention: `time_username`* @@ -550,6 +563,7 @@ weeksPerMonth: 4 issueColumns: - iid - title +- spent - total_estimate # Include the given columns in the merge request table @@ -558,16 +572,21 @@ issueColumns: mergeRequestColumns: - iid - title +- spent - total_estimate # Include the given columns in the time record table # See --record_columns option for more information -# defaults to user, date, type, iid, time +# defaults to user, date, project, type, iid, title, time, note recordColumns: - user +- date +- project +- type - iid - title - time +- note # Add columns for each project member to issue and # merge request table, including their total time spent @@ -575,7 +594,7 @@ recordColumns: userColumns: true # Date format -# Click here for format options: http://momentjs.com/docs/#/displaying/format/ +# Click here for format options: https://day.js.org/docs/en/display/format # defaults to DD.MM.YYYY HH:mm:ss dateFormat: DD.MM.YYYY HH:mm:ss @@ -599,7 +618,7 @@ timeFormat: timezone: "Europe/Berlin" # Output type -# Available: csv, table, markdown, pdf, xlsx +# Available: csv, table, markdown, invoice # defaults to table output: markdown diff --git a/package-lock.json b/package-lock.json index 11cca80..53709ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,96 +1,120 @@ { "name": "gitlab-time-tracker", - "version": "1.8.1-snapshot", + "version": "1.9.0-beta0002", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-time-tracker", - "version": "1.8.1-snapshot", + "version": "1.9.0-beta0002", "license": "GPL-2.0", "dependencies": { - "@inquirer/select": "^4.2.3", - "async": "^3.2.6", - "camelcase": "^8.0.0", + "@inquirer/confirm": "^6.1.1", + "@inquirer/select": "^5.2.1", + "camelcase": "^9.0.0", "cli-cursor": "^5.0.0", "cli-table": "^0.3.11", - "colors": "^1.4.0", - "commander": "^14.0.0", + "commander": "^15.0.0", "csv-string": "^4.1.1", - "env-paths": "^3.0.0", - "find-in-files": "^0.5.0", + "dayjs": "^1.11.21", + "env-paths": "^4.0.0", "hash-sum": "^2.0.0", "hashids": "^2.3.0", + "js-yaml": "^5.2.1", "markdown-table": "^3.0.4", - "moment": "^2.30.1", - "moment-timezone": "^0.6.0", - "node-spinner": "^0.0.4", - "open": "^10.1.2", + "open": "^11.0.0", + "picocolors": "^1.1.1", "progress": "^2.0.3", - "prompt": "^1.3.0", - "read-yaml": "^1.1.0", - "shelljs": "^0.10.0", - "swissqrbill": "^4.2.0", - "tempfile": "^5.0.0", - "throttled-queue": "^2.1.4", - "underscore": "^1.13.7", - "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz" + "swissqrbill": "^4.3.0", + "tempfile": "^6.0.1", + "throttled-queue": "^3.0.0" }, "bin": { "gtt": "dist/gtt.cjs" }, "devDependencies": { - "@yao-pkg/pkg": "^6.5.1", - "chai": "^5.2.0", - "esbuild": "^0.25.4", - "mocha": "^11.4.0", - "sinon": "^20.0.0" + "@types/node": "^26.1.1", + "@yao-pkg/pkg": "^6.21.0", + "chai": "^6.2.2", + "esbuild": "^0.28.1", + "mocha": "^11.3.0", + "sinon": "^22.0.0", + "typescript": "^7.0.2" + }, + "engines": { + "node": "24" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": ">=20 <21" + "node": ">=6.9.0" } }, "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.3", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", - "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -99,35 +123,63 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, "engines": { - "node": ">=0.1.90" + "node": ">=6.9.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -137,13 +189,14 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -153,13 +206,14 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -169,13 +223,14 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -185,13 +240,14 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -201,13 +257,14 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -217,13 +274,14 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -233,13 +291,14 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -249,13 +308,14 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -265,13 +325,14 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -281,13 +342,14 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -297,13 +359,14 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -313,13 +376,14 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -329,13 +393,14 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -345,13 +410,14 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -361,13 +427,14 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -377,13 +444,14 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -393,13 +461,14 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -409,13 +478,14 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -425,13 +495,14 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -441,13 +512,14 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -456,14 +528,32 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -473,13 +563,14 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -489,13 +580,14 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -505,13 +597,14 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -520,22 +613,52 @@ "node": ">=18" } }, - "node_modules/@inquirer/core": { - "version": "10.1.13", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.13.tgz", - "integrity": "sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==", + "node_modules/@inquirer/ansi": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.7.tgz", + "integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==", + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + } + }, + "node_modules/@inquirer/confirm": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.1.1.tgz", + "integrity": "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==", + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.12", - "@inquirer/type": "^3.0.7", - "ansi-escapes": "^4.3.2", + "@inquirer/core": "^11.2.1", + "@inquirer/type": "^4.0.7" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz", + "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.7", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7", "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -547,26 +670,27 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.12.tgz", - "integrity": "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.7.tgz", + "integrity": "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" } }, "node_modules/@inquirer/select": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.3.tgz", - "integrity": "sha512-OAGhXU0Cvh0PhLz9xTF/kx6g6x+sP+PcyTiLvCrewI99P3BBeexD+VbuwkNDvqGkk3y2h5ZiWLeRP7BFlhkUDg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.1.tgz", + "integrity": "sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==", + "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.13", - "@inquirer/figures": "^1.0.12", - "@inquirer/type": "^3.0.7", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/ansi": "^2.0.7", + "@inquirer/core": "^11.2.1", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -578,11 +702,12 @@ } }, "node_modules/@inquirer/type": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.7.tgz", - "integrity": "sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.7.tgz", + "integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" }, "peerDependencies": { "@types/node": ">=18" @@ -598,6 +723,7 @@ "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", @@ -611,10 +737,11 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "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" }, @@ -627,6 +754,7 @@ "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", @@ -644,6 +772,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.4" }, @@ -652,17 +781,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -670,103 +796,78 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "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.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "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", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "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==", - "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==", - "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", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, + "node_modules/@roberts_lando/vfs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.3.tgz", + "integrity": "sha512-YjkxVSLw5WMZQoARaryRAjcxA+GbBzWMJdwYZX5oLUt9cC/gew9as4Dn7tcLzPp7BPoR221VpTZ+78TRPawnjg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 22" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", + "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1" } }, "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-10.0.2.tgz", + "integrity": "sha512-8lVwD1Df1BmzoaOLhMcGGcz/Jyr5QY2KSB75/YK1QgKzoabTeLdIVyhXNZK9ojfSKSdirbXqdbsXXqP9/Ve8+A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", "type-detect": "^4.1.0" } }, @@ -775,138 +876,551 @@ "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/@yao-pkg/pkg": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@yao-pkg/pkg/-/pkg-6.5.1.tgz", - "integrity": "sha512-z6XlySYfnqfm1AfVlBN8A3yeAQniIwL7TKQfDCGsswYSVYLt2snbRefQYsfQQ3pw5lVXrZdLqgTjzaqID9IkWA==", - "dev": true, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "devOptional": true, + "license": "MIT", "dependencies": { - "@babel/generator": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "@yao-pkg/pkg-fetch": "3.5.23", - "into-stream": "^6.0.0", - "minimist": "^1.2.6", - "multistream": "^4.1.0", - "picocolors": "^1.1.0", - "picomatch": "^4.0.2", - "prebuild-install": "^7.1.1", - "resolve": "^1.22.10", - "stream-meter": "^1.0.4", - "tar": "^7.4.3", - "tinyglobby": "^0.2.11", - "unzipper": "^0.12.3" - }, - "bin": { - "pkg": "lib-es5/bin.js" - }, + "undici-types": "~8.3.0" + } + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=18.0.0" + "node": ">=16.20.0" } }, - "node_modules/@yao-pkg/pkg-fetch": { - "version": "3.5.23", - "resolved": "https://registry.npmjs.org/@yao-pkg/pkg-fetch/-/pkg-fetch-3.5.23.tgz", - "integrity": "sha512-rn45sqVQSkcJNSBdTnYze3n+kyub4CN8aiWYlPgA9yp9FZeEF+BlpL68kSIm3HaVuANniF+7RBMH5DkC4zlHZA==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.6", - "picocolors": "^1.1.0", - "progress": "^2.0.3", - "semver": "^7.3.5", - "tar-fs": "^2.1.1", - "yargs": "^16.2.0" - }, - "bin": { - "pkg-fetch": "lib-es5/bin.js" + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 6.0.0" + "node": ">=16.20.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16.20.0" } }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=16.20.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=16.20.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=16.20.0" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/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 + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@yao-pkg/pkg": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@yao-pkg/pkg/-/pkg-6.21.0.tgz", + "integrity": "sha512-dZl2C7rdwwEI4tv7WW+Cvnl+2K8OqHKUXfNQRq3mZCTC4degoFx1jA4d5wOn9d8lHrUy58xuEt1eJD0pTddW5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "@roberts_lando/vfs": "^0.3.3", + "@yao-pkg/pkg-fetch": "3.6.4", + "esbuild": "^0.28.1", + "into-stream": "^9.1.0", + "multistream": "^4.1.0", + "picocolors": "^1.1.0", + "picomatch": "^4.0.2", + "postject": "^1.0.0-alpha.6", + "prebuild-install": "^7.1.1", + "resolve": "^1.22.10", + "resolve.exports": "^2.0.3", + "stream-meter": "^1.0.4", + "tar": "^7.5.7", + "tinyglobby": "^0.2.11", + "unzipper": "^0.12.3" + }, + "bin": { + "pkg": "lib-es5/bin.js" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@yao-pkg/pkg-fetch": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@yao-pkg/pkg-fetch/-/pkg-fetch-3.6.4.tgz", + "integrity": "sha512-2JXvS9HbMudLlzEjSaJ7bLNnF/WlTv7iaTAJp2Tk8pBsgwCyL9p4rIN8cztHlyZF7qVzr1EaBjd7DQooFk0azQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.0", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^3.1.1", + "undici": "^7.28.0", + "yargs": "^16.2.0" + }, + "bin": { + "pkg-fetch": "lib-es5/bin.js" + } + }, + "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/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "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/bare-events": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.1.tgz", + "integrity": "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.3.tgz", + "integrity": "sha512-xRgplks8SvcKkdlv2M6Z2LZmRsmqd+x0nXXGXeMEjwdibj1HSDrlnqBRLeYdMvsgCox7Bq0e+DHwfczOfsn6IA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.3.tgz", + "integrity": "sha512-fF4Q7QsyKVF5Rj0qvI8BgUNjqzC2JvQlpTaPLjVJVxYVUX5Zr9un+y3w1HmA4nNKdFmRBT8z/WmrjvXzXVerKQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz", + "integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.3.tgz", + "integrity": "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.8.1", + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz", + "integrity": "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ @@ -922,64 +1436,44 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "dev": true, + "license": "MIT" }, "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": { "balanced-match": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/buffer": { "version": "5.7.1", @@ -1000,6 +1494,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -1009,6 +1504,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", "dependencies": { "run-applescript": "^7.0.0" }, @@ -1020,30 +1516,25 @@ } }, "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz", + "integrity": "sha512-TO9xmyXTZ9HUHI8M1OnvExxYB0eYVS/1e5s7IDMTAoIcwUd+aNcFODs6Xk83mobk0velyHFQgA1yIrvYc6wclw==", + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -1051,6 +1542,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1067,6 +1559,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1074,20 +1567,12 @@ "node": ">=8" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "engines": { - "node": ">= 16" - } - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { "readdirp": "^4.0.1" }, @@ -1103,6 +1588,7 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } @@ -1111,6 +1597,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" }, @@ -1136,6 +1623,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "license": "MIT", "engines": { "node": ">=0.1.90" } @@ -1144,6 +1632,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", "engines": { "node": ">= 12" } @@ -1153,6 +1642,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -1164,6 +1654,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1172,13 +1663,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cliui/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1193,6 +1686,7 @@ "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" }, @@ -1205,6 +1699,7 @@ "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", @@ -1221,6 +1716,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1231,34 +1728,32 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" }, "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.12.0" } }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1272,23 +1767,23 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/csv-string/-/csv-string-4.1.1.tgz", "integrity": "sha512-KGvaJEZEdh2O/EVvczwbPLqJZtSQaWQ4cEJbiOJEG4ALq+dBBqNmBkRXTF4NV79V25+XYtiqbco1IWrmHLm5FQ==", + "license": "MIT", "engines": { "node": ">=12.0" } }, - "node_modules/cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "engines": { - "node": ">=0.4.0" - } + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1306,6 +1801,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1318,6 +1814,7 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -1328,28 +1825,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -1362,9 +1852,10 @@ } }, "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -1376,6 +1867,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1384,19 +1876,21 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "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": { "node": ">=0.3.1" } @@ -1406,48 +1900,100 @@ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "readable-stream": "^2.0.2" } }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "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 + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-4.0.0.tgz", + "integrity": "sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==", + "license": "MIT", + "dependencies": { + "is-safe-filename": "^0.1.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -1455,31 +2001,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/escalade": { @@ -1487,6 +2034,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1496,6 +2044,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1503,115 +2052,66 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bare-events": "^2.7.0" } }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, + "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" } }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "engines": { - "node": "> 0.1.90" - } + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" + "fast-string-truncated-width": "^3.0.2" } }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "fast-string-width": "^3.0.2" } }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -1621,39 +2121,12 @@ } } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz", - "integrity": "sha512-jPrupTOe/pO//3a9Ty2o4NqQCp0L46UG+swUnfFtdmtQVN8pEltKpAqR7Nuf6vWn0GBXx5w+R1MyZzqwjEIqdA==", - "dependencies": { - "traverse-chain": "~0.1.0" - } - }, - "node_modules/find-in-files": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/find-in-files/-/find-in-files-0.5.0.tgz", - "integrity": "sha512-VraTc6HdtdSHmAp0yJpAy20yPttGKzyBWc7b7FPnnsX9TOgmKx0g9xajizpF/iuu4IvNK4TP0SpyBT9zAlwG+g==", - "dependencies": { - "find": "^0.1.5", - "q": "^1.0.1" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -1670,6 +2143,7 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -1679,6 +2153,7 @@ "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" @@ -1690,27 +2165,19 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1725,6 +2192,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1734,32 +2202,25 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "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", @@ -1775,28 +2236,19 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1804,18 +2256,21 @@ "node_modules/hash-sum": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "license": "MIT" }, "node_modules/hashids": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/hashids/-/hashids-2.3.0.tgz", - "integrity": "sha512-ljM73TE/avEhNnazxaj0Dw3BbEUuLC5yYCQ9RSkSUcT4ZSU6ZebdKCIBJ+xT/DnSYW36E9k82GH1Q6MydSIosQ==" + "integrity": "sha512-ljM73TE/avEhNnazxaj0Dw3BbEUuLC5yYCQ9RSkSUcT4ZSU6ZebdKCIBJ+xT/DnSYW36E9k82GH1Q6MydSIosQ==", + "license": "MIT" }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -1828,31 +2283,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1871,43 +2306,44 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/into-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", - "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-9.1.0.tgz", + "integrity": "sha512-DRsRnQrbzdFjaQ1oe4C6/EIUymIOEix1qROEJTF9dbMq+M4Zrm6VaLp6SD/B9IsiEjPZuBSnWWFN+udajugdWA==", "dev": true, - "dependencies": { - "from2": "^2.3.0", - "p-is-promise": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -1920,6 +2356,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -1930,45 +2367,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, + "node_modules/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", "dependencies": { "is-docker": "^3.0.0" }, @@ -1982,29 +2407,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/is-safe-filename": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-safe-filename/-/is-safe-filename-0.1.1.tgz", + "integrity": "sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2015,6 +2434,7 @@ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2023,9 +2443,10 @@ } }, "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" }, @@ -2040,23 +2461,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -2067,16 +2487,33 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "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==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.1.tgz", + "integrity": "sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "js-yaml": "bin/js-yaml.mjs" } }, "node_modules/jsesc": { @@ -2084,6 +2521,7 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -2092,10 +2530,11 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -2108,6 +2547,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2118,23 +2558,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "dev": true - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -2146,75 +2575,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true - }, "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 + "dev": true, + "license": "ISC" }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, "node_modules/mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -2227,6 +2609,7 @@ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2235,12 +2618,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "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.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -2254,24 +2638,27 @@ "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/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^7.1.2" }, @@ -2279,44 +2666,31 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mocha": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.5.0.tgz", - "integrity": "sha512-VKDjhy6LMTKm0WgNEdlY77YVsD49LZnPSXJAaPNL9NRYQADxvORsyG1DIQY6v53BKTnlNbEE2MbVCDbnxr4K3w==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.3.0.tgz", + "integrity": "sha512-J0RLIM89xi8y6l77bgbX+03PeBRDQCOVQpnwOcCN7b8hCmbh6JvGI2ZDJ5WMoHz+IaPU+S4lvTd0j51GmBAdgQ==", "dev": true, + "license": "MIT", "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^7.0.0", + "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", + "minimatch": "^5.1.6", "ms": "^2.1.3", "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", @@ -2340,6 +2714,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2349,6 +2724,7 @@ "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", @@ -2362,13 +2738,51 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } }, "node_modules/mocha/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2383,6 +2797,7 @@ "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" }, @@ -2395,6 +2810,7 @@ "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", @@ -2408,10 +2824,11 @@ } }, "node_modules/mocha/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -2425,30 +2842,12 @@ "node": ">=12" } }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.0.tgz", - "integrity": "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, "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 + "dev": true, + "license": "MIT" }, "node_modules/multistream": { "version": "4.1.0", @@ -2469,44 +2868,34 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "once": "^1.4.0", "readable-stream": "^3.6.0" } }, - "node_modules/multistream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "license": "ISC", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-abi": { - "version": "3.75.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", - "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "version": "3.94.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", + "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -2514,56 +2903,19 @@ "node": ">=10" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-spinner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/node-spinner/-/node-spinner-0.0.4.tgz", - "integrity": "sha512-W4ivgsaxoJr1wSppeEQGYrq23GuMniTwJNZWLpFadCIuxwu1srmdH2uH+VlaMnxvjBqZ4NlcCBQEOmB3mXF+cA==", - "dependencies": { - "util-extend": "~1.0.1" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "dev": true, + "license": "MIT" }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -2572,6 +2924,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", "dependencies": { "mimic-function": "^5.0.0" }, @@ -2583,36 +2936,31 @@ } }, "node_modules/open": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", - "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "license": "MIT", "dependencies": { - "default-browser": "^5.2.1", + "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-is-promise": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", - "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2628,6 +2976,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -2642,13 +2991,15 @@ "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 + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2657,6 +3008,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2665,13 +3018,15 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "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" @@ -2683,26 +3038,18 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "engines": { - "node": ">= 14.16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2710,11 +3057,51 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/postject/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", "dev": true, + "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -2736,84 +3123,76 @@ "node": ">=10" } }, + "node_modules/prebuild-install/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, - "node_modules/prompt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", - "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dependencies": { - "@colors/colors": "1.5.0", - "async": "3.2.3", - "read": "1.0.x", - "revalidator": "0.1.x", - "winston": "2.x" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/prompt/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/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" } @@ -2823,6 +3202,7 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -2837,72 +3217,25 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-yaml": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-yaml/-/read-yaml-1.1.0.tgz", - "integrity": "sha512-bDA8pyfGurfEHlgy/wm4vPmcCNW4QPsf86u9JvOixYWc8YD2O985hmZwZrBlzfvf/J4vKGTOWq/CThixACPRPA==", - "dependencies": { - "extend-shallow": "^2.0.1", - "js-yaml": "^3.8.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-yaml/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/read-yaml/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==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/read/node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/readdirp": { @@ -2910,6 +3243,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.18.0" }, @@ -2923,17 +3257,20 @@ "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/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -2947,10 +3284,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" @@ -2962,27 +3310,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", "engines": { "node": ">=18" }, @@ -2990,10 +3322,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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", @@ -3008,21 +3341,14 @@ "url": "https://feross.org/support" } ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3035,6 +3361,7 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -3043,6 +3370,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3054,26 +3383,17 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/shelljs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.10.0.tgz", - "integrity": "sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==", - "dependencies": { - "execa": "^5.1.1", - "fast-glob": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, "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==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -3099,7 +3419,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/simple-get": { "version": "4.0.1", @@ -3120,6 +3441,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -3127,45 +3449,30 @@ } }, "node_modules/sinon": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-20.0.0.tgz", - "integrity": "sha512-+FXOAbdnj94AQIxH0w1v8gzNxkawVvNqE3jUzRLptR71Oykeu2RrQXXl/VQjKay+Qnh73fDt/oDfMo6xMeDQbQ==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-22.0.0.tgz", + "integrity": "sha512-sq/6DpdXOrLyfbKlXLg/Usc7xu8YXPeLkOFZRvA3bNUSA2lhbrZ06yuXbH1fkzBPCbz9O10+7hznzUsjaYNm0Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "supports-color": "^7.2.0" + "@sinonjs/fake-timers": "^15.4.0", + "@sinonjs/samsam": "^10.0.2", + "diff": "^9.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/sinon/node_modules/diff": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=8" - } - }, - "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/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "engines": { - "node": "*" + "node": ">=0.3.1" } }, "node_modules/stream-meter": { @@ -3173,24 +3480,72 @@ "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "^2.1.4" } }, - "node_modules/string_decoder": { + "node_modules/stream-meter/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-meter/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/stream-meter/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, + "node_modules/streamx": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.0.tgz", + "integrity": "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "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", @@ -3209,6 +3564,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3223,6 +3579,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3231,13 +3588,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3246,12 +3605,13 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.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.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -3266,6 +3626,7 @@ "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" }, @@ -3278,23 +3639,17 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3307,6 +3662,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3322,6 +3678,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3332,12 +3689,14 @@ "node_modules/svg-engine": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/svg-engine/-/svg-engine-0.3.0.tgz", - "integrity": "sha512-s172jAcwfoCcvM/6DwNBvmWN3brztHGFENCR+RU3CBJKeBxPrRlTltVxX1Je5hst782QgP8PM6U37vUR/RhPng==" + "integrity": "sha512-s172jAcwfoCcvM/6DwNBvmWN3brztHGFENCR+RU3CBJKeBxPrRlTltVxX1Je5hst782QgP8PM6U37vUR/RhPng==", + "license": "MIT" }, "node_modules/swissqrbill": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/swissqrbill/-/swissqrbill-4.2.0.tgz", - "integrity": "sha512-wXGTTSpt6zO/p4pURY9pQJkzEfA5xX80jt1jbB1OOTogSNEeBAnoT1KYUj1++LtUb8OoH5GBFCe3EUpHpiB7AA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/swissqrbill/-/swissqrbill-4.3.0.tgz", + "integrity": "sha512-FzSPEVWVQ3R6B0vghqi7VJCLp54AMYxCSiJGr2QzXo8OSU8JBv7XJcF67BAVAriGkuaZqVfhxuD6yRFT6WAXEA==", + "license": "MIT", "dependencies": { "svg-engine": "^0.3.0" }, @@ -3358,16 +3717,16 @@ } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "version": "7.5.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz", + "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { @@ -3375,88 +3734,93 @@ } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.3.tgz", + "integrity": "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==", "dev": true, + "license": "MIT", "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" } }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", + "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", "dev": true, + "license": "MIT", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "streamx": "^2.12.5" } }, "node_modules/temp-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "license": "MIT", "engines": { "node": ">=14.16" } }, "node_modules/tempfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-5.0.0.tgz", - "integrity": "sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-6.0.1.tgz", + "integrity": "sha512-DE4nURsf7nUqYHJKTgOVdpt0SBY5r4us4kbFXqg7KZFB7ih27NxIk3qXv29FtqTaE45stnLKTECmSc9ICuRbDQ==", + "license": "MIT", "dependencies": { + "is-safe-filename": "^0.1.1", "temp-dir": "^3.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/throttled-queue": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/throttled-queue/-/throttled-queue-2.1.4.tgz", - "integrity": "sha512-YGdk8sdmr4ge3g+doFj/7RLF5kLM+Mi7DEciu9PHxnMJZMeVuZeTj31g4VE7ekUffx/IdbvrtOCiz62afg0mkg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/throttled-queue/-/throttled-queue-3.0.0.tgz", + "integrity": "sha512-8X5YUdgDHaqy9DmJzoRWK45o2vzBZ7Rt4bT1Mody4TUuYOXSb7paRwDPVspCZiiW4rxZopgZQAwnhI2LU0QwFQ==", + "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, + "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -3465,33 +3829,12 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/traverse-chain": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", - "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg==" - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -3504,44 +3847,83 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc" + }, "engines": { - "node": ">=10" + "node": ">=16.20.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==" + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" + } + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "devOptional": true, + "license": "MIT" }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/unzipper": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz", - "integrity": "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.5.tgz", + "integrity": "sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==", "dev": true, + "license": "MIT", "dependencies": { "bluebird": "~3.7.2", "duplexer2": "~0.1.4", - "fs-extra": "^11.2.0", + "fs-extra": "11.3.1", "graceful-fs": "^4.2.2", "node-int64": "^0.4.0" } @@ -3550,33 +3932,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/util-extend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", - "integrity": "sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3587,56 +3951,12 @@ "node": ">= 8" } }, - "node_modules/winston": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", - "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", - "dependencies": { - "async": "^2.6.4", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/winston/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/winston/node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", @@ -3644,6 +3964,7 @@ "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", @@ -3661,6 +3982,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3669,13 +3991,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3690,43 +4014,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3738,18 +4026,23 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, - "node_modules/xlsx": { - "version": "0.20.3", - "resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", - "integrity": "sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==", - "license": "Apache-2.0", - "bin": { - "xlsx": "bin/xlsx.njs" + "node_modules/wsl-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", + "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" }, "engines": { - "node": ">=0.8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/y18n": { @@ -3757,6 +4050,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -3766,15 +4060,17 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -3793,6 +4089,7 @@ "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" } @@ -3802,6 +4099,7 @@ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -3817,6 +4115,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3829,6 +4128,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3837,13 +4137,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3858,6 +4160,7 @@ "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" }, @@ -3870,6 +4173,7 @@ "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": { "node": ">=10" } @@ -3879,23 +4183,13 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index f2f4a68..2f5f291 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gitlab-time-tracker", - "version": "1.8.2-snapshot", + "version": "1.9.0-beta0002", "type": "module", "description": "A command line interface for GitLabs time tracking feature.", "bugs": { @@ -14,61 +14,57 @@ "scripts": { "prebuild": "echo \"let version = '${npm_package_version}'; export default version;\" > src/version.js", "test": "NODE_ENV=test mocha 'spec/**/*.spec.js'", - "esbuild": "esbuild 'src/gtt.js' --format=cjs --target=node20 --platform=node --bundle --outfile=dist/gtt.cjs --inject:./src/polyfill/import-meta-url.js --define:import.meta.url=import_meta_url", + "typecheck": "tsc --noEmit", + "esbuild": "esbuild 'src/gtt.js' --format=cjs --target=node24 --platform=node --bundle --outfile=dist/gtt.cjs --inject:./src/polyfill/import-meta-url.js --define:import.meta.url=import_meta_url", "pkg": "pkg dist/gtt.cjs -o out/gtt -c package.json", "docker": "docker build . -t gitlab-time-tracker:${npm_package_version} -t gitlab-time-tracker:latest", - "build": "npm run-script prebuild && npm run-script test && npm run-script esbuild && npm run-script pkg", - "buildAll": "npm run-script prebuild && npm run-script test && npm run-script esbuild && npm run-script pkg && npm run-script docker" + "build": "npm run-script prebuild && npm run-script typecheck && npm run-script test && npm run-script esbuild && npm run-script pkg", + "buildAll": "npm run-script prebuild && npm run-script typecheck && npm run-script test && npm run-script esbuild && npm run-script pkg && npm run-script docker" }, "bin": { "gtt": "dist/gtt.cjs" }, "engines": { - "node": ">=20 <21" + "node": "24" }, "pkg": { "scripts": "dist/gtt.cjs", "targets": [ - "node20-linux-x64", - "node20-macos-x64", - "node20-win-x64" + "node24-linux-x64", + "node24-macos-x64", + "node24-win-x64" ] }, "author": "kriskbx", "license": "GPL-2.0", "dependencies": { - "@inquirer/select": "^4.2.3", - "async": "^3.2.6", - "camelcase": "^8.0.0", + "@inquirer/confirm": "^6.1.1", + "@inquirer/select": "^5.2.1", + "camelcase": "^9.0.0", "cli-cursor": "^5.0.0", "cli-table": "^0.3.11", - "colors": "^1.4.0", - "commander": "^14.0.0", + "commander": "^15.0.0", "csv-string": "^4.1.1", - "env-paths": "^3.0.0", - "find-in-files": "^0.5.0", + "dayjs": "^1.11.21", + "env-paths": "^4.0.0", "hash-sum": "^2.0.0", "hashids": "^2.3.0", + "js-yaml": "^5.2.1", "markdown-table": "^3.0.4", - "moment": "^2.30.1", - "moment-timezone": "^0.6.0", - "node-spinner": "^0.0.4", - "open": "^10.1.2", + "open": "^11.0.0", + "picocolors": "^1.1.1", "progress": "^2.0.3", - "prompt": "^1.3.0", - "read-yaml": "^1.1.0", - "shelljs": "^0.10.0", - "swissqrbill": "^4.2.0", - "tempfile": "^5.0.0", - "throttled-queue": "^2.1.4", - "underscore": "^1.13.7", - "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz" + "swissqrbill": "^4.3.0", + "tempfile": "^6.0.1", + "throttled-queue": "^3.0.0" }, "devDependencies": { - "@yao-pkg/pkg": "^6.5.1", - "chai": "^5.2.0", - "esbuild": "^0.25.4", - "mocha": "^11.4.0", - "sinon": "^20.0.0" + "@types/node": "^26.1.1", + "@yao-pkg/pkg": "^6.21.0", + "chai": "^6.2.2", + "esbuild": "^0.28.1", + "mocha": "^11.3.0", + "sinon": "^22.0.0", + "typescript": "^7.0.2" } } diff --git a/readme.md b/readme.md index 8b5a4c9..60a84db 100755 --- a/readme.md +++ b/readme.md @@ -9,11 +9,11 @@ gtt is a fully featured command line interface for GitLab's time tracking featur ## About this fork (ndu2) -Shout-out to kris for creating this handy tool. As we use gtt regularly and maintenance on the original repo stopped, I maintain the code base in the foreseeable future on this fork (versions 1.8.x). +Shout-out to kris for creating this handy tool. As we use gtt regularly and maintenance on the original repo stopped, I maintain the code base in the foreseeable future on this fork (versions 1.8.x and later). Feel free to contact me or create a Pull Request if you have some patches or proposals. -### Where to get gtt v1.8 +### Where to get gtt There are various options: @@ -33,7 +33,7 @@ How to install and use gtt? You can find the documentation [here](documentation. ### limitations -Time tracking for other work items (e.g. tasks, epics) is currently not supported. +Time tracking and reporting for epics is currently not supported. ## license diff --git a/spec/core/billing.spec.js b/spec/core/billing.spec.js new file mode 100644 index 0000000..2468214 --- /dev/null +++ b/spec/core/billing.spec.js @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import Config from '../../src/core/config.js'; +import chargeRatio from '../../src/core/billing.js'; + +describe('chargeRatio', () => { + let config; + + beforeEach(() => { + config = new Config(); + config.set('freeLabels', ['pro bono']); + config.set('halfPriceLabels', ['discount']); + }); + + it('is 0.0 when a label matches freeLabels', () => { + expect(chargeRatio(['pro bono', 'bug'], config)).to.equal(0.0); + }); + + it('is 0.5 when a label matches halfPriceLabels', () => { + expect(chargeRatio(['discount', 'bug'], config)).to.equal(0.5); + }); + + it('is 1.0 when no label matches', () => { + expect(chargeRatio(['bug'], config)).to.equal(1.0); + }); + + it('free wins over half price when both match', () => { + expect(chargeRatio(['pro bono', 'discount'], config)).to.equal(0.0); + }); + + it('treats missing freeLabels/halfPriceLabels config as empty', () => { + const bareConfig = new Config(); + + expect(chargeRatio(['pro bono'], bareConfig)).to.equal(1.0); + }); +}); diff --git a/spec/core/cli.spec.js b/spec/core/cli.spec.js new file mode 100644 index 0000000..9964ee5 --- /dev/null +++ b/spec/core/cli.spec.js @@ -0,0 +1,80 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import Cli, { CliExitError } from '../../src/core/cli.js'; + +describe('Cli', () => { + let exitStub, writeStub; + + beforeEach(() => { + Cli.quiet = false; + Cli.verbose = false; + exitStub = sinon.stub(process, 'exit'); + writeStub = sinon.stub(process.stdout, 'write'); + }); + + afterEach(() => { + exitStub.restore(); + writeStub.restore(); + }); + + describe('error', () => { + it('throws a CliExitError instead of exiting the process', () => { + expect(() => Cli.error('boom')).to.throw(CliExitError, 'boom'); + expect(exitStub.called).to.be.false; + }); + + it('carries exit code 1', () => { + try { + Cli.error('boom'); + } catch (e) { + expect(e.code).to.equal(1); + } + }); + + it('prints the error message before throwing', () => { + expect(() => Cli.error('boom')).to.throw(); + expect(writeStub.calledWithMatch(/Error:.*boom/)).to.be.true; + }); + + it('extracts .message from an Error instance passed as message, keeping the original for verbose logging', () => { + const original = new Error('underlying failure'); + let caught; + + try { + Cli.error(original); + } catch (e) { + caught = e; + } + + expect(caught.message).to.equal('underlying failure'); + }); + }); + + describe('x', () => { + it('throws (via Cli.error) when given a message', () => { + expect(() => Cli.x('boom')).to.throw(CliExitError, 'boom'); + }); + + it('does not throw when given no message - just stops the spinner', async () => { + await Cli.x(); + + expect(exitStub.called).to.be.false; + }); + }); + + describe('out/warn', () => { + it('out writes to stdout unless quiet', () => { + Cli.out('hello'); + expect(writeStub.calledWith('hello')).to.be.true; + + writeStub.resetHistory(); + Cli.quiet = true; + Cli.out('hello'); + expect(writeStub.called).to.be.false; + }); + + it('warn does not throw', () => { + expect(() => Cli.warn('careful')).to.not.throw(); + }); + }); +}); diff --git a/spec/core/configFile.spec.js b/spec/core/configFile.spec.js new file mode 100644 index 0000000..e5126d9 --- /dev/null +++ b/spec/core/configFile.spec.js @@ -0,0 +1,129 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { expect } from 'chai'; +import { findLocalConfigDir, readConfigFile, resolveLocalConfig } from '../../src/core/configFile.js'; + +describe('findLocalConfigDir', () => { + let dir; + + beforeEach(() => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gtt-configfile-')); + }); + + afterEach(() => { + fs.rmSync(dir, { recursive: true, force: true }); + }); + + it('finds the file in the starting directory', () => { + fs.writeFileSync(path.join(dir, '.gtt.yml'), ''); + + expect(findLocalConfigDir(dir, '.gtt.yml')).to.equal(dir); + }); + + it('walks up through parent directories to find the file', () => { + fs.writeFileSync(path.join(dir, '.gtt.yml'), ''); + const nested = path.join(dir, 'a', 'b', 'c'); + fs.mkdirSync(nested, { recursive: true }); + + expect(findLocalConfigDir(nested, '.gtt.yml')).to.equal(dir); + }); + + it('returns null when no config file is found up to the root', () => { + const nested = path.join(dir, 'a', 'b'); + fs.mkdirSync(nested, { recursive: true }); + + expect(findLocalConfigDir(nested, '.this-file-does-not-exist.yml')).to.equal(null); + }); +}); + +describe('readConfigFile', () => { + let dir; + + beforeEach(() => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gtt-configfile-')); + }); + + afterEach(() => { + fs.rmSync(dir, { recursive: true, force: true }); + }); + + it('parses a valid YAML file', () => { + const file = path.join(dir, 'config.yml'); + fs.writeFileSync(file, 'token: abc\nurl: https://example.com\n'); + + expect(readConfigFile(file)).to.deep.equal({ token: 'abc', url: 'https://example.com' }); + }); + + it('throws a contextualized error for invalid YAML', () => { + const file = path.join(dir, 'broken.yml'); + fs.writeFileSync(file, 'token: [unclosed'); + + expect(() => readConfigFile(file)).to.throw(new RegExp(`Error parsing configuration: "${file.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"`)); + }); + + it('throws a contextualized error for a missing file', () => { + const file = path.join(dir, 'missing.yml'); + + expect(() => readConfigFile(file)).to.throw(new RegExp(`Error parsing configuration: "${file.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"`)); + }); +}); + +describe('resolveLocalConfig', () => { + let dir; + + beforeEach(() => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gtt-configfile-')); + }); + + afterEach(() => { + fs.rmSync(dir, { recursive: true, force: true }); + }); + + function write(name, content) { + const file = path.join(dir, name); + fs.writeFileSync(file, content); + return file; + } + + it('returns the local config as-is when extend is explicitly disabled', () => { + const local = write('local.yml', 'extend: false\ntoken: local-token\n'); + const global = write('global.yml', 'token: global-token\nurl: https://global.example\n'); + + expect(resolveLocalConfig(local, global)).to.deep.equal({ extend: false, token: 'local-token' }); + }); + + it('defaults to extending the global config when extend is not specified', () => { + const local = write('local.yml', 'token: local-token\n'); + const global = write('global.yml', 'token: global-token\nurl: https://global.example\n'); + + expect(resolveLocalConfig(local, global)).to.deep.equal({ + extend: true, + token: 'local-token', + url: 'https://global.example' + }); + }); + + it('merges global underneath local when extend is true (the default)', () => { + const local = write('local.yml', 'extend: true\ntoken: local-token\n'); + const global = write('global.yml', 'token: global-token\nurl: https://global.example\n'); + + expect(resolveLocalConfig(local, global)).to.deep.equal({ + extend: true, + token: 'local-token', + url: 'https://global.example' + }); + }); + + it('merges an explicitly named file underneath local when extend is a path', () => { + const other = write('other.yml', 'token: other-token\nurl: https://other.example\n'); + const local = write('local.yml', `extend: ${other}\ntoken: local-token\n`); + const global = write('global.yml', 'token: global-token\n'); + + expect(resolveLocalConfig(local, global)).to.deep.equal({ + extend: other, + token: 'local-token', + url: 'https://other.example' + }); + }); +}); diff --git a/spec/include/config.spec.js b/spec/include/config.spec.js index a2ffe60..ba38709 100755 --- a/spec/include/config.spec.js +++ b/spec/include/config.spec.js @@ -1,4 +1,4 @@ -import config from '../../src/include/config.js'; +import config from '../../src/core/config.js'; import { expect } from 'chai'; describe('The config class', () => { @@ -32,7 +32,7 @@ describe('The config class', () => { expect(Config.get(key)).to.equal(undefined); }); - it('returns moment instances for dates', () => { + it('returns dayjs instances for dates', () => { let Config = new config(), dates = ['from', 'to']; diff --git a/spec/include/parallel.spec.js b/spec/include/parallel.spec.js new file mode 100644 index 0000000..e5935b9 --- /dev/null +++ b/spec/include/parallel.spec.js @@ -0,0 +1,70 @@ +import { expect } from 'chai'; +import Config from '../../src/core/config.js'; +import parallel from '../../src/core/parallel.js'; + +const tick = () => new Promise(resolve => setImmediate(resolve)); + +describe('parallel', () => { + let config; + + beforeEach(() => { + config = new Config(); + }); + + it('processes every task', async () => { + const seen = []; + + await parallel([1, 2, 3, 4, 5], async task => { + await tick(); + seen.push(task); + }, config); + + expect(seen.sort()).to.deep.equal([1, 2, 3, 4, 5]); + }); + + it('accepts plain sync workers', async () => { + const seen = []; + + await parallel([1, 2], task => seen.push(task), config); + + expect(seen).to.deep.equal([1, 2]); + }); + + it('never runs more workers than the runner limit', async () => { + let active = 0; + let peak = 0; + + await parallel(Array.from({ length: 12 }, (_, i) => i), async () => { + active++; + peak = Math.max(peak, active); + await tick(); + active--; + }, config, 3); + + expect(peak).to.be.at.most(3); + }); + + it('rejects with the first worker error and starts no further tasks', async () => { + const started = []; + let caught = null; + + try { + await parallel([1, 2, 3, 4, 5], async task => { + started.push(task); + await tick(); + if (task === 1) throw new Error('boom'); + }, config, 1); + } catch (error) { + caught = error; + } + + expect(caught).to.be.an('error').with.property('message', 'boom'); + expect(started).to.deep.equal([1]); + }); + + it('handles an empty task list', async () => { + await parallel([], () => { + throw new Error('should not run'); + }, config); + }); +}); diff --git a/spec/models/frame.spec.js b/spec/models/frame.spec.js new file mode 100644 index 0000000..2ac69f1 --- /dev/null +++ b/spec/models/frame.spec.js @@ -0,0 +1,108 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { expect } from 'chai'; +import Config from '../../src/core/config.js'; +import Frame from '../../src/timekeeping/storage/frame.js'; + +describe('frame class', () => { + let config, dir; + + beforeEach(() => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gtt-frame-')); + config = new Config(); + config.frameDir = dir; + config.set('project', 'group/project'); + }); + + afterEach(() => { + fs.rmSync(dir, { recursive: true, force: true }); + }); + + it('marks frames for not-yet-existing resources as new', () => { + expect(new Frame(config, 'a new issue', 'issue').resource.new).to.equal(true); + expect(new Frame(config, 42, 'issue').resource.new).to.equal(undefined); + }); + + it('persists on start/stop and round-trips through fromFile', () => { + const frame = new Frame(config, 42, 'issue', 'a note').startMe(); + frame.stopMe(); + + const loaded = Frame.fromFile(config, frame.file); + + expect(loaded.id).to.equal(frame.id); + expect(loaded.project).to.equal('group/project'); + expect(loaded.resource).to.deep.equal({ id: 42, type: 'issue' }); + expect(loaded.note).to.equal('a note'); + expect(loaded.start.isSame(frame.start)).to.equal(true); + expect(loaded.stop.isSame(frame.stop)).to.equal(true); + }); + + it('computes the duration in seconds', () => { + const frame = Frame.fromJson(config, { + id: 'abc', + project: 'group/project', + resource: { id: 42, type: 'issue' }, + notes: [], + start: '2026-01-05T10:00:00Z', + stop: '2026-01-05T11:30:00Z', + timezone: 'UTC' + }); + + expect(frame.duration).to.equal(5400); + }); + + it('rejects invalid start and stop dates', () => { + const json = { + id: 'abc', + project: 'group/project', + resource: { id: 42, type: 'issue' }, + notes: [], + start: '2026-01-05T10:00:00Z', + stop: false, + timezone: 'UTC' + }; + + expect(() => Frame.fromJson(config, { ...json, start: 'not a date' })).to.throw(/Start date/); + expect(() => Frame.fromJson(config, { ...json, stop: 'not a date' })).to.throw(/Stop date/); + }); + + it('validates dates set through the setters', () => { + const frame = new Frame(config, 42, 'issue').startMe(); + + expect(() => { + frame.stop = 'not a date'; + }).to.throw(); + + frame.stop = '2026-01-05T11:30:00Z'; + expect(frame.stop.isSame('2026-01-05T11:30:00Z')).to.equal(true); + }); + + it('rejects a frame with no start date at all', () => { + const json = { + id: 'abc', + project: 'group/project', + resource: { id: 42, type: 'issue' }, + notes: [], + start: false, + stop: false, + timezone: 'UTC' + }; + + expect(() => Frame.fromJson(config, json)).to.throw(/Start date/); + }); + + it('persists start/stop as strings even without a timezone configured', () => { + config.set('timezone', false, true); + + const frame = new Frame(config, 42, 'issue').startMe(); + frame.stopMe(); + + expect(frame._start).to.be.a('string'); + expect(frame._stop).to.be.a('string'); + + const loaded = Frame.fromFile(config, frame.file); + expect(loaded.start.isSame(frame.start)).to.equal(true); + expect(loaded.stop.isSame(frame.stop)).to.equal(true); + }); +}); diff --git a/spec/models/time.title.spec.js b/spec/models/time.title.spec.js deleted file mode 100644 index 5b34eec..0000000 --- a/spec/models/time.title.spec.js +++ /dev/null @@ -1,37 +0,0 @@ - -import moment from 'moment'; -import Config from '../../src/include/file-config.js'; -import Time from '../../src/models/time.js'; -import issue from '../../src/models/issue.js'; -import mergeRequest from '../../src/models/mergeRequest.js'; -import { expect } from 'chai'; - -describe('time class', () => { - it('Returns title of parent Issue', () => { - const config = new Config(process.cwd()); - const parent = new issue(config, {title: "Test title"}) - const time = new Time('1h', moment(), {}, parent, config); - - expect(time.title).to.be.equal("Test title"); - }); - - it('Returns title of parent MergeRequest', () => { - const config = new Config(process.cwd()); - const parent = new mergeRequest(config, {title: "Test title"}) - const time = new Time('1h', moment(), {}, parent, config); - - expect(time.title).to.be.equal("Test title"); - }); - - it('Returns Null for missed title or parent', () => { - const config = new Config(process.cwd()); - const parent = new mergeRequest(config, {}); - let time; - time = new Time('1h', moment(), {}, parent, config); - expect(time.title).to.be.equal(null); - - time = new Time('1h', moment(), {}, null, config); - expect(time.title).to.be.equal(null); - }); -}); - diff --git a/spec/output/base.spec.js b/spec/output/base.spec.js new file mode 100644 index 0000000..2605c0a --- /dev/null +++ b/spec/output/base.spec.js @@ -0,0 +1,148 @@ +import dayjs from '../../src/core/dayjs.js'; +import { expect } from 'chai'; +import Config from '../../src/core/config.js'; +import Output from '../../src/reporting/output/base.js'; +import calculateStats from '../../src/reporting/stats.js'; + +function makeTime({ user = 'alice', seconds = 0, date = '2026-01-05T10:00:00Z', note = null, chargeRatio = 1.0 } = {}) { + return { user, seconds, date: dayjs(date), note, chargeRatio }; +} + +function makeIssue({ iid = 1, labels = [], times = [], estimate = 0, spent = 0, project_id = 1, title = 'issue', project_namespace = 'group/project' } = {}) { + const issue = { + iid, + project_id, + project_namespace, + title, + labels, + times, + total_spent_s : spent, + total_estimate_s : estimate + }; + + return issue; +} + +describe('calculateStats', () => { + let config; + + beforeEach(() => { + config = new Config(); + }); + + function calculate(issues = [], mergeRequests = []) { + return calculateStats(config, { issues, mergeRequests }); + } + + it('aggregates spent time per user and per project', () => { + const output = calculate([ + makeIssue({ + iid: 1, times: [ + makeTime({ user: 'alice', seconds: 3600 }), + makeTime({ user: 'bob', seconds: 1800 }) + ] + }), + makeIssue({ + iid: 2, project_namespace: 'group/other', times: [ + makeTime({ user: 'alice', seconds: 1800 }) + ] + }) + ]); + + expect(output.spent).to.equal(7200); + expect(output.users).to.deep.equal({ alice: '1h 30m', bob: '30m' }); + expect(output.projects).to.deep.equal({ 'group/project': '1h 30m', 'group/other': '30m' }); + expect(output.stats.spent).to.equal('2h'); + }); + + it('sums estimates and total spent across issues and merge requests', () => { + const output = calculate( + [makeIssue({ iid: 1, estimate: '3600', spent: '7200' })], + [makeIssue({ iid: 1, estimate: '1800', spent: '900' })] + ); + + expect(output.totalEstimate).to.equal(5400); + expect(output.totalSpent).to.equal(8100); + expect(output.stats['total estimate']).to.equal('1h 30m'); + expect(output.stats['total spent']).to.equal('2h 15m'); + }); + + it('tracks free and half price time by chargeRatio, set on each time record by Task.recordTimelogs', () => { + const output = calculate([ + makeIssue({ iid: 1, times: [makeTime({ seconds: 3600, chargeRatio: 0.0 })] }), + makeIssue({ iid: 2, times: [makeTime({ seconds: 1800, chargeRatio: 0.5 })] }), + makeIssue({ iid: 3, times: [makeTime({ seconds: 60, chargeRatio: 1.0 })] }) + ]); + + expect(output.spentFree).to.equal(3600); + expect(output.spentHalfPrice).to.equal(1800); + expect(output.spent).to.equal(5460); + }); + + it('treats full-price (chargeRatio 1.0) time as neither free nor half price', () => { + const output = calculate([ + makeIssue({ iid: 1, times: [makeTime({ seconds: 3600, chargeRatio: 1.0 })] }) + ]); + + expect(output.spentFree).to.equal(0); + expect(output.spentHalfPrice).to.equal(0); + }); + + it('sorts issues by iid and times by date, newest first', () => { + const report = { + issues: [ + makeIssue({ iid: 1, times: [makeTime({ date: '2026-01-01T10:00:00Z' })] }), + makeIssue({ iid: 3, times: [makeTime({ date: '2026-01-03T10:00:00Z' })] }), + makeIssue({ iid: 2, times: [makeTime({ date: '2026-01-02T10:00:00Z' })] }) + ], + mergeRequests: [] + }; + const output = calculateStats(config, report); + + expect(report.issues.map(issue => issue.iid)).to.deep.equal([3, 2, 1]); + expect(output.times.map(time => time.date.format('YYYY-MM-DD'))).to.deep.equal([ + '2026-01-03', '2026-01-02', '2026-01-01' + ]); + }); + + it('consolidates per-day data of all issues', () => { + config.set('dateFormatGroupReport', 'YYYY-MM-DD'); + + const output = calculate([ + makeIssue({ iid: 1, times: [makeTime({ date: '2026-01-01T10:00:00Z', note: 'a', seconds: 60 })] }), + makeIssue({ iid: 2, times: [ + makeTime({ date: '2026-01-01T10:00:00Z', note: 'b', seconds: 120 }), + makeTime({ date: '2026-01-02T10:00:00Z', note: 'c', seconds: 180 }) + ] }) + ]); + + expect(Object.keys(output.daysNew)).to.deep.equal(['2026-01-01', '2026-01-02']); + expect(output.daysNew['2026-01-01'].map(d => d.getNotes())).to.deep.equal([['a'], ['b']]); + expect(output.daysNew['2026-01-02'].map(d => d.getNotes())).to.deep.equal([['c']]); + }); +}); + +describe('Output.prepare', () => { + it('formats dayjs dates, replaces null/undefined and picks columns in order', () => { + const config = new Config(); + config.set('dateFormat', 'YYYY-MM-DD'); + + const output = new Output(config, { issues: [], mergeRequests: [] }); + const row = output.prepare({ + iid: 7, + date: dayjs('2026-01-05T10:00:00Z'), + missing: null, + labels: ['a', 'b'] + }, ['iid', 'date', 'missing', 'undefined_column', 'labels']); + + expect(row).to.deep.equal([7, '2026-01-05', '', '', 'a,b']); + }); + + it('returns empty string when the column is missing on both obj and its parent, or there is no parent', () => { + const config = new Config(); + const output = new Output(config, { issues: [], mergeRequests: [] }); + + expect(output.prepare({ parent: {} }, ['title'])).to.deep.equal(['']); + expect(output.prepare({}, ['title'])).to.deep.equal(['']); + }); +}); diff --git a/spec/reporting/filters.spec.js b/spec/reporting/filters.spec.js new file mode 100644 index 0000000..d1567f1 --- /dev/null +++ b/spec/reporting/filters.spec.js @@ -0,0 +1,38 @@ +import { expect } from 'chai'; +import { excludeByLabel, excludeMoved } from '../../src/reporting/filters.js'; + +function item(iid, labels = []) { + return { iid, labels }; +} + +describe('excludeByLabel', () => { + it('returns items unchanged when there are no exclude labels', () => { + const items = [item(1, ['bug'])]; + + expect(excludeByLabel(items, null)).to.deep.equal(items); + expect(excludeByLabel(items, undefined)).to.deep.equal(items); + expect(excludeByLabel(items, false)).to.deep.equal(items); + }); + + it('drops items carrying any of the excluded labels', () => { + const items = [item(1, ['bug']), item(2, ['wontfix']), item(3, ['bug', 'wontfix']), item(4, [])]; + + const result = excludeByLabel(items, ['wontfix']); + + expect(result.map(i => i.iid)).to.deep.equal([1, 4]); + }); +}); + +describe('excludeMoved', () => { + it('drops issues that have been moved to another project', () => { + const issues = [ + { iid: 1, moved_to_id: null }, + { iid: 2, moved_to_id: 42 }, + { iid: 3 } + ]; + + const result = excludeMoved(issues); + + expect(result.map(i => i.iid)).to.deep.equal([1, 3]); + }); +}); diff --git a/spec/reporting/reportConfigBuilder.spec.js b/spec/reporting/reportConfigBuilder.spec.js new file mode 100644 index 0000000..23bfe6a --- /dev/null +++ b/spec/reporting/reportConfigBuilder.spec.js @@ -0,0 +1,112 @@ +import { expect } from 'chai'; +import Config from '../../src/core/config.js'; +import Args from '../../src/core/args.js'; +import { buildReportConfig, validateReportConfig } from '../../src/reporting/reportConfigBuilder.js'; + +const Output = { table: () => {}, csv: () => {} }; + +function opts(overrides = {}) { + return Object.assign({ + url: undefined, token: undefined, from: undefined, to: undefined, + closed: undefined, user: undefined, milestone: undefined, + include_by_labels: undefined, exclude_by_labels: undefined, + include_labels: undefined, exclude_labels: undefined, + date_format: undefined, time_format: undefined, hours_per_day: undefined, + output: 'table', file: undefined, query: undefined, report: undefined, + record_columns: undefined, issue_columns: undefined, merge_request_columns: undefined, + no_headlines: undefined, no_warnings: undefined, quiet: undefined, + show_without_times: undefined, user_columns: undefined, type: undefined, + subgroups: undefined, verbose: undefined, + invoiceTitle: undefined, invoiceReference: undefined, invoiceText: undefined, + invoiceAddress: undefined, invoiceCurrency: undefined, invoiceCurrencyPerHour: undefined, + invoiceVAT: undefined, invoiceDate: undefined, invoiceTimeMaxUnit: undefined, + invoiceCurrencyMaxUnit: undefined, invoicePositionText: undefined, + invoicePositionExtra: undefined, invoicePositionExtraText: undefined, + invoicePositionExtraValue: undefined + }, overrides); +} + +describe('buildReportConfig', () => { + let config; + + beforeEach(() => { + config = new Config(); + }); + + it('maps plain options onto config', () => { + buildReportConfig(config, opts({ url: 'https://example.com', token: 'abc', output: 'csv' }), new Args([])); + + expect(config.get('url')).to.equal('https://example.com'); + expect(config.get('token')).to.equal('abc'); + expect(config.get('output')).to.equal('csv'); + }); + + it('resolves the project and iids from positional args', () => { + buildReportConfig(config, opts(), new Args(['group/project', '12', '34'])); + + expect(config.get('project')).to.deep.equal(['group/project']); + expect(config.get('iids')).to.deep.equal(['12', '34']); + }); + + it('applies the --today shortcut over --from/--to', () => { + buildReportConfig(config, opts({ today: true, from: '2020-01-01', to: '2020-01-02' }), new Args([])); + + expect(config.get('from').format('YYYY-MM-DD')).to.equal(config.get('to').subtract(1, 'day').format('YYYY-MM-DD')); + }); + + it('splits invoicePositionExtraText/Value into arrays, defaulting to a single empty entry', () => { + buildReportConfig(config, opts(), new Args([])); + + expect(config.get('invoicePositionExtraText')).to.deep.equal(['']); + expect(config.get('invoicePositionExtraValue')).to.deep.equal(['']); + }); +}); + +describe('validateReportConfig', () => { + let config; + + beforeEach(() => { + config = new Config(); + }); + + it('errors when no project is set', () => { + buildReportConfig(config, opts(), new Args([])); + + const { errors } = validateReportConfig(config, Output); + + expect(errors).to.include('Missing project(s) or group(s) namespace. Try this: gtt report "username/project-name"'); + }); + + it('errors when the output backend does not exist', () => { + buildReportConfig(config, opts({ output: 'nope' }), new Args(['group/project'])); + + const { errors } = validateReportConfig(config, Output); + + expect(errors.some(e => e.includes('nope'))).to.be.true; + }); + + it('errors when invoicePositionExtraText/Value lengths do not match', () => { + buildReportConfig(config, opts({ invoicePositionExtraText: 'a,b', invoicePositionExtraValue: '1' }), new Args(['group/project'])); + + const { errors } = validateReportConfig(config, Output); + + expect(errors).to.include('invoicePositionExtraText and invoicePositionExtraValue length do not match'); + }); + + it('warns when ids are given but multiple query types are requested', () => { + buildReportConfig(config, opts({ query: undefined }), new Args(['group/project', '5'])); + + const { warnings } = validateReportConfig(config, Output); + + expect(warnings).to.include('The ids argument is ignored when querying issues and merge requests'); + }); + + it('passes cleanly for a well-formed project report', () => { + buildReportConfig(config, opts(), new Args(['group/project'])); + + const { errors, warnings } = validateReportConfig(config, Output); + + expect(errors).to.deep.equal([]); + expect(warnings).to.deep.equal([]); + }); +}); diff --git a/spec/reporting/timelogs.spec.js b/spec/reporting/timelogs.spec.js new file mode 100644 index 0000000..b5c8abe --- /dev/null +++ b/spec/reporting/timelogs.spec.js @@ -0,0 +1,106 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import dayjs from '../../src/core/dayjs.js'; +import fetchTimelogs, { timelogsFor } from '../../src/reporting/api/timelogs.js'; + +function page(nodes, hasNextPage, endCursor = null) { + return { + body: { + data: { + project: { + timelogs: { + pageInfo: { hasNextPage, endCursor }, + nodes + } + } + } + } + }; +} + +function node(id) { + return { id, user: { username: 'alice' }, spentAt: '2026-01-01', timeSpent: 60 }; +} + +describe('fetchTimelogs', () => { + let client, from, to; + + beforeEach(() => { + client = { graphQL: sinon.stub() }; + from = dayjs('2026-01-01'); + to = dayjs('2026-01-31'); + }); + + it('returns the flat, ordered concatenation of all pages', async () => { + client.graphQL + .onCall(0).resolves(page([node(1), node(2)], true, 'cursor-1')) + .onCall(1).resolves(page([node(3)], false)); + + const timelogs = await fetchTimelogs(client, 'group/project', from, to); + + expect(timelogs.map(t => t.id)).to.deep.equal([1, 2, 3]); + }); + + it('requests each page with the previous page\'s end cursor, in order', async () => { + client.graphQL + .onCall(0).resolves(page([node(1)], true, 'cursor-1')) + .onCall(1).resolves(page([node(2)], false)); + + await fetchTimelogs(client, 'group/project', from, to); + + expect(client.graphQL.firstCall.args[0].variables.after).to.equal(''); + expect(client.graphQL.secondCall.args[0].variables.after).to.equal('cursor-1'); + expect(client.graphQL.firstCall.args[0].variables.project).to.equal('group/project'); + }); + + it('returns an empty array when the response has errors', async () => { + client.graphQL.resolves({ body: { errors: [{ message: 'nope' }] } }); + + const timelogs = await fetchTimelogs(client, 'group/project', from, to); + + expect(timelogs).to.deep.equal([]); + }); + + it('returns an empty array when nodes is missing', async () => { + client.graphQL.resolves({ body: { data: { project: { timelogs: { pageInfo: { hasNextPage: false } } } } } }); + + const timelogs = await fetchTimelogs(client, 'group/project', from, to); + + expect(timelogs).to.deep.equal([]); + }); + + it('stops after a single page when hasNextPage is false', async () => { + client.graphQL.resolves(page([node(1)], false)); + + await fetchTimelogs(client, 'group/project', from, to); + + expect(client.graphQL.callCount).to.equal(1); + }); +}); + +describe('timelogsFor', () => { + const timelogs = [ + { issues: { iid: 1, projectId: 10 }, id: 'a' }, + { issues: { iid: 2, projectId: 10 }, id: 'b' }, + { mergeRequests: { iid: 1, projectId: 10 }, id: 'c' }, + { issues: { iid: 1, projectId: 99 }, id: 'd' } // same iid, different project + ]; + + it('matches issues by iid and project_id', () => { + const matches = timelogsFor(timelogs, 'issues', { iid: 1, project_id: 10 }); + + expect(matches.map(t => t.id)).to.deep.equal(['a']); + }); + + it('matches merge requests by iid and project_id, independently of issues', () => { + const matches = timelogsFor(timelogs, 'mergeRequests', { iid: 1, project_id: 10 }); + + expect(matches.map(t => t.id)).to.deep.equal(['c']); + }); + + it('excludes entries from a different project sharing the same iid', () => { + const matches = timelogsFor(timelogs, 'issues', { iid: 1, project_id: 999 }); + + expect(matches).to.deep.equal([]); + }); +}); diff --git a/spec/timekeeping/timekeeper.spec.js b/spec/timekeeping/timekeeper.spec.js new file mode 100644 index 0000000..1566e52 --- /dev/null +++ b/spec/timekeeping/timekeeper.spec.js @@ -0,0 +1,124 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import Config from '../../src/core/config.js'; +import Task from '../../src/core/api/task.js'; +import Timekeeper from '../../src/timekeeping/timekeeper.js'; + +function fakeFrames(frames) { + return { + length: frames.length, + forEach: (iterator) => Promise.all(frames.map(frame => iterator(frame))) + }; +} + +function makeFrame({ project = 'group/project', type = 'issue', id = 1, duration = 3600, notes = [], isNew = false } = {}) { + return { + project, + resource: { type, id, ...(isNew ? { new: true } : {}) }, + duration, + notes, + note: null, + _stop: '2026-01-01T00:00:00Z', + title: null, + write: sinon.spy() + }; +} + +describe('Timekeeper', () => { + let config, timekeeper, make, createTime, getNotes; + + beforeEach(() => { + config = new Config(); + timekeeper = new Timekeeper(config); + + make = sinon.stub(Task.prototype, 'make').callsFake(function (project, id) { + this.data = { title: `title for ${id}`, iid: 99 }; + return Promise.resolve(this); + }); + createTime = sinon.stub(Task.prototype, 'createTime').resolves({ id: 'gid://gitlab/Note/555' }); + getNotes = sinon.stub(Task.prototype, 'getNotes').resolves([]); + }); + + afterEach(() => { + make.restore(); + createTime.restore(); + getNotes.restore(); + }); + + describe('pendingFrames', () => { + it('is exposed as a public interface used by both sync and archiveInit', () => { + expect(timekeeper.pendingFrames).to.be.a('function'); + }); + }); + + describe('sync', () => { + it('returns immediately without touching phases when there is nothing to sync', async () => { + const onPhase = sinon.spy(); + + await timekeeper.sync(fakeFrames([]), { onPhase }); + + expect(onPhase.called).to.be.false; + }); + + it('runs resolve, details and update in order with the right totals', async () => { + const frames = [makeFrame({ id: 1 }), makeFrame({ id: 2 })]; + const phases = []; + + await timekeeper.sync(fakeFrames(frames), { + onPhase: (phase, total) => phases.push([phase, total]) + }); + + expect(phases).to.deep.equal([ + ['resolve', 2], ['details', 2], ['update', 2] + ]); + }); + + it('resolves each distinct project/type/id once, and skips onProgress for repeats', async () => { + const frames = [ + makeFrame({ id: 1 }), + makeFrame({ id: 1 }), // same issue tracked across two frames + makeFrame({ id: 2 }) + ]; + let resolveProgressCalls = 0; + let phase = null; + + await timekeeper.sync(fakeFrames(frames), { + onPhase: (name) => { phase = name; }, + onProgress: () => { if (phase === 'resolve') resolveProgressCalls++; } + }); + + expect(make.callCount).to.equal(2); + expect(resolveProgressCalls).to.equal(2); + }); + + it('sets frame.title from the resolved resource', async () => { + const frame = makeFrame({ id: 7 }); + + await timekeeper.sync(fakeFrames([frame])); + + expect(frame.title).to.equal('title for 7'); + }); + + it('writes a time record note for the untracked duration and persists the frame', async () => { + const frame = makeFrame({ duration: 3600, notes: [{ id: 1, time: 1000 }] }); + + await timekeeper.sync(fakeFrames([frame])); + + expect(createTime.calledOnce).to.be.true; + expect(createTime.firstCall.args[0]).to.equal(2600); + expect(frame.notes).to.have.lengthOf(2); + expect(frame.notes[1]).to.deep.equal({ id: 555, time: 2600 }); + expect(frame.write.calledWith(true)).to.be.true; + }); + + it('promotes a new resource id to the created iid', async () => { + const frame = makeFrame({ id: 'new-issue-title', isNew: true }); + + await timekeeper.sync(fakeFrames([frame])); + + expect(frame.resource.new).to.be.undefined; + expect(frame.resource.title).to.equal('new-issue-title'); + expect(frame.resource.id).to.equal(99); + }); + }); +}); diff --git a/src/core/api/gitlab-client.js b/src/core/api/gitlab-client.js new file mode 100755 index 0000000..4e81fa5 --- /dev/null +++ b/src/core/api/gitlab-client.js @@ -0,0 +1,200 @@ +import { throttledQueue } from 'throttled-queue'; +import parallel from '../parallel.js'; + +/** + * GitLab REST/GraphQL client: owns the request throttle, single/parallel + * paginated GET, POST and GraphQL. Root of the API-model hierarchy. + */ +class GitlabClient { + static throttle; + + static init(config) { + if(GitlabClient.throttle == undefined){ + GitlabClient.throttle = throttledQueue({ + maxPerInterval: config.data.throttleMaxRequestsPerInterval, + interval: config.data.throttleInterval + }); + } + } + + + /** + * construct + * @param config + */ + constructor(config) { + GitlabClient.init(config); + this.config = config; + + this.url = config.get('url').endsWith('/') ? config.get('url') : `${config.get('url')}/`; + this.token = config.get('token'); + + this._perPage = this.config ? this.config.get('_perPage') : 100; + this._parallel = this.config ? this.config.get('_parallel') : 4; + } + + /** + * query the given path + * @param path + * @param data + * @returns {Promise} + */ + post(path, data) { + return GitlabClient.throttle(async () => { + const response = await fetch(`${this.url}${path}`, { + method: 'POST', + headers: { + 'PRIVATE-TOKEN': this.token, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + + await GitlabClient.assertOk(response, 'POST', path); + + const isJson = (response.headers.get('content-type') ?? '').startsWith('application/json'); + const body = isJson ? await response.json() : undefined; + + return { body, headers: response.headers }; + }); + } + + /** + * throw a descriptive error if the response is not OK + * @param response + * @param method + * @param path + */ + static async assertOk(response, method, path) { + if (response.ok) return; + + let body = ''; + try { + body = (await response.text()).slice(0, 512); + } catch { /* body is optional error context */ } + + throw new Error(`${method} ${path} failed: ${response.status} ${response.statusText}${body ? ` — ${body}` : ''}`); + } + + /** + * throw if the response is not JSON + * @param response + * @param method + * @param path + */ + static assertJson(response, method, path) { + const contentType = response.headers.get('content-type') ?? ''; + + if (!contentType.startsWith('application/json')) + throw new Error(`${method} ${path} returned content-type "${contentType}", expected application/json`); + } + + + /** + * query the given path + * @param data + * @returns {Promise} + */ + graphQL(data) { + // remove v4/ from url, add graphql + const path = this.url.substr(0, this.url.length-3) + 'graphql'; + + return GitlabClient.throttle(async () => { + const response = await fetch(`${path}`, { + method: 'POST', + headers: { + 'Authorization': 'Bearer '+this.token, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + + await GitlabClient.assertOk(response, 'POST', path); + GitlabClient.assertJson(response, 'POST', path); + + return { body: await response.json(), headers: response.headers }; + }); + } + + + /** + * query the given path + * @param path + * @param page + * @param perPage + * @returns {Promise} + */ + get(path, page = 1, perPage = this._perPage) { + path += (path.includes('?') ? '&' : '?') + `page=${page}&per_page=${perPage}`; + + return GitlabClient.throttle(async () => { + const response = await fetch(`${this.url}${path}`, { + headers: { + 'PRIVATE-TOKEN': this.token + } + }); + + await GitlabClient.assertOk(response, 'GET', path); + GitlabClient.assertJson(response, 'GET', path); + + return { body: await response.json(), headers: response.headers }; + }); + } + + /** + * query the given path and paginate automatically and in parallel + * through all available pages + * @param path + * @param perPage + * @param runners + * @returns {Promise} + */ + async all(path, perPage = this._perPage, runners = this._parallel) { + const response = await this.get(path, 1, perPage); + const collect = [...response.body]; + const pages = parseInt(response.headers.get('x-total-pages')); + + if (pages === 1) return collect; + + const tasks = GitlabClient.createGetTasks(path, pages, 2, perPage); + await this.getParallel(tasks, collect, runners); + + return collect; + } + + /** + * make multiple get requests by the given tasks and apply the + * data to the given set + * @param tasks + * @param collect + * @param runners + * @returns {Promise} + */ + getParallel(tasks, collect = [], runners = this._parallel) { + return parallel(tasks, async task => { + const response = await this.get(task.path, task.page, task.perPage); + response.body.forEach(item => collect.push(item)); + }, this.config, runners); + } + + /** + * create a task list to get all pages from + * the given path + * @param path + * @param to + * @param from + * @param perPage + * @returns {Array} + */ + static createGetTasks(path, to, from = 2, perPage) { + let tasks = []; + + for (let i = from; i <= to; i++) { + tasks.push({path, perPage, page: i}) + } + + return tasks; + } +} + +export default GitlabClient; diff --git a/src/core/api/issue.js b/src/core/api/issue.js new file mode 100644 index 0000000..aca2b00 --- /dev/null +++ b/src/core/api/issue.js @@ -0,0 +1,22 @@ +import CoreTask from './task.js'; +import GitlabClient from './gitlab-client.js'; + +class Issue extends CoreTask { + static resoureType = 'issues'; + + constructor(config, data, client, project) { + super(config, data, client, Issue.resoureType, project); + } + + static list(config, project, state, my, client = new GitlabClient(config)) { + const query = `scope=${my ? "assigned-to-me" : "all"}&state=${state}`; + const path = project + ? `projects/${encodeURIComponent(project)}/${Issue.resoureType}?${query}` + : `${Issue.resoureType}/?${query}`; + + return client.get(path) + .then(response => response.body.map(data => new this(config, data, client))); + } +} + +export default Issue; diff --git a/src/core/api/mergeRequest.js b/src/core/api/mergeRequest.js new file mode 100644 index 0000000..8e958a2 --- /dev/null +++ b/src/core/api/mergeRequest.js @@ -0,0 +1,22 @@ +import CoreTask from './task.js'; +import GitlabClient from './gitlab-client.js'; + +class MergeRequest extends CoreTask { + static resoureType = 'merge_requests'; + + constructor(config, data, client, project) { + super(config, data, client, MergeRequest.resoureType, project); + } + + static list(config, project, state, my, client = new GitlabClient(config)) { + const query = `scope=${my ? "assigned-to-me" : "all"}&state=${state}`; + const path = project + ? `projects/${encodeURIComponent(project)}/${MergeRequest.resoureType}?${query}` + : `${MergeRequest.resoureType}}/?${query}`; + + return client.get(path) + .then(response => response.body.map(data => new this(config, data, client))); + } +} + +export default MergeRequest; diff --git a/src/core/api/owner.js b/src/core/api/owner.js new file mode 100755 index 0000000..bc24bae --- /dev/null +++ b/src/core/api/owner.js @@ -0,0 +1,82 @@ +import GitlabClient from './gitlab-client.js'; +import parallel from '../parallel.js'; + +/** + * owner model + */ +class Owner { + constructor(config, client = new GitlabClient(config)) { + this.config = config; + this.client = client; + this.projects = []; + this.groups = []; + this.users = []; + } + + /** + * is authorized? + * @returns {Promise} + */ + async authorized() { + if (!this.config.get('_checkToken')) return; + + try { + await this.client.get('broadcast_messages'); + } catch (e) { + if (e.statusCode === 403) return; + throw e; + } + } + + /** + * query and set the group + * @param fullPath group path, e.g. "group/subgroup" + * @returns {Promise} + */ + async getGroup(fullPath = this.config.get('project')) { + let groups = await this.client.get(`groups`); + if (groups.body.length === 0) throw 'Group not found'; + + let filtered = groups.body.filter(group => group.full_path === fullPath); + if (filtered.length === 0) throw 'Group not found'; + this.groups = this.groups.concat(filtered); + } + + /** + * get sub groups + * @returns {Promise} + */ + async getSubGroups() { + let groups = await this.client.get(`groups`); + if (groups.body.length === 0) return; + + let filtered = this._filterGroupsByParents(groups.body, this.groups.map(g => g.id)); + if (filtered.length === 0) return; + + this.groups = this.groups.concat(filtered); + } + + _filterGroupsByParents(groups, parents) { + let filtered = groups.filter(group => { + return parents.indexOf(group.parent_id) !== -1; + }); + + if (filtered.length !== 0) { + filtered = filtered.concat(this._filterGroupsByParents(groups, filtered.map(g => g.id))); + } + + return filtered; + } + + /** + * query and set the projects by a user + * @returns {Promise} + */ + getProjectsByGroup() { + return parallel(this.groups, async group => { + this.projects = await this.client.all(`groups/${group.id}/projects`); + }, this.config); + } +} + +export default Owner; diff --git a/src/core/api/task.js b/src/core/api/task.js new file mode 100644 index 0000000..ac7e6a7 --- /dev/null +++ b/src/core/api/task.js @@ -0,0 +1,212 @@ +import dayjs from '../dayjs.js'; +import GitlabClient from './gitlab-client.js'; +import Time from '../time.js'; +import chargeRatio from '../billing.js'; +import Project from '../../reporting/api/project.js'; + +class Task { + /** + * @param config + * @param data + * @param client + * @param type + * @param {Project} [project] the owning project's, if known + */ + constructor(config, data = {}, client = new GitlabClient(config), type, project) { + this.config = config; + this.client = client; + this.times = []; + this.data = data; + this.type = type; + this.project = project; + } + + get iid() { + return this.data.iid; + } + + get id() { + return this.data.id; + } + + get title() { + return this.data.title; + } + + get project_id() { + return this.data.project_id; + } + + get project_namespace() { + return this.project.namespace; + } + + get project_name() { + return this.project.name; + } + + get description() { + return this.data.description; + } + + get labels() { + let excludeLabels = this.config.get('excludeLabels'); + let labels = Array.isArray(excludeLabels) + ? (this.data.labels || []).filter(label => !excludeLabels.includes(label)) + : (this.data.labels || []); + let include = this.config.get('includeLabels'); + return include.length > 0 ? labels.filter(label => include.includes(label)) : labels; + } + + get milestone() { + return this.data.milestone ? this.data.milestone.title : null; + } + + get assignee() { + return this.data.assignee ? this.data.assignee.username : null; + } + + get author() { + return this.data.author.username; + } + + get closed() { + return this.data.state === 'closed'; + } + + get updated_at() { + return dayjs(this.data.updated_at); + } + + get created_at() { + return dayjs(this.data.created_at); + } + + get state() { + return this.data.state; + } + + get spent() { + return this.config.toHumanReadable(this.timeSpent, this._type); + } + + get due_date() { + return this.data.due_date ? dayjs(this.data.due_date): null; + } + + get total_spent() { + return this.data.time_stats ? this.config.toHumanReadable(this.data.time_stats.total_time_spent, this._type) : null; + } + + get total_spent_s() { + return this.data.time_stats ? this.data.time_stats.total_time_spent : 0; + } + + get total_estimate() { + return this.data.time_stats ? this.config.toHumanReadable(this.data.time_stats.time_estimate, this._type) : null; + } + + get total_estimate_s() { + return this.data.time_stats ? this.data.time_stats.time_estimate : 0; + } + + get _type() { + return this.type; + } + + get _typeSingular() { + return this.type === 'merge_requests' ? 'Merge Request' : 'Issue'; + } + + make(project, id, create = false) { + let promise = create + ? this.client.post(`projects/${encodeURIComponent(project)}/${this._type}`, {title: id}) + : this.client.get(`projects/${encodeURIComponent(project)}/${this._type}/${id}`); + + return promise.then(response => { + this.data = response.body; + return this; + }); + } + + async getNotes() { + let notes = await this.client.all(`projects/${this.data.project_id}/${this._type}/${this.iid}/notes`); + this.notes = notes; + + return notes; + } + + createTime(time, created_at, note) { + if(note === null || note === undefined) { + note = ''; + } + else { + note = '\n\n' + note; + } + var date = new Date(created_at); + var spentAt = date.getUTCFullYear()+"-"+(date.getUTCMonth()+1)+"-"+date.getUTCDate(); + const query = + `mutation($input: CreateNoteInput!) { + createNote(input: $input) { + note { + id + body + } + errors + } + }` + let noteablePath = (this._type == 'merge_requests') ? 'MergeRequest' : 'WorkItem'; + let request = { + "query": query, + "variables": { + "input": { + "noteableId": `gid://gitlab/${noteablePath}/${this.id}`, + "body": '/spend '+Time.toHumanReadable(time, this.config.get('hoursPerDay'), '[%sign][%days>d ][%hours>h ][%minutes>m ][%seconds>s]' + ' ' + spentAt + note), + } + } + }; + return this.client.graphQL(request).then(response => { + let errors = response.body?.errors ?? response.body?.data?.createNote?.errors; + if(!response.body || (errors && errors.length)) { + throw new Error(`createTime failed: ${JSON.stringify(response.body)}`); + } + return response.body.data.createNote.note; + }); + } + + recordTimelogs(timelogs){ + let ratio = chargeRatio(this.labels, this.config); + + let times = [], + timeSpent = 0, + timeUsers = {}, + timeFormat = this.config.get('timeFormat', this._type); + + timelogs.forEach( + (timelog) => { + let spentAt = dayjs(timelog.spentAt); + + let time = new Time(spentAt, { + author: {username: timelog.user.username}, + created_at: timelog.spentAt, + noteable_type: this._typeSingular + }, this.config, timelog.timeSpent, timelog.note && timelog.note.body ? timelog.note.body : null, ratio); + + // only include times by the configured user + if (this.config.get('user') && this.config.get('user') !== timelog.user.username) return; + + if (!timeUsers[timelog.user.username]) timeUsers[timelog.user.username] = 0; + + timeSpent += time.seconds; + timeUsers[timelog.user.username] += time.seconds; + + times.push(time); + }); + + Object.entries(timeUsers).forEach(([name, time]) => this[`time_${name}`] = Time.toHumanReadable(time, this.config.get('hoursPerDay'), timeFormat)); + this.timeSpent = timeSpent; + this.times = times; + } +} + +export default Task; diff --git a/src/core/args.js b/src/core/args.js new file mode 100644 index 0000000..211034e --- /dev/null +++ b/src/core/args.js @@ -0,0 +1,47 @@ +/** + * Args helper + */ +class Args { + constructor(args) { + this.args = args; + /** @type {{project?: string[], iids?: string[]}} */ + this.data = {}; + } + + /** + * parse the args and return the project argument + * @returns {*} + */ + project() { + if (!this.args[0] && !this.data.project) return null; + + if (this.data.project) return this.data.project; + + let projects = [...new Set(this.args.filter(arg => isNaN(Number(arg))))]; + this.args = this.args.filter(arg => !projects.includes(arg)); + + if(projects.length == 0) + return null; + + return this.data.project = projects; + } + + /** + * parse the args and return an array of issues + * @returns {*} + */ + iids() { + if (this.data.iids) return this.data.iids; + + this.data.iids = [...new Set(this.args.map((issue) => { + if (issue.indexOf(',') === -1) return issue; + return issue.split(','); + }).flat())]; + + if (this.data.iids.length === 0) return null; + + return this.data.iids; + } +} + +export default Args; diff --git a/src/core/billing.js b/src/core/billing.js new file mode 100644 index 0000000..0c31c13 --- /dev/null +++ b/src/core/billing.js @@ -0,0 +1,15 @@ +/** + * Charge ratio for a set of GitLab labels, driven by the freeLabels/ + * halfPriceLabels config. Free wins over half-price if both match. + * @param {string[]} labels + * @param config + * @returns {number} 0.0, 0.5 or 1.0 + */ +export default function chargeRatio(labels, config) { + let free = config.get('freeLabels') ?? []; + let halfPrice = config.get('halfPriceLabels') ?? []; + + if (labels.some(label => free.includes(label))) return 0.0; + if (labels.some(label => halfPrice.includes(label))) return 0.5; + return 1.0; +} diff --git a/src/core/cli.js b/src/core/cli.js new file mode 100755 index 0000000..6405a57 --- /dev/null +++ b/src/core/cli.js @@ -0,0 +1,242 @@ +import pc from 'picocolors'; +import confirm from '@inquirer/confirm'; +import cursor from 'cli-cursor'; +import progress from 'progress'; + +const spinnerFrames = ['|', '/', '-', '\\']; +let spinnerIndex = 0; +const spinner = { next: () => spinnerFrames[spinnerIndex++ % spinnerFrames.length] }; + +/** + * thrown by Cli.error - carries the exit code the process should end + * with once the caller (or the top-level unhandledRejection handler in + * gtt.js) is done unwinding. + */ +export class CliExitError extends Error { + constructor(message, code = 1) { + super(message); + this.code = code; + } +} + +/** + * Cli helper + */ +class Cli { + /** @type {boolean} */ + static quiet = false; + /** @type {boolean} */ + static verbose = false; + /** @type {any} */ + static active; + + /* + * emojis + */ + static get update() { + return '⏱'; + } + + static get print() { + return '🖨'; + } + + static get look() { + return '🔍'; + } + + static get fetch() { + return '📦'; + } + + static get process() { + return '⚙️'; + } + + static get output() { + return '📃'; + } + + static get merge() { + return '📎'; + } + + static get party() { + return '🥑'; + } + + /** + * ask + * @param message + * @returns {Promise} + */ + static async ask(message) { + let answer = await confirm({ message, default: true }); + + if (!answer) throw new Error('Declined'); + } + + /** + * print + * @param string + */ + static out(string) { + if (Cli.quiet) return; + process.stdout.write(string); + } + + /** + * print done message + */ + static done() { + Cli.out(pc.green(`\n${Cli.party} Finished!\n`)); + } + + /** + * print a warning + * @param message + */ + static warn(message) { + Cli.out(pc.bgWhite(pc.black(` Warning: ${message} `)) + "\n"); + } + + /** + * create a new bar + * @param message + * @param total + * @returns {*} + */ + static bar(message, total) { + Cli.resolve(false); + + if (Cli.quiet) return Cli.promise(); + + this.active = { + started: new Date(), + message: pc.bold(pc.gray(`\r${message}... `)), + bar: new progress(`${message} (:current/:total) [:bar] :percent - :minutesm left`, { + total, + clear: true, + width: 40, + renderThrottle: 100 + }), + interval: setInterval(() => { + if (!Cli.active.bar || Cli.active.bar.complete) return clearInterval(Cli.active.interval); + Cli.tick(0); + }, 1000) + }; + + this.tick(); + return Cli.promise(); + } + + /** + * bar tick + * @param amount + */ + static tick(amount = 0) { + if (!Cli.active.bar || !Cli.active.started) return; + + let left; + + if (Cli.active.bar.curr > 0) { + let elapsed = Math.ceil((new Date().getTime() - Cli.active.started.getTime()) / 1000); + left = ((elapsed / Cli.active.bar.curr) * (Cli.active.bar.total - Cli.active.bar.curr)) / 60; + left = left < 1 ? `<1` : Math.ceil(left); + } else { + left = 0; + } + + Cli.active.bar.tick(amount, { + minutes: left + }); + } + + /** + * advance an existing bar + */ + static advance() { + Cli.tick(1); + } + + /** + * create a new list, including a spinner + * @param message + * @returns {*} + */ + static list(message) { + Cli.resolve(false); + + this.active = {message: pc.bold(pc.gray(`\r${message}... `))}; + this.active.interval = setInterval(() => { + Cli.out(Cli.active.message + pc.bold(pc.blue(spinner.next()))); + }, 100); + + return Cli.promise(); + } + + /** + * stop a list item with a check mark + * @returns {*} + */ + static mark() { + Cli.resolve(); + if (Cli.active) Cli.out(`${Cli.active.message}` + pc.green(`✓\n`)); + + return Cli.promise(); + } + + /** + * stop a list item with an x + * @param {string|Error|false} [message] + * @param {Error|false} [error] + * @returns {Promise} + */ + static x(message = false, error = false) { + Cli.resolve(); + if (Cli.active) Cli.out(`${Cli.active.message}` + pc.red(`✗\n`)); + + if (message) Cli.error(message, error); + return Cli.promise(); + } + + /** + * stop and resolve a list or bar + */ + static resolve(show = true) { + cursor.toggle(show); + if (Cli.active && Cli.active.interval) clearInterval(Cli.active.interval); + } + + /** + * show an error message + * @param {string|Error} message + * @param {Error|false} [error] + * @returns {never} + */ + static error(message, error) { + Cli.resolve(); + + if (message instanceof Error) { + error = error ?? message; + message = message.message; + } + + Cli.out(`Error: ${pc.red(message)}` + '\n'); + if (error && Cli.verbose) console.log(error); + + throw new CliExitError(message, 1); + } + + /** + * get a promise (for chaining promises) + * @returns {Promise} + */ + static promise() { + return new Promise(resolve => { + resolve(); + }); + } +} + +export default Cli; \ No newline at end of file diff --git a/src/gtt-config.js b/src/core/commands/config.js similarity index 55% rename from src/gtt-config.js rename to src/core/commands/config.js index 882b7b9..26243eb 100755 --- a/src/gtt-config.js +++ b/src/core/commands/config.js @@ -1,14 +1,14 @@ import {Command} from 'commander'; -import Config from './include/file-config.js'; -import Fs from './include/filesystem.js'; +import Fs from '../filesystem.js'; -let config = new Config(process.cwd()); - -function cfgCmd() { - const cfgCmd = new Command('config', 'edit the configuration file in your default editor') +function cfgCmd(configLoader) { + const cfgCmd = new Command('config') + .description('edit the configuration file in your default editor') .option('-l, --local', 'edit the local configuration file') .action((options, program) => { +let config = configLoader(); + if (program.opts().local) { config.assertLocalConfig(); } diff --git a/src/include/config.js b/src/core/config.js similarity index 82% rename from src/include/config.js rename to src/core/config.js index d91e303..dcd8e88 100755 --- a/src/include/config.js +++ b/src/core/config.js @@ -1,7 +1,5 @@ -import moment from 'moment'; -import _ from 'underscore'; -import Time from './../models/time.js'; -import EventEmitter from 'events'; +import dayjs from './dayjs.js'; +import Time from './time.js'; const dates = ['from', 'to']; const objectsWithDefaults = ['timeFormat', 'columns']; @@ -12,7 +10,7 @@ const defaults = { token: false, project: false, from: "1970-01-01", - to: moment().format(), + to: dayjs().add(1, 'day').format('YYYY-MM-DD'), iids: false, closed: false, milestone: false, @@ -21,7 +19,7 @@ const defaults = { weeksPerMonth: 4, issueColumns: ['iid', 'title', 'spent', 'total_estimate'], mergeRequestColumns: ['iid', 'title', 'spent', 'total_estimate'], - recordColumns: ['user', 'date', 'type', 'iid', 'time'], + recordColumns: ['user', 'date', 'project', 'type', 'iid', 'title', 'time', 'note'], userColumns: false, dateFormat: 'DD.MM.YYYY HH:mm:ss', timeFormat: Time.defaultTimeFormat, @@ -50,14 +48,12 @@ const defaults = { /** * basic config */ -class config extends EventEmitter { +class Config { /** * construct */ constructor() { - super(); - - this.data = _.extend({}, defaults); + this.data = {...defaults}; } /** @@ -67,7 +63,7 @@ class config extends EventEmitter { * @param key * @param value * @param force - * @returns {config} + * @returns {Config} */ set(key, value, force = false) { if (!force && (value === null || value === undefined)) return this; @@ -85,9 +81,9 @@ class config extends EventEmitter { */ get(key, subKey = false) { if (dates.includes(key)) - return moment(this.data[key]); + return dayjs(this.data[key]); - if (objectsWithDefaults.includes(key) && _.isObject(this.data[key])) + if (objectsWithDefaults.includes(key) && typeof this.data[key] === 'object' && this.data[key] !== null) return subKey && this.data[key][subKey] ? this.data[key][subKey] : defaults[key]; return this.data[key]; @@ -104,4 +100,4 @@ class config extends EventEmitter { } } -export default config; +export default Config; diff --git a/src/core/configFile.js b/src/core/configFile.js new file mode 100644 index 0000000..accc9d5 --- /dev/null +++ b/src/core/configFile.js @@ -0,0 +1,63 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { load as yamlLoad } from 'js-yaml'; +import Fs from './filesystem.js'; + +/** + * Walk up from startDir looking for a file named `filename`. + * @param startDir + * @param filename + * @returns {string|null} the directory it was found in, or null + */ +export function findLocalConfigDir(startDir, filename) { + if (fs.existsSync(Fs.join(startDir, filename))) return startDir; + + const root = (os.platform() === 'win32') ? process.cwd().split(path.sep)[0] + '\\' : '/'; + let dir = startDir; + + while (dir) { + dir = path.dirname(dir); + if (dir === root) dir = ''; + if (fs.existsSync(Fs.join(dir, filename))) return dir; + } + + return null; +} + +/** + * Read and parse one YAML config file. + * @param file + * @returns {Object} + */ +export function readConfigFile(file) { + try { + return yamlLoad(fs.readFileSync(file, 'utf8')); + } catch (e) { + e.message = `Error parsing configuration: "${file}": ${e.message}`; + throw e; + } +} + +/** + * Resolve a local config against the extend: chaining rule: local + * overrides global (extend: true, the default), local overrides an + * explicitly named file (extend: ), or local stands alone. + * @param localFile + * @param globalFile + * @returns {Object} + */ +export function resolveLocalConfig(localFile, globalFile) { + let local = Object.assign({extend: true}, readConfigFile(localFile)); + + if (local.extend === true) { + let global = readConfigFile(globalFile); + return Object.assign(global ? global : {}, local); + } + + if (local.extend) { + return Object.assign(readConfigFile(local.extend), local); + } + + return local; +} diff --git a/src/core/dayjs.js b/src/core/dayjs.js new file mode 100644 index 0000000..671142d --- /dev/null +++ b/src/core/dayjs.js @@ -0,0 +1,14 @@ +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc.js'; +import timezone from 'dayjs/plugin/timezone.js'; +import relativeTime from 'dayjs/plugin/relativeTime.js'; +import advancedFormat from 'dayjs/plugin/advancedFormat.js'; + +// single place to configure dayjs: utc+timezone for frame timestamps, +// relativeTime for "x minutes ago", advancedFormat for the "Do" token +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(relativeTime); +dayjs.extend(advancedFormat); + +export default dayjs; diff --git a/src/core/file-config.js b/src/core/file-config.js new file mode 100755 index 0000000..ef6498d --- /dev/null +++ b/src/core/file-config.js @@ -0,0 +1,71 @@ +import fs from 'fs'; +import Config from './config.js'; +import { dump as yamlDump } from 'js-yaml'; +import Fs from './filesystem.js'; +import envPaths from 'env-paths'; +import { findLocalConfigDir, readConfigFile, resolveLocalConfig } from './configFile.js'; + +/** + * file config with local and global configuration files + */ +class FileConfig extends Config { + /** + * construct + * @param workDir + * @param load set to false to skip parsing the config files, e.g. when + * recovering from a broken config to still resolve its paths + */ + constructor(workDir, recover) { + super(); + this.assertGlobalConfig(recover); + this.workDir = workDir; + if(!recover) { + this.data = Object.assign(this.data, this.localExists() ? resolveLocalConfig(this.local, this.global) : readConfigFile(this.global)); + } + if (!fs.existsSync(this.frameDir)) fs.mkdirSync(this.frameDir, { recursive: true }); + } + + localExists() { + if (fs.existsSync(this.local)) return true; + + let found = findLocalConfigDir(this.workDir, this.localConfigFile); + if (found === null) return false; + + this.workDir = found; + return true; + } + + assertGlobalConfig(recover) { + if (!fs.existsSync(this.globalDir)) fs.mkdirSync(this.globalDir, { recursive: true }); + if (recover && !fs.existsSync(this.global)) fs.appendFileSync(this.global, yamlDump(this.data)); + } + + assertLocalConfig() { + if (!this.localExists()) fs.appendFileSync(this.local, ''); + } + + get localConfigFile() { + return '.gtt.yml'; + } + + get globalDir() { + return envPaths(".gtt", {suffix:""}).data; + } + + get frameDir() { + if(this.data.frameDir) { + return this.data.frameDir; + } + return Fs.join(this.globalDir, 'frames'); + } + + get global() { + return Fs.join(this.globalDir, 'config.yml'); + } + + get local() { + return Fs.join(this.workDir, this.localConfigFile); + } +} + +export default FileConfig; diff --git a/src/include/filesystem.js b/src/core/filesystem.js similarity index 52% rename from src/include/filesystem.js rename to src/core/filesystem.js index de173ee..b2e0953 100755 --- a/src/include/filesystem.js +++ b/src/core/filesystem.js @@ -1,19 +1,9 @@ -import _ from 'underscore'; import fs from 'fs'; import path from 'path'; import open from 'open'; -import find from 'find-in-files'; import child_process from 'child_process'; -class filesystem { - static find(pattern, dir) { - return new Promise((resolve, reject) => { - find.find(pattern, dir) - .then(results => resolve(_.keys(results))) - .catch(error => reject(error)); - }); - } - +class Filesystem { static exists(file) { return fs.existsSync(file); } @@ -22,6 +12,14 @@ class filesystem { return fs.unlinkSync(file); } + static readText(file) { + return fs.readFileSync(file, 'utf8'); + } + + static writeText(file, data) { + return fs.writeFileSync(file, data); + } + static open(file) { let editor = process.env.VISUAL; @@ -38,12 +36,23 @@ class filesystem { return path.join(...args); } + /** + * @param dir + * @returns {import('fs').Dirent|null} null when the directory has no files + */ static newest(dir) { - return _.max(filesystem.readDir(dir), file => (fs.statSync(path.join(dir, file.name)).ctime)); + let files = Filesystem.readDir(dir); + if (files.length === 0) return null; + + let ctime = file => fs.statSync(path.join(dir, file.name)).ctime; + + return files.reduce((newest, file) => (ctime(file) > ctime(newest) ? file : newest), files[0]); } static all(dir) { - return _.sortBy(filesystem.readDir(dir), file => (fs.statSync(path.join(dir, file.name)).ctime)); + let ctime = file => fs.statSync(path.join(dir, file.name)).ctime.getTime(); + + return Filesystem.readDir(dir).sort((a, b) => ctime(a) - ctime(b)); } static readDir(dir) { @@ -51,4 +60,4 @@ class filesystem { } } -export default filesystem; +export default Filesystem; diff --git a/src/core/parallel.js b/src/core/parallel.js new file mode 100644 index 0000000..11ae70b --- /dev/null +++ b/src/core/parallel.js @@ -0,0 +1,30 @@ +/** + * run the given worker over the given tasks with a bounded number of + * concurrent runners. Rejects with the first worker error; no new tasks + * are started after a failure. + * @param tasks iterable of work items + * @param worker async (task) => void — may also be a plain sync function + * @param config config instance, supplies the default runner count (_parallel) + * @param runners max number of concurrent workers, defaults to config._parallel + * @returns {Promise} + */ +export default async function parallel(tasks, worker, config, runners = config.get('_parallel')) { + const queue = Array.from(tasks); + let index = 0; + let failed = false; + + const runner = async () => { + while (index < queue.length && !failed) { + const task = queue[index++]; + try { + await worker(task); + } catch (error) { + failed = true; + throw error; + } + } + }; + + const count = Math.min(Math.max(parseInt(runners) || 1, 1), Math.max(queue.length, 1)); + await Promise.all(Array.from({ length: count }, runner)); +} diff --git a/src/models/time.js b/src/core/time.js similarity index 57% rename from src/models/time.js rename to src/core/time.js index 5535f19..dfcf122 100755 --- a/src/models/time.js +++ b/src/core/time.js @@ -1,40 +1,35 @@ -import _ from 'underscore'; -import moment from 'moment'; +import dayjs from './dayjs.js'; const defaultTimeFormat = '[%sign][%days>d ][%hours>h ][%minutes>m ][%seconds>s]'; -const mappings = ['complete', 'sign', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds']; -const regex = /^(?:([-])\s*)?(?:(\d+)mo\s*)?(?:(\d+)w\s*)?(?:(\d+)d\s*)?(?:(\d+)h\s*)?(?:(\d+)m\s*)?(?:(\d+)s\s*)?$/; const conditionalRegex = /(\[\%([^\>\]]*)\>([^\]]*)\])/ig; const roundedRegex = /(\[\%([^\>\]]*)\:([^\]]*)\])/ig; const conditionalSimpleRegex = /([0-9]*)\>(.*)/ig; const defaultRegex = /(\[\%([^\]]*)\])/ig; -Number.prototype.padLeft = function (n, str) { - return Array(n - String(this).length + 1).join(str || '0') + this; -}; +function padLeft(value, n, str) { + return Array(Math.max(0, n - String(value).length + 1)).join(str || '0') + value; +} /** * time model */ -class time { +class Time { /** * construct - * @param timeString - * @param note - * @param {hasTimes} parent + * @param date + * @param data raw noteable payload (author, created_at, noteable_type) * @param config + * @param {number} seconds + * @param {string|null} [note] + * @param {number} [chargeRatio] */ - constructor(timeString, date = null, note, parent, config) { - this.data = note; + constructor(date = null, data, config, seconds, note = null, chargeRatio = 1.0) { + this.data = data; this._date = date; - this.parent = parent; this.config = config; - - if(!timeString) { - return; - } - - this.seconds = time.parse(timeString, this._hoursPerDay, this._daysPerWeek, this._weeksPerMonth); + this.note = note; + this.chargeRatio = chargeRatio; + this.seconds = seconds; } /* @@ -49,32 +44,15 @@ class time { } get date() { - return this._date ? moment(this._date) : moment(this.data.created_at); + return this._date ? dayjs(this._date) : dayjs(this.data.created_at); } get type() { return this.data.noteable_type; } - get project_id() { - return this.parent.data.project_id; - } - - get iid() { - return this.parent.iid; - } - get time() { - return time.toHumanReadable(this.seconds, this._hoursPerDay, this._timeFormat); - } - - /** - * Title of the linked Noteable object (Issue/MergeRequest) - * - * @returns {String|null} - */ - get title() { - return this.parent && this.parent.title || null; + return Time.toHumanReadable(this.seconds, this._hoursPerDay, this._timeFormat); } get _timeFormat() { @@ -93,28 +71,6 @@ class time { return this.config && this.config.get('weeksPerMonth') ? parseInt(this.config.get('weeksPerMonth')) : 4; } - /** - * parse human readable to seconds - * @param string - * @param hoursPerDay - * @param daysPerWeek - * @param weeksPerMonth - * @returns {*} - */ - static parse(string, hoursPerDay = 8, daysPerWeek = 5, weeksPerMonth = 4) { - let match, parsed; - - if ((match = regex.exec(string)) === null) return false; - parsed = _.object(mappings, match.map(i => i === undefined ? 0 : i)); - - return (parsed.sign ? -1 : 1) * (parseInt(parsed.seconds) - + (parseInt(parsed.minutes) * 60) - + (parseInt(parsed.hours) * 60 * 60) - + (parseInt(parsed.days) * hoursPerDay * 60 * 60) - + (parseInt(parsed.weeks) * daysPerWeek * hoursPerDay * 60 * 60) - + (parseInt(parsed.months) * weeksPerMonth * daysPerWeek * hoursPerDay * 60 * 60)); - } - /** * get human readable * @param input @@ -122,7 +78,7 @@ class time { * @param format * @returns {string} */ - static toHumanReadable(input, hoursPerDay = 8, format = time.defaultTimeFormat) { + static toHumanReadable(input, hoursPerDay = 8, format = Time.defaultTimeFormat) { let sign = parseInt(input) < 0 ? '-' : '', output = format, match; input = Math.abs(input); @@ -136,18 +92,18 @@ class time { inserts.days_overall = input / secondsInADay; inserts.days_overall_comma = inserts.days_overall.toString().replace('.', ','); inserts.days = Math.floor(inserts.days_overall); - inserts.Days = inserts.days.padLeft(2, 0); + inserts.Days = padLeft(inserts.days, 2, '0'); inserts.hours_overall = input / secondsInAnHour; inserts.hours_overall_comma = inserts.hours_overall.toString().replace('.', ','); inserts.hours = Math.floor((input % secondsInADay) / secondsInAnHour); - inserts.Hours = inserts.hours.padLeft(2, 0); + inserts.Hours = padLeft(inserts.hours, 2, '0'); inserts.minutes_overall = input / secondsInAMinute; inserts.minutes_overall_comma = (inserts.minutes_overall).toString().replace('.', ','); inserts.minutes = Math.floor(((input % secondsInADay) % secondsInAnHour) / secondsInAMinute); - inserts.Minutes = inserts.minutes.padLeft(2, 0); + inserts.Minutes = padLeft(inserts.minutes, 2, '0'); inserts.seconds_overall = input; inserts.seconds = ((input % secondsInADay) % secondsInAnHour) % secondsInAMinute; - inserts.Seconds = inserts.seconds.padLeft(2, 0); + inserts.Seconds = padLeft(inserts.seconds, 2, '0'); // rounded while ((match = roundedRegex.exec(format)) !== null) { @@ -158,9 +114,9 @@ class time { decimals = conditionalMatch[1] } - decimals = parseInt(decimals); - time = Math.ceil(inserts[match[2]] * Math.pow(10, decimals)) / Math.pow(10, decimals); - output = output.replace(match[0], time !== 0 && conditionalMatch ? time + conditionalMatch[2] : time); + let iDecimals = parseInt(decimals); + time = Math.ceil(inserts[match[2]] * Math.pow(10, iDecimals)) / Math.pow(10, iDecimals); + output = output.replace(match[0], (time !== 0 && conditionalMatch ? time + conditionalMatch[2] : time).toString()); } // conditionals @@ -180,4 +136,4 @@ class time { } } -export default time; +export default Time; diff --git a/src/core/zip.js b/src/core/zip.js new file mode 100644 index 0000000..71cbcc8 --- /dev/null +++ b/src/core/zip.js @@ -0,0 +1,179 @@ +import fs from 'fs'; +import zlib from 'zlib'; + +const METHOD_STORE = 0; +const METHOD_DEFLATE = 8; + +/** + * convert a JS Date to DOS date/time fields used by the zip format + */ +function dosDateTime(date) { + const time = ((date.getHours() & 0x1f) << 11) | ((date.getMinutes() & 0x3f) << 5) | ((date.getSeconds() >> 1) & 0x1f); + const day = (((Math.max(date.getFullYear(), 1980) - 1980) & 0x7f) << 9) | (((date.getMonth() + 1) & 0xf) << 5) | (date.getDate() & 0x1f); + + return {time, day}; +} + +/** + * reverse of dosDateTime + */ +function dosToDate(day, time) { + const year = ((day >> 9) & 0x7f) + 1980; + const month = ((day >> 5) & 0xf) - 1; + const date = day & 0x1f; + const hours = (time >> 11) & 0x1f; + const minutes = (time >> 5) & 0x3f; + const seconds = (time & 0x1f) * 2; + + return new Date(year, month, date, hours, minutes, seconds); +} + +/** + * minimal zip (deflate) writer, so archiving does not require + * an external dependency. + */ +class Zip { + constructor() { + this.entries = []; + } + + /** + * add a file to the archive + * @param name path of the file inside the archive, e.g. "01/abc.json" + * @param data Buffer with the file's contents + * @param date last modified date of the entry + */ + addFile(name, data, date = new Date()) { + const compressed = zlib.deflateRawSync(data); + const useCompressed = compressed.length < data.length; + + this.entries.push({ + name, + data, + payload: useCompressed ? compressed : data, + method: useCompressed ? METHOD_DEFLATE : METHOD_STORE, + crc: zlib.crc32(data), + date + }); + + return this; + } + + /** + * build the zip file as a Buffer + * @returns {Buffer} + */ + toBuffer() { + const localParts = []; + const centralParts = []; + let offset = 0; + + for (const entry of this.entries) { + const nameBuf = Buffer.from(entry.name, 'utf8'); + const {time, day} = dosDateTime(entry.date); + + const localHeader = Buffer.alloc(30); + localHeader.writeUInt32LE(0x04034b50, 0); + localHeader.writeUInt16LE(20, 4); + localHeader.writeUInt16LE(0x0800, 6); + localHeader.writeUInt16LE(entry.method, 8); + localHeader.writeUInt16LE(time, 10); + localHeader.writeUInt16LE(day, 12); + localHeader.writeUInt32LE(entry.crc, 14); + localHeader.writeUInt32LE(entry.payload.length, 18); + localHeader.writeUInt32LE(entry.data.length, 22); + localHeader.writeUInt16LE(nameBuf.length, 26); + localHeader.writeUInt16LE(0, 28); + + localParts.push(localHeader, nameBuf, entry.payload); + + const centralHeader = Buffer.alloc(46); + centralHeader.writeUInt32LE(0x02014b50, 0); + centralHeader.writeUInt16LE(20, 4); + centralHeader.writeUInt16LE(20, 6); + centralHeader.writeUInt16LE(0x0800, 8); + centralHeader.writeUInt16LE(entry.method, 10); + centralHeader.writeUInt16LE(time, 12); + centralHeader.writeUInt16LE(day, 14); + centralHeader.writeUInt32LE(entry.crc, 16); + centralHeader.writeUInt32LE(entry.payload.length, 20); + centralHeader.writeUInt32LE(entry.data.length, 24); + centralHeader.writeUInt16LE(nameBuf.length, 28); + centralHeader.writeUInt16LE(0, 30); + centralHeader.writeUInt16LE(0, 32); + centralHeader.writeUInt16LE(0, 34); + centralHeader.writeUInt32LE(0, 38); + centralHeader.writeUInt32LE(offset, 42); + + centralParts.push(centralHeader, nameBuf); + + offset += localHeader.length + nameBuf.length + entry.payload.length; + } + + const centralSize = centralParts.reduce((n, b) => n + b.length, 0); + const centralOffset = offset; + + const end = Buffer.alloc(22); + end.writeUInt32LE(0x06054b50, 0); + end.writeUInt16LE(0, 4); + end.writeUInt16LE(0, 6); + end.writeUInt16LE(this.entries.length, 8); + end.writeUInt16LE(this.entries.length, 10); + end.writeUInt32LE(centralSize, 12); + end.writeUInt32LE(centralOffset, 16); + end.writeUInt16LE(0, 20); + + return Buffer.concat([...localParts, ...centralParts, end]); + } + + /** + * write the zip archive to disk atomically + * @param file + */ + write(file) { + const tmpFile = `${file}.tmp`; + + fs.writeFileSync(tmpFile, this.toBuffer()); + fs.renameSync(tmpFile, file); + } + + /** + * read an existing zip archive (as produced by this class) back into + * a Zip instance, so new files can be appended to it. Returns an + * empty Zip if the file does not exist. + * @param file + * @returns {Zip} + */ + static fromFile(file) { + const zip = new Zip(); + + if (!fs.existsSync(file)) return zip; + + const buffer = fs.readFileSync(file); + let offset = 0; + + while (offset < buffer.length && buffer.readUInt32LE(offset) === 0x04034b50) { + const method = buffer.readUInt16LE(offset + 8); + const time = buffer.readUInt16LE(offset + 10); + const day = buffer.readUInt16LE(offset + 12); + const crc = buffer.readUInt32LE(offset + 14); + const compressedSize = buffer.readUInt32LE(offset + 18); + const nameLength = buffer.readUInt16LE(offset + 26); + const extraLength = buffer.readUInt16LE(offset + 28); + + const nameStart = offset + 30; + const name = buffer.toString('utf8', nameStart, nameStart + nameLength); + const dataStart = nameStart + nameLength + extraLength; + const payload = buffer.subarray(dataStart, dataStart + compressedSize); + const data = method === METHOD_DEFLATE ? zlib.inflateRawSync(payload) : Buffer.from(payload); + + zip.entries.push({name, data, payload: Buffer.from(payload), method, crc, date: dosToDate(day, time)}); + + offset = dataStart + compressedSize; + } + + return zip; + } +} + +export default Zip; diff --git a/src/gtt-cancel.js b/src/gtt-cancel.js deleted file mode 100755 index cf0a8f7..0000000 --- a/src/gtt-cancel.js +++ /dev/null @@ -1,33 +0,0 @@ -import {Command} from 'commander'; -import colors from 'colors'; -import moment from 'moment'; -import Config from './include/file-config.js'; -import Cli from './include/cli.js'; -import Tasks from './include/tasks.js'; - -function cancel() { - const cancel = new Command('cancel', 'cancel and discard active monitoring time') - .option('--verbose', 'show verbose output') - .action((options, program) => { - -Cli.verbose = program.opts().verbose; - -let config = new Config(process.cwd()); -let tasks = new Tasks(config); - -tasks.cancel() - .then(frames => { - frames.forEach(frame => { - if(!frame.resource.new) - return console.log(`Cancel project ${frame.project.magenta} ${frame.resource.type.blue} ${('#' + frame.resource.id).blue}, started ${moment(frame.start).fromNow().green}`) - - console.log(`Cancel project ${frame.project.magenta} for new ${frame.resource.type} "${(frame.resource.id).blue}", started ${moment(frame.start).fromNow().green}`) - }) - }) - .catch(error => Cli.error(error)); - } -); -return cancel; -} - -export default cancel; diff --git a/src/gtt-delete.js b/src/gtt-delete.js deleted file mode 100755 index 8e82c93..0000000 --- a/src/gtt-delete.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Command } from 'commander'; -import Frame from './models/frame.js'; -import Config from './include/file-config.js'; -import Cli from './include/cli.js'; -import Fs from './include/filesystem.js'; - -function delCmd() { - const delCmd = new Command('delete', 'delete time record by the given id') - .arguments('[id]') - .action((id, opts, program) => { - - let config = new Config(process.cwd()); - - if (!id && -Infinity === (id = Fs.newest(config.frameDir).name)) - Cli.error('No record found.'); - - let file = Fs.join(config.frameDir, id.replace('.json', '') + '.json'); - if (!Fs.exists(file)) { - Cli.error(`Record ${id} not found.`); - } else { - let frame = Frame.fromFile(config, file).stopMe(); - Fs.remove(file); - console.log(`Deleting record ${frame.id.magenta}`); - } - } - ); - return delCmd; -} - -export default delCmd; diff --git a/src/gtt-edit.js b/src/gtt-edit.js deleted file mode 100755 index a14ea63..0000000 --- a/src/gtt-edit.js +++ /dev/null @@ -1,82 +0,0 @@ -import {Command} from 'commander'; -import Config from './include/file-config.js'; -import Cli from './include/cli.js'; -import Fs from './include/filesystem.js'; -import _ from 'underscore'; -import Time from './models/time.js'; -import Frame from './models/frame.js'; -import select from '@inquirer/select'; - - - -function edit() { - const edit = new Command('edit', 'edit time record by the given id') - .arguments('[id]') - .action((id, opts ,program) => { - -let config = new Config(process.cwd()); -let timeFormat = config.set('timeFormat', program.opts().time_format).get('timeFormat', 'log'); -const listSize = 30; - -function column(str, n){ - if(str.length > n) { - str = str.substr(0, n-1) + "…" - } - return str.padEnd(n); -} - -function toHumanReadable(input) { - return Time.toHumanReadable(Math.ceil(input), config.get('hoursPerDay'), timeFormat); -} - -if (!id) { - let lastFrames = Fs.all(config.frameDir).slice(-listSize); // last listSize frames (one page of inquirer) - lastFrames = lastFrames.map((file) => - Frame.fromFile(config, Fs.join(config.frameDir, file.name)) - ); - - let lastFramesDetails = lastFrames - .sort((a, b) => (a.start.isBefore(b.start) ? -1 : 1)) - .map((frame) => { - let issue = `${ - (frame.resource.type + " #" + frame.resource.id).padEnd(20).blue - }${column(frame.title != null ? frame.title : "", 50)}`; - return { - name: - ` ${frame.id} ${frame.start.clone().format("MMMM Do YYYY HH:mm").green} ${ - frame.stop ? "to " + frame.stop.clone().format("HH:mm").green : "(running)"}\t` + - `${column(frame.project, 50).magenta}${issue}${ - frame.note != null ? frame.note : "" - }`, - value: frame.id, - }; - }); - - if (lastFramesDetails.length == 0) { - Cli.error("No records found."); - } else { - select({ - message: "Frame?", - default: lastFramesDetails[lastFramesDetails.length - 1].value, - choices: lastFramesDetails, - pageSize: listSize, - }).then((answer) => { - if (!Fs.exists(Fs.join(config.frameDir, answer + ".json"))) { - Cli.error("record not found."); - } else { - Fs.open(Fs.join(config.frameDir, answer + ".json")); - } - }); - } -} else { - if (!Fs.exists(Fs.join(config.frameDir, id + ".json"))) - Cli.error("No record found."); - Fs.open(Fs.join(config.frameDir, id.replace(".json", "") + ".json")); -} - -} -); -return edit; -} - -export default edit; diff --git a/src/gtt-list.js b/src/gtt-list.js deleted file mode 100755 index 781c3c2..0000000 --- a/src/gtt-list.js +++ /dev/null @@ -1,44 +0,0 @@ -import {Command} from 'commander'; -import colors from 'colors'; -import moment from 'moment'; -import Table from 'cli-table'; - - -import Config from './include/file-config.js'; -import cli from './include/cli.js'; -import Tasks from './include/tasks.js'; - -function list() { - const list = new Command('list', 'list all open issues') - .arguments('[project]') - .option('--verbose', 'show verbose output') - .option('-c, --closed', 'show closed issues (instead of opened only)') - .option('--my', 'show only issues assigned to me') - .action((aproject, options, program) => { - -let config = new Config(process.cwd()), - tasks = new Tasks(config), - type = program.opts().type ? program.opts().type : 'issue', - project = program.args[0]; - -tasks.list(project, program.opts().closed ? 'closed' : 'opened', program.opts().my) - .then(issues => { - let table = new Table({ - style : {compact : true, 'padding-left' : 1} - }); - if (issues.length == 0) { - console.log("No issues found."); - } - issues.forEach(issue => { - table.push([issue.iid.toString().magenta, issue.title.green + "\n" + issue.data.web_url.gray, issue.state]) - }) - console.log(table.toString()); - }) - .catch(error => cli.error(error)); - -} -); -return list; -} - -export default list; diff --git a/src/gtt-report.js b/src/gtt-report.js deleted file mode 100755 index 81f39c6..0000000 --- a/src/gtt-report.js +++ /dev/null @@ -1,393 +0,0 @@ -import _ from 'underscore'; -import fs from 'fs'; -import {Command} from 'commander'; -import moment from 'moment'; -import Cli from './include/cli.js'; -import Config from './include/file-config.js'; -import Report from './models/report.js'; -import Owner from './models/owner.js'; -import ReportCollection from './models/reportCollection.js'; -import table from './output/table.js'; -import csv from './output/csv.js'; -import markdown from './output/markdown.js'; -import invoice from './output/invoice.js'; -import xlsx from './output/xlsx.js'; - -const Output = { - table, - csv, - markdown, - invoice, - xlsx -}; - -// this collects options -function collect(val, arr) { - if (!arr) arr = []; - arr.push(val); - - return _.uniq(arr); -} - - -function report() { - const report = new Command('report', 'generate a report for the given project and issues') - .arguments('[project] [ids...]') - .option('-e --type ', 'specify the query type: project, user, group') - .option('--subgroups', 'include sub groups') - .option('--url ', 'URL to GitLabs API') - .option('--token ', 'API access token') - .option('-f --from ', 'query times that are equal or greater than the given date') - .option('-t --to ', 'query times that are equal or smaller than the given date') - .option('--today', 'ignores --from and --to and queries entries for today') - .option('--this_week', 'ignores --from and --to and queries entries for this week') - .option('--this_month', 'ignores --from and --to and queries entries for this month') - .option('--last_month', 'ignores --from and --to and queries entries for last month') - .option('-c --closed', 'include closed issues') - .option('-m --milestone ', 'include issues from the given milestone') - .option('--hours_per_day ', 'hours per day for human readable time formats') - .option('-u --user ', 'only query times from the given user') - .option('-q --query ', 'query the given data types: issues, merge_requests', collect, null) - .option('-r --report ', 'include in the report: stats, issues, merge_requests, records', collect, null) - .option('-o --output ', 'use the given output') - .option('-l --file ', 'save report to the given file') - .option('--include_by_labels ', 'only include issues that have the given labels', collect, null) - .option('--exclude_by_labels ', 'exclude issues that have the given labels', collect, null) - .option('--include_labels ', 'only include the given labels in the report', collect, null) - .option('--exclude_labels ', 'exclude the given labels in the report', collect, null) - .option('--date_format ', 'use the given date format in the report', collect, null) - .option('--time_format