From b719e0a845e17f6f7afc7540a24a872714939ae9 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 23:38:55 +0700 Subject: [PATCH 01/12] first commit --- .eslintrc.json | 63 ++++++++++++++ .github/workflows/ci.yml | 101 ++++++++++++++++++++++ .gitignore | 5 ++ .prettierrc.json | 7 ++ LICENSE | 21 +++++ README.md | 56 ++++++++++++ lerna.json | 24 +++++ package.json | 39 +++++++++ packages/dockerjs/LICENSE | 21 +++++ packages/dockerjs/Makefile | 7 ++ packages/dockerjs/README.md | 43 +++++++++ packages/dockerjs/__tests__/basic.test.ts | 6 ++ packages/dockerjs/dockerjs.control | 7 ++ packages/dockerjs/jest.config.js | 20 +++++ packages/dockerjs/package.json | 32 +++++++ packages/dockerjs/pgpm.plan | 3 + pgpm.json | 6 ++ pnpm-workspace.yaml | 2 + tsconfig.json | 16 ++++ 19 files changed, 479 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .prettierrc.json create mode 100644 LICENSE create mode 100644 README.md create mode 100644 lerna.json create mode 100644 package.json create mode 100644 packages/dockerjs/LICENSE create mode 100644 packages/dockerjs/Makefile create mode 100644 packages/dockerjs/README.md create mode 100644 packages/dockerjs/__tests__/basic.test.ts create mode 100644 packages/dockerjs/dockerjs.control create mode 100644 packages/dockerjs/jest.config.js create mode 100644 packages/dockerjs/package.json create mode 100644 packages/dockerjs/pgpm.plan create mode 100644 pgpm.json create mode 100644 pnpm-workspace.yaml create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..9a3628b --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,63 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true, + "jest": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "overrides": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint", + "simple-import-sort", + "unused-imports" + ], + "rules": { + "indent": [ + "error", + 2 + ], + "quotes": [ + "error", + "single", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ], + "quote-props": [ + "error", + "as-needed" + ], + "semi": [ + "error", + "always" + ], + "simple-import-sort/imports": 1, + "simple-import-sort/exports": 1, + "unused-imports/no-unused-imports": 1, + "@typescript-eslint/no-unused-vars": [ + 1, + { + "argsIgnorePattern": "React|res|next|^_" + } + ], + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-var-requires": 0, + "no-console": 0, + "@typescript-eslint/ban-ts-comment": 0, + "prefer-const": 0, + "no-case-declarations": 0, + "no-implicit-globals": 0, + "@typescript-eslint/no-unsafe-declaration-merging": 0 + } +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1692719 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,101 @@ +name: pgpm tests +on: + pull_request: + branches: + - main + push: + branches: + - main + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + fail-fast: false + matrix: + package: + - your-module-1 + - your-module-2 + + env: + PGHOST: localhost + PGPORT: 5432 + PGUSER: postgres + PGPASSWORD: password + PGPM_VERSION: 2.7.9 + + services: + pg_db: + image: pyramation/pgvector:13.3-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + minio_cdn: + image: minio/minio:edge-cicd + env: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + ports: + - 9000:9000 + - 9001:9001 + options: >- + --health-cmd "curl -f http://localhost:9000/minio/health/live || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Configure Git (for tests) + run: | + git config --global user.name "CI Test User" + git config --global user.email "ci@example.com" + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'pnpm' + + - name: Install + run: pnpm install + + - name: Cache pgpm CLI + id: cache-pgpm + uses: actions/cache@v4 + with: + path: ~/.npm + key: pgpm-${{ env.PGPM_VERSION }} + + - name: Install pgpm CLI globally + run: npm install -g pgpm@${{ env.PGPM_VERSION }} + + - name: Build + run: pnpm -r build + + - name: Seed pg and app_user + run: | + pgpm admin-users bootstrap --yes + # optional, but added to avoid concurrent attempts to add user + pgpm admin-users add --test --yes + + - name: Test ${{ matrix.package }} + run: cd ./packages/${{ matrix.package }} && pnpm test + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9152479 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +**/node_modules/ +**/.DS_Store +**/dist +**/pnpm-debug.log +lerna-debug.log \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..911778d --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "useTabs": false, + "singleQuote": false +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..153d3dd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2026 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f940fa5 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# dockerjs + +

+ +

+ +

+ + + +

+ + +## Getting Started + +This workspace was generated with `pgpm init workspace`. For a complete guide on developing with pgpm workspaces, see [Workspaces: Organize Postgres](https://constructive.io/learn/modular-postgres/workspaces-organize-postgres). + +### Quick Start + +```sh +# Install dependencies +pnpm install + +# Start PostgreSQL (requires Docker) +pgpm docker start + +# Load environment variables +eval "$(pgpm env)" + +# Create a module +pgpm init + +# Navigate to your module and run tests +cd packages/your-module +pnpm test:watch +``` + +### Prerequisites + +- Node.js 20+ +- pnpm +- Docker +- PostgreSQL client tools (`psql`) +- pgpm (`npm install -g pgpm`) + +See [Prerequisites](https://constructive.io/learn/quickstart/prerequisites) for detailed setup instructions. + +## Credits + +**🛠 Built by the [Constructive](https://constructive.io) team — creators of modular Postgres tooling for secure, composable backends. If you like our work, contribute on [GitHub](https://github.com/constructive-io).** + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/lerna.json b/lerna.json new file mode 100644 index 0000000..54019f2 --- /dev/null +++ b/lerna.json @@ -0,0 +1,24 @@ +{ + "$schema": "node_modules/lerna/schemas/lerna-schema.json", + "version": "independent", + "npmClient": "pnpm", + "npmClientArgs": [ + "--frozen-lockfile" + ], + "packages": [ + "packages/*" + ], + "registry": "https://registry.npmjs.org", + "command": { + "create": { + "homepage": "https://github.com/pyramation/dockerjs", + "license": "MIT", + "access": "restricted" + }, + "publish": { + "allowBranch": "main", + "message": "chore(release): publish", + "conventionalCommits": true + } + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..065600f --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "dockerjs", + "version": "0.0.1", + "author": "Dan Lynch ", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/pyramation/dockerjs" + }, + "license": "MIT", + "publishConfig": { + "access": "restricted" + }, + "scripts": { + "build": "pnpm -r run build", + "clean": "pnpm -r run clean", + "test": "pnpm -r run test", + "lint": "pnpm -r run lint", + "deps": "pnpm up -r -i -L" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^25.0.3", + "@typescript-eslint/eslint-plugin": "^8.50.1", + "@typescript-eslint/parser": "^8.50.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-simple-import-sort": "^12.1.1", + "eslint-plugin-unused-imports": "^4.3.0", + "eslint": "^9.39.2", + "jest": "^30.2.0", + "lerna": "^9.0.3", + "makage": "0.1.9", + "pgsql-test": "^2.18.15", + "prettier": "^3.7.4", + "ts-jest": "^29.4.6", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" + } +} \ No newline at end of file diff --git a/packages/dockerjs/LICENSE b/packages/dockerjs/LICENSE new file mode 100644 index 0000000..153d3dd --- /dev/null +++ b/packages/dockerjs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2026 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/dockerjs/Makefile b/packages/dockerjs/Makefile new file mode 100644 index 0000000..9d7c062 --- /dev/null +++ b/packages/dockerjs/Makefile @@ -0,0 +1,7 @@ +EXTENSION = dockerjs +DATA = sql/dockerjs--0.0.1.sql + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) + \ No newline at end of file diff --git a/packages/dockerjs/README.md b/packages/dockerjs/README.md new file mode 100644 index 0000000..e464521 --- /dev/null +++ b/packages/dockerjs/README.md @@ -0,0 +1,43 @@ +# dockerjs + +

+ +

+ +

+ + + + +

+ +## Developing + +This is a pnpm module within a pnpm workspace. + +```sh +# Install dependencies +pnpm install + +# Run tests +pnpm test + +# Run tests in watch mode +pnpm test:watch + +# Build the module +pnpm build + +# Lint the code +pnpm lint +``` + +## Credits + +**Built by the [Constructive](https://constructive.io) team. If you like our work, contribute on [GitHub](https://github.com/constructive-io).** + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/packages/dockerjs/__tests__/basic.test.ts b/packages/dockerjs/__tests__/basic.test.ts new file mode 100644 index 0000000..5dbacab --- /dev/null +++ b/packages/dockerjs/__tests__/basic.test.ts @@ -0,0 +1,6 @@ +describe('first test', () => { + it('should pass', () => { + expect(1 + 1).toBe(2); + }); +}); + diff --git a/packages/dockerjs/dockerjs.control b/packages/dockerjs/dockerjs.control new file mode 100644 index 0000000..4ab109f --- /dev/null +++ b/packages/dockerjs/dockerjs.control @@ -0,0 +1,7 @@ +# dockerjs extension +comment = 'dockerjs extension' +default_version = '0.0.1' +module_pathname = '$libdir/dockerjs' +requires = 'uuid-ossp,plpgsql' +relocatable = false +superuser = false diff --git a/packages/dockerjs/jest.config.js b/packages/dockerjs/jest.config.js new file mode 100644 index 0000000..10b083a --- /dev/null +++ b/packages/dockerjs/jest.config.js @@ -0,0 +1,20 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + + // Match both __tests__ and colocated test files + testMatch: ['**/?(*.)+(test|spec).{ts,tsx,js,jsx}'], + + // Ignore build artifacts and type declarations + testPathIgnorePatterns: ['/dist/', '\\.d\\.ts$'], + modulePathIgnorePatterns: ['/dist/'], + + // Only watch js, ts, and sql files + watchPathIgnorePatterns: [ + '/dist/', + '/node_modules/' + ], + + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', 'sql'], +}; \ No newline at end of file diff --git a/packages/dockerjs/package.json b/packages/dockerjs/package.json new file mode 100644 index 0000000..abd93b2 --- /dev/null +++ b/packages/dockerjs/package.json @@ -0,0 +1,32 @@ +{ + "name": "dockerjs", + "version": "0.0.1", + "author": "Dan Lynch ", + "description": "dockerjs", + "homepage": "https://github.com/pyramation/dockerjs", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/pyramation/dockerjs" + }, + "bugs": { + "url": "https://github.com/pyramation/dockerjs/issues" + }, + "scripts": { + "clean": "makage clean", + "prepack": "npm run build", + "build": "makage build", + "build:dev": "makage build --dev", + "lint": "eslint . --fix", + "test": "jest --passWithNoTests", + "test:watch": "jest --watch" + }, + "keywords": [], + "devDependencies": { + "makage": "0.1.9" + } +} diff --git a/packages/dockerjs/pgpm.plan b/packages/dockerjs/pgpm.plan new file mode 100644 index 0000000..542f229 --- /dev/null +++ b/packages/dockerjs/pgpm.plan @@ -0,0 +1,3 @@ +%syntax-version=1.0.0 +%project=dockerjs +%uri=dockerjs \ No newline at end of file diff --git a/pgpm.json b/pgpm.json new file mode 100644 index 0000000..e20d138 --- /dev/null +++ b/pgpm.json @@ -0,0 +1,6 @@ +{ + "packages": [ + "packages/*", + "extensions/*" + ] +} \ No newline at end of file diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..18ec407 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'packages/*' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4c8a664 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "strictNullChecks": false, + "skipLibCheck": true, + "sourceMap": false, + "declaration": true, + "resolveJsonModule": true, + "moduleResolution": "node" + }, + "exclude": ["dist", "node_modules"] +} From df9a29e946b1511e94a2c09cccc8a1609b8343a5 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 17:26:31 +0000 Subject: [PATCH 02/12] feat: add docker-parser and bash-parser packages with heterogeneous parsing - Create docker-parser package with full Dockerfile parsing/deparsing - Create bash-parser package with bash/shell command parsing/deparsing - Implement heterogeneous parsing: RUN instructions include nested Bash AST - Add comprehensive test suites with round-trip testing - Add fixtures for both Dockerfile and bash scripts - Remove pgpm configuration, convert to pnpm-only workspace - Add ESLint v9 flat config for linting --- README.md | 36 +- __fixtures__/bash/basic/assignment.sh | 1 + __fixtures__/bash/basic/pipeline.sh | 1 + __fixtures__/bash/basic/redirect.sh | 1 + __fixtures__/bash/basic/simple.sh | 1 + __fixtures__/bash/basic/with-args.sh | 1 + __fixtures__/bash/control-flow/for-loop.sh | 1 + __fixtures__/bash/control-flow/if-then.sh | 1 + __fixtures__/bash/control-flow/while-loop.sh | 1 + __fixtures__/docker/basic/simple.dockerfile | 7 + __fixtures__/docker/basic/with-env.dockerfile | 11 + .../docker/basic/with-healthcheck.dockerfile | 5 + .../docker/multi-stage/builder.dockerfile | 11 + .../multi-stage/with-platform.dockerfile | 13 + eslint.config.js | 61 + package.json | 31 +- packages/bash-parser/README.md | 81 + .../bash-parser/__tests__/deparser.test.ts | 110 + packages/bash-parser/__tests__/parser.test.ts | 202 + .../bash-parser/__tests__/roundtrip.test.ts | 123 + packages/bash-parser/jest.config.js | 9 + packages/bash-parser/package.json | 42 + packages/bash-parser/src/clean.ts | 79 + packages/bash-parser/src/deparser.ts | 371 + packages/bash-parser/src/index.ts | 14 + packages/bash-parser/src/lexer.ts | 482 ++ packages/bash-parser/src/parser.ts | 800 ++ packages/bash-parser/src/types.ts | 261 + packages/bash-parser/test-utils/index.ts | 112 + packages/bash-parser/tsconfig.esm.json | 7 + packages/bash-parser/tsconfig.json | 9 + packages/docker-parser/README.md | 81 + .../docker-parser/__tests__/deparser.test.ts | 151 + .../docker-parser/__tests__/parser.test.ts | 276 + .../docker-parser/__tests__/roundtrip.test.ts | 180 + packages/docker-parser/jest.config.js | 9 + packages/docker-parser/package.json | 45 + .../scripts/generate-fixtures.ts | 45 + packages/docker-parser/src/clean.ts | 114 + packages/docker-parser/src/deparser.ts | 505 ++ packages/docker-parser/src/index.ts | 14 + packages/docker-parser/src/lexer.ts | 445 + packages/docker-parser/src/parser.ts | 1056 +++ packages/docker-parser/src/types.ts | 338 + packages/docker-parser/test-utils/index.ts | 112 + packages/docker-parser/tsconfig.esm.json | 7 + packages/docker-parser/tsconfig.json | 9 + packages/dockerjs/LICENSE | 21 - packages/dockerjs/Makefile | 7 - packages/dockerjs/README.md | 43 - packages/dockerjs/__tests__/basic.test.ts | 6 - packages/dockerjs/dockerjs.control | 7 - packages/dockerjs/jest.config.js | 20 - packages/dockerjs/package.json | 32 - packages/dockerjs/pgpm.plan | 3 - pgpm.json | 6 - pnpm-lock.yaml | 7321 +++++++++++++++++ 57 files changed, 13557 insertions(+), 181 deletions(-) create mode 100644 __fixtures__/bash/basic/assignment.sh create mode 100644 __fixtures__/bash/basic/pipeline.sh create mode 100644 __fixtures__/bash/basic/redirect.sh create mode 100644 __fixtures__/bash/basic/simple.sh create mode 100644 __fixtures__/bash/basic/with-args.sh create mode 100644 __fixtures__/bash/control-flow/for-loop.sh create mode 100644 __fixtures__/bash/control-flow/if-then.sh create mode 100644 __fixtures__/bash/control-flow/while-loop.sh create mode 100644 __fixtures__/docker/basic/simple.dockerfile create mode 100644 __fixtures__/docker/basic/with-env.dockerfile create mode 100644 __fixtures__/docker/basic/with-healthcheck.dockerfile create mode 100644 __fixtures__/docker/multi-stage/builder.dockerfile create mode 100644 __fixtures__/docker/multi-stage/with-platform.dockerfile create mode 100644 eslint.config.js create mode 100644 packages/bash-parser/README.md create mode 100644 packages/bash-parser/__tests__/deparser.test.ts create mode 100644 packages/bash-parser/__tests__/parser.test.ts create mode 100644 packages/bash-parser/__tests__/roundtrip.test.ts create mode 100644 packages/bash-parser/jest.config.js create mode 100644 packages/bash-parser/package.json create mode 100644 packages/bash-parser/src/clean.ts create mode 100644 packages/bash-parser/src/deparser.ts create mode 100644 packages/bash-parser/src/index.ts create mode 100644 packages/bash-parser/src/lexer.ts create mode 100644 packages/bash-parser/src/parser.ts create mode 100644 packages/bash-parser/src/types.ts create mode 100644 packages/bash-parser/test-utils/index.ts create mode 100644 packages/bash-parser/tsconfig.esm.json create mode 100644 packages/bash-parser/tsconfig.json create mode 100644 packages/docker-parser/README.md create mode 100644 packages/docker-parser/__tests__/deparser.test.ts create mode 100644 packages/docker-parser/__tests__/parser.test.ts create mode 100644 packages/docker-parser/__tests__/roundtrip.test.ts create mode 100644 packages/docker-parser/jest.config.js create mode 100644 packages/docker-parser/package.json create mode 100644 packages/docker-parser/scripts/generate-fixtures.ts create mode 100644 packages/docker-parser/src/clean.ts create mode 100644 packages/docker-parser/src/deparser.ts create mode 100644 packages/docker-parser/src/index.ts create mode 100644 packages/docker-parser/src/lexer.ts create mode 100644 packages/docker-parser/src/parser.ts create mode 100644 packages/docker-parser/src/types.ts create mode 100644 packages/docker-parser/test-utils/index.ts create mode 100644 packages/docker-parser/tsconfig.esm.json create mode 100644 packages/docker-parser/tsconfig.json delete mode 100644 packages/dockerjs/LICENSE delete mode 100644 packages/dockerjs/Makefile delete mode 100644 packages/dockerjs/README.md delete mode 100644 packages/dockerjs/__tests__/basic.test.ts delete mode 100644 packages/dockerjs/dockerjs.control delete mode 100644 packages/dockerjs/jest.config.js delete mode 100644 packages/dockerjs/package.json delete mode 100644 packages/dockerjs/pgpm.plan delete mode 100644 pgpm.json create mode 100644 pnpm-lock.yaml diff --git a/README.md b/README.md index f940fa5..75c4cad 100644 --- a/README.md +++ b/README.md @@ -5,49 +5,41 @@

- - + +

+Dockerfile and Bash parsers for JavaScript/TypeScript. -## Getting Started +## Packages -This workspace was generated with `pgpm init workspace`. For a complete guide on developing with pgpm workspaces, see [Workspaces: Organize Postgres](https://constructive.io/learn/modular-postgres/workspaces-organize-postgres). +| Package | Description | +|---------|-------------| +| [docker-parser](./packages/docker-parser) | Parse Dockerfiles into AST and deparse back to source | +| [bash-parser](./packages/bash-parser) | Parse bash/shell commands into AST and deparse back to source | -### Quick Start +## Getting Started ```sh # Install dependencies pnpm install -# Start PostgreSQL (requires Docker) -pgpm docker start - -# Load environment variables -eval "$(pgpm env)" +# Build all packages +pnpm build -# Create a module -pgpm init - -# Navigate to your module and run tests -cd packages/your-module -pnpm test:watch +# Run tests +pnpm test ``` ### Prerequisites - Node.js 20+ - pnpm -- Docker -- PostgreSQL client tools (`psql`) -- pgpm (`npm install -g pgpm`) - -See [Prerequisites](https://constructive.io/learn/quickstart/prerequisites) for detailed setup instructions. ## Credits -**🛠 Built by the [Constructive](https://constructive.io) team — creators of modular Postgres tooling for secure, composable backends. If you like our work, contribute on [GitHub](https://github.com/constructive-io).** +Built by the [Constructive](https://constructive.io) team. ## Disclaimer diff --git a/__fixtures__/bash/basic/assignment.sh b/__fixtures__/bash/basic/assignment.sh new file mode 100644 index 0000000..64c9dc4 --- /dev/null +++ b/__fixtures__/bash/basic/assignment.sh @@ -0,0 +1 @@ +VAR=value echo $VAR diff --git a/__fixtures__/bash/basic/pipeline.sh b/__fixtures__/bash/basic/pipeline.sh new file mode 100644 index 0000000..cc6a058 --- /dev/null +++ b/__fixtures__/bash/basic/pipeline.sh @@ -0,0 +1 @@ +cat file.txt | grep pattern | sort diff --git a/__fixtures__/bash/basic/redirect.sh b/__fixtures__/bash/basic/redirect.sh new file mode 100644 index 0000000..23966eb --- /dev/null +++ b/__fixtures__/bash/basic/redirect.sh @@ -0,0 +1 @@ +echo hello > output.txt diff --git a/__fixtures__/bash/basic/simple.sh b/__fixtures__/bash/basic/simple.sh new file mode 100644 index 0000000..7c0dffd --- /dev/null +++ b/__fixtures__/bash/basic/simple.sh @@ -0,0 +1 @@ +echo hello world diff --git a/__fixtures__/bash/basic/with-args.sh b/__fixtures__/bash/basic/with-args.sh new file mode 100644 index 0000000..07cf877 --- /dev/null +++ b/__fixtures__/bash/basic/with-args.sh @@ -0,0 +1 @@ +ls -la /tmp diff --git a/__fixtures__/bash/control-flow/for-loop.sh b/__fixtures__/bash/control-flow/for-loop.sh new file mode 100644 index 0000000..101798f --- /dev/null +++ b/__fixtures__/bash/control-flow/for-loop.sh @@ -0,0 +1 @@ +for i in 1 2 3; do echo $i; done diff --git a/__fixtures__/bash/control-flow/if-then.sh b/__fixtures__/bash/control-flow/if-then.sh new file mode 100644 index 0000000..e32811d --- /dev/null +++ b/__fixtures__/bash/control-flow/if-then.sh @@ -0,0 +1 @@ +if test -f file.txt; then echo exists; fi diff --git a/__fixtures__/bash/control-flow/while-loop.sh b/__fixtures__/bash/control-flow/while-loop.sh new file mode 100644 index 0000000..3634783 --- /dev/null +++ b/__fixtures__/bash/control-flow/while-loop.sh @@ -0,0 +1 @@ +while true; do echo loop; done diff --git a/__fixtures__/docker/basic/simple.dockerfile b/__fixtures__/docker/basic/simple.dockerfile new file mode 100644 index 0000000..3d8812f --- /dev/null +++ b/__fixtures__/docker/basic/simple.dockerfile @@ -0,0 +1,7 @@ +FROM node:18-alpine +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/__fixtures__/docker/basic/with-env.dockerfile b/__fixtures__/docker/basic/with-env.dockerfile new file mode 100644 index 0000000..502c31c --- /dev/null +++ b/__fixtures__/docker/basic/with-env.dockerfile @@ -0,0 +1,11 @@ +FROM python:3.11-slim +ENV PYTHONUNBUFFERED=1 +ENV APP_HOME=/app +WORKDIR ${APP_HOME} +ARG VERSION=1.0.0 +LABEL version=${VERSION} +COPY requirements.txt . +RUN pip install -r requirements.txt +COPY . . +USER nobody +ENTRYPOINT ["python", "app.py"] diff --git a/__fixtures__/docker/basic/with-healthcheck.dockerfile b/__fixtures__/docker/basic/with-healthcheck.dockerfile new file mode 100644 index 0000000..6289f81 --- /dev/null +++ b/__fixtures__/docker/basic/with-healthcheck.dockerfile @@ -0,0 +1,5 @@ +FROM nginx:alpine +COPY nginx.conf /etc/nginx/nginx.conf +EXPOSE 80 +HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD ["wget", "-q", "--spider", "http://localhost/health"] +STOPSIGNAL SIGTERM diff --git a/__fixtures__/docker/multi-stage/builder.dockerfile b/__fixtures__/docker/multi-stage/builder.dockerfile new file mode 100644 index 0000000..f6d52ef --- /dev/null +++ b/__fixtures__/docker/multi-stage/builder.dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.21 AS builder +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o /app/server + +FROM alpine:3.18 AS runtime +COPY --from=builder /app/server /usr/local/bin/server +EXPOSE 8080 +ENTRYPOINT ["/usr/local/bin/server"] diff --git a/__fixtures__/docker/multi-stage/with-platform.dockerfile b/__fixtures__/docker/multi-stage/with-platform.dockerfile new file mode 100644 index 0000000..d952971 --- /dev/null +++ b/__fixtures__/docker/multi-stage/with-platform.dockerfile @@ -0,0 +1,13 @@ +FROM --platform=linux/amd64 node:18 AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM --platform=linux/amd64 node:18-alpine +WORKDIR /app +COPY --from=build /app/dist ./dist +COPY --from=build /app/node_modules ./node_modules +USER node +CMD ["node", "dist/index.js"] diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..03d2542 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,61 @@ +const typescriptEslint = require('@typescript-eslint/eslint-plugin'); +const typescriptParser = require('@typescript-eslint/parser'); +const simpleImportSort = require('eslint-plugin-simple-import-sort'); +const unusedImports = require('eslint-plugin-unused-imports'); + +module.exports = [ + { + ignores: ['**/dist/**', '**/node_modules/**', '**/*.js', '**/*.d.ts'] + }, + { + files: ['**/*.ts'], + languageOptions: { + parser: typescriptParser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module' + }, + globals: { + console: 'readonly', + process: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + module: 'readonly', + require: 'readonly', + exports: 'readonly', + describe: 'readonly', + it: 'readonly', + expect: 'readonly', + beforeEach: 'readonly', + afterEach: 'readonly', + beforeAll: 'readonly', + afterAll: 'readonly', + jest: 'readonly' + } + }, + plugins: { + '@typescript-eslint': typescriptEslint, + 'simple-import-sort': simpleImportSort, + 'unused-imports': unusedImports + }, + rules: { + indent: ['error', 2], + quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }], + 'quote-props': ['error', 'as-needed'], + semi: ['error', 'always'], + 'simple-import-sort/imports': 'warn', + 'simple-import-sort/exports': 'warn', + 'unused-imports/no-unused-imports': 'warn', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: 'React|res|next|^_' }], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'no-console': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + 'prefer-const': 'off', + 'no-case-declarations': 'off', + 'no-implicit-globals': 'off', + '@typescript-eslint/no-unsafe-declaration-merging': 'off' + } + } +]; diff --git a/package.json b/package.json index 065600f..0e63b80 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,19 @@ { "name": "dockerjs", "version": "0.0.1", - "author": "Dan Lynch ", + "author": "Constructive ", "private": true, "repository": { "type": "git", - "url": "https://github.com/pyramation/dockerjs" + "url": "https://github.com/constructive-io/dockerjs" }, "license": "MIT", "publishConfig": { "access": "restricted" }, + "workspaces": [ + "packages/*" + ], "scripts": { "build": "pnpm -r run build", "clean": "pnpm -r run clean", @@ -20,20 +23,20 @@ }, "devDependencies": { "@types/jest": "^30.0.0", - "@types/node": "^25.0.3", - "@typescript-eslint/eslint-plugin": "^8.50.1", - "@typescript-eslint/parser": "^8.50.1", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^8.47.0", + "@typescript-eslint/parser": "^8.47.0", + "eslint": "^9.39.1", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^4.3.0", - "eslint": "^9.39.2", + "eslint-plugin-simple-import-sort": "^12.1.0", + "eslint-plugin-unused-imports": "^4.0.0", "jest": "^30.2.0", - "lerna": "^9.0.3", - "makage": "0.1.9", - "pgsql-test": "^2.18.15", - "prettier": "^3.7.4", + "jest-diff": "30.2.0", + "lerna": "^8.2.4", + "makage": "^0.1.8", + "prettier": "^3.0.2", "ts-jest": "^29.4.6", "ts-node": "^10.9.2", - "typescript": "^5.9.3" + "typescript": "^5.1.6" } -} \ No newline at end of file +} diff --git a/packages/bash-parser/README.md b/packages/bash-parser/README.md new file mode 100644 index 0000000..ddf7d62 --- /dev/null +++ b/packages/bash-parser/README.md @@ -0,0 +1,81 @@ +# bash-parser + +Bash/shell command parser and deparser for JavaScript/TypeScript. + +## Installation + +```bash +npm install bash-parser +``` + +## Usage + +### Parsing + +```typescript +import { parse } from 'bash-parser'; + +const source = 'echo hello | grep h && ls -la'; +const ast = parse(source); +console.log(JSON.stringify(ast, null, 2)); +``` + +### Deparsing + +```typescript +import { parse, deparse } from 'bash-parser'; + +const source = 'echo hello'; +const ast = parse(source); +const output = deparse(ast); +console.log(output); // echo hello +``` + +### AST Comparison + +```typescript +import { parse, cleanTree } from 'bash-parser'; + +const ast1 = parse('echo hello'); +const ast2 = parse('echo hello'); + +const clean1 = cleanTree(ast1); +const clean2 = cleanTree(ast2); + +// Compare ASTs without position information +console.log(JSON.stringify(clean1) === JSON.stringify(clean2)); // true +``` + +## Supported Constructs + +### Commands +- Simple commands with arguments +- Pipelines (`cmd1 | cmd2`) +- Logical operators (`&&`, `||`) +- Subshells (`(cmd)`) +- Brace groups (`{ cmd; }`) + +### Control Flow +- if/then/else/elif/fi +- while/do/done +- until/do/done +- for/in/do/done +- case/esac + +### Redirections +- Input (`<`) +- Output (`>`, `>>`) +- Here strings (`<<<`) +- File descriptor redirects (`2>&1`) + +### Other +- Variable assignments (`VAR=value`) +- Function definitions +- Quoted strings (single and double) +- Variable expansion (`$VAR`, `${VAR}`) +- Command substitution (`$(cmd)`, `` `cmd` ``) +- Arithmetic expansion (`$((expr))`) + +## License + +MIT diff --git a/packages/bash-parser/__tests__/deparser.test.ts b/packages/bash-parser/__tests__/deparser.test.ts new file mode 100644 index 0000000..cd9ef32 --- /dev/null +++ b/packages/bash-parser/__tests__/deparser.test.ts @@ -0,0 +1,110 @@ +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; + +describe('bash-deparser', () => { + describe('deparse', () => { + it('should deparse simple command', () => { + const ast = parse('echo hello'); + const result = deparse(ast); + expect(result).toBe('echo hello'); + }); + + it('should deparse command with multiple arguments', () => { + const ast = parse('ls -la /tmp'); + const result = deparse(ast); + expect(result).toBe('ls -la /tmp'); + }); + + it('should deparse pipeline', () => { + const ast = parse('cat file | grep pattern'); + const result = deparse(ast); + expect(result).toBe('cat file | grep pattern'); + }); + + it('should deparse logical AND', () => { + const ast = parse('cmd1 && cmd2'); + const result = deparse(ast); + expect(result).toBe('cmd1 && cmd2'); + }); + + it('should deparse logical OR', () => { + const ast = parse('cmd1 || cmd2'); + const result = deparse(ast); + expect(result).toBe('cmd1 || cmd2'); + }); + + it('should deparse redirect output', () => { + const ast = parse('echo hello > file.txt'); + const result = deparse(ast); + expect(result).toBe('echo hello >file.txt'); + }); + + it('should deparse redirect input', () => { + const ast = parse('cat < input.txt'); + const result = deparse(ast); + expect(result).toBe('cat { + const ast = parse('echo hello >> file.txt'); + const result = deparse(ast); + expect(result).toBe('echo hello >>file.txt'); + }); + + it('should deparse assignment', () => { + const ast = parse('VAR=value'); + const result = deparse(ast); + expect(result).toBe('VAR=value'); + }); + + it('should deparse assignment with command', () => { + const ast = parse('VAR=value echo $VAR'); + const result = deparse(ast); + expect(result).toBe('VAR=value echo $VAR'); + }); + + it('should deparse subshell', () => { + const ast = parse('(echo hello)'); + const result = deparse(ast); + expect(result).toBe('(echo hello)'); + }); + + it('should deparse if statement', () => { + const ast = parse('if test -f file; then echo exists; fi'); + const result = deparse(ast); + expect(result).toContain('if'); + expect(result).toContain('then'); + expect(result).toContain('fi'); + }); + + it('should deparse while loop', () => { + const ast = parse('while true; do echo loop; done'); + const result = deparse(ast); + expect(result).toContain('while'); + expect(result).toContain('do'); + expect(result).toContain('done'); + }); + + it('should deparse for loop', () => { + const ast = parse('for i in 1 2 3; do echo $i; done'); + const result = deparse(ast); + expect(result).toContain('for'); + expect(result).toContain('in'); + expect(result).toContain('do'); + expect(result).toContain('done'); + }); + + it('should deparse function definition', () => { + const ast = parse('myfunc() { echo hello; }'); + const result = deparse(ast); + expect(result).toContain('myfunc()'); + }); + + it('should deparse multiple commands', () => { + const ast = parse('echo one; echo two'); + const result = deparse(ast); + expect(result).toContain('echo one'); + expect(result).toContain('echo two'); + }); + }); +}); diff --git a/packages/bash-parser/__tests__/parser.test.ts b/packages/bash-parser/__tests__/parser.test.ts new file mode 100644 index 0000000..5319680 --- /dev/null +++ b/packages/bash-parser/__tests__/parser.test.ts @@ -0,0 +1,202 @@ +import { parse } from '../src/parser'; +import { LogicalExpression,Pipeline, SimpleCommand } from '../src/types'; + +describe('bash-parser', () => { + describe('parse', () => { + it('should parse a simple command', () => { + const source = 'echo hello'; + const ast = parse(source); + + expect(ast.type).toBe('Script'); + expect(ast.commands).toHaveLength(1); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.type).toBe('SimpleCommand'); + expect(cmd.name?.text).toBe('echo'); + expect(cmd.suffix).toHaveLength(1); + expect(cmd.suffix?.[0].type).toBe('Word'); + }); + + it('should parse command with multiple arguments', () => { + const source = 'ls -la /tmp'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.name?.text).toBe('ls'); + expect(cmd.suffix).toHaveLength(2); + }); + + it('should parse pipeline', () => { + const source = 'cat file | grep pattern'; + const ast = parse(source); + + const pipeline = ast.commands[0] as Pipeline; + expect(pipeline.type).toBe('Pipeline'); + expect(pipeline.commands).toHaveLength(2); + }); + + it('should parse logical AND', () => { + const source = 'cmd1 && cmd2'; + const ast = parse(source); + + const expr = ast.commands[0] as LogicalExpression; + expect(expr.type).toBe('LogicalExpression'); + expect(expr.op).toBe('&&'); + }); + + it('should parse logical OR', () => { + const source = 'cmd1 || cmd2'; + const ast = parse(source); + + const expr = ast.commands[0] as LogicalExpression; + expect(expr.type).toBe('LogicalExpression'); + expect(expr.op).toBe('||'); + }); + + it('should parse redirect output', () => { + const source = 'echo hello > file.txt'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.suffix).toBeDefined(); + const redirect = cmd.suffix?.find(s => s.type === 'Redirect'); + expect(redirect).toBeDefined(); + if (redirect?.type === 'Redirect') { + expect(redirect.op).toBe('>'); + expect(redirect.file?.text).toBe('file.txt'); + } + }); + + it('should parse redirect input', () => { + const source = 'cat < input.txt'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + const redirect = cmd.suffix?.find(s => s.type === 'Redirect'); + expect(redirect).toBeDefined(); + if (redirect?.type === 'Redirect') { + expect(redirect.op).toBe('<'); + } + }); + + it('should parse append redirect', () => { + const source = 'echo hello >> file.txt'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + const redirect = cmd.suffix?.find(s => s.type === 'Redirect'); + if (redirect?.type === 'Redirect') { + expect(redirect.op).toBe('>>'); + } + }); + + it('should parse assignment', () => { + const source = 'VAR=value'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.prefix).toHaveLength(1); + expect(cmd.prefix?.[0].text).toBe('VAR=value'); + }); + + it('should parse assignment with command', () => { + const source = 'VAR=value echo $VAR'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.prefix).toHaveLength(1); + expect(cmd.name?.text).toBe('echo'); + }); + + it('should parse subshell', () => { + const source = '(echo hello)'; + const ast = parse(source); + + expect(ast.commands[0].type).toBe('Subshell'); + }); + + it('should parse if statement', () => { + const source = 'if test -f file; then echo exists; fi'; + const ast = parse(source); + + expect(ast.commands[0].type).toBe('IfClause'); + }); + + it('should parse while loop', () => { + const source = 'while true; do echo loop; done'; + const ast = parse(source); + + expect(ast.commands[0].type).toBe('WhileClause'); + }); + + it('should parse for loop', () => { + const source = 'for i in 1 2 3; do echo $i; done'; + const ast = parse(source); + + const forClause = ast.commands[0]; + expect(forClause.type).toBe('ForClause'); + if (forClause.type === 'ForClause') { + expect(forClause.name).toBe('i'); + expect(forClause.wordlist).toHaveLength(3); + } + }); + + it('should parse function definition', () => { + const source = 'myfunc() { echo hello; }'; + const ast = parse(source); + + expect(ast.commands[0].type).toBe('FunctionDefinition'); + if (ast.commands[0].type === 'FunctionDefinition') { + expect(ast.commands[0].name).toBe('myfunc'); + } + }); + + it('should parse multiple commands', () => { + const source = 'echo one; echo two'; + const ast = parse(source); + + expect(ast.commands).toHaveLength(2); + }); + + it('should parse quoted strings', () => { + const source = 'echo "hello world"'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + expect(cmd.suffix?.[0].type).toBe('Word'); + if (cmd.suffix?.[0].type === 'Word') { + expect(cmd.suffix[0].text).toBe('"hello world"'); + } + }); + + it('should parse single quoted strings', () => { + const source = "echo 'hello world'"; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + if (cmd.suffix?.[0].type === 'Word') { + expect(cmd.suffix[0].text).toBe("'hello world'"); + } + }); + + it('should parse variable expansion', () => { + const source = 'echo $HOME'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + if (cmd.suffix?.[0].type === 'Word') { + expect(cmd.suffix[0].text).toBe('$HOME'); + } + }); + + it('should parse command substitution', () => { + const source = 'echo $(pwd)'; + const ast = parse(source); + + const cmd = ast.commands[0] as SimpleCommand; + if (cmd.suffix?.[0].type === 'Word') { + expect(cmd.suffix[0].text).toBe('$(pwd)'); + } + }); + }); +}); diff --git a/packages/bash-parser/__tests__/roundtrip.test.ts b/packages/bash-parser/__tests__/roundtrip.test.ts new file mode 100644 index 0000000..1703738 --- /dev/null +++ b/packages/bash-parser/__tests__/roundtrip.test.ts @@ -0,0 +1,123 @@ +import { cleanTree } from '../src/clean'; +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; + +describe('bash-parser round-trip', () => { + /** + * Round-trip test helper: parse -> deparse -> parse -> compare cleaned ASTs + */ + function expectRoundTrip(source: string): void { + const ast1 = parse(source); + const deparsed = deparse(ast1); + const ast2 = parse(deparsed); + + const clean1 = cleanTree(ast1); + const clean2 = cleanTree(ast2); + + expect(clean2).toEqual(clean1); + } + + describe('simple commands', () => { + it('should round-trip simple command', () => { + expectRoundTrip('echo hello'); + }); + + it('should round-trip command with multiple arguments', () => { + expectRoundTrip('ls -la /tmp'); + }); + + it('should round-trip command with quoted string', () => { + expectRoundTrip('echo "hello world"'); + }); + + it('should round-trip command with single quoted string', () => { + expectRoundTrip("echo 'hello world'"); + }); + + it('should round-trip command with variable', () => { + expectRoundTrip('echo $HOME'); + }); + + it('should round-trip command with command substitution', () => { + expectRoundTrip('echo $(pwd)'); + }); + }); + + describe('pipelines', () => { + it('should round-trip simple pipeline', () => { + expectRoundTrip('cat file | grep pattern'); + }); + + it('should round-trip multi-stage pipeline', () => { + expectRoundTrip('cat file | grep pattern | sort'); + }); + }); + + describe('logical operators', () => { + it('should round-trip logical AND', () => { + expectRoundTrip('cmd1 && cmd2'); + }); + + it('should round-trip logical OR', () => { + expectRoundTrip('cmd1 || cmd2'); + }); + + it('should round-trip chained logical operators', () => { + expectRoundTrip('cmd1 && cmd2 || cmd3'); + }); + }); + + describe('redirections', () => { + it('should round-trip output redirect', () => { + expectRoundTrip('echo hello > file.txt'); + }); + + it('should round-trip input redirect', () => { + expectRoundTrip('cat < input.txt'); + }); + + it('should round-trip append redirect', () => { + expectRoundTrip('echo hello >> file.txt'); + }); + + it('should round-trip stderr redirect', () => { + expectRoundTrip('cmd 2> error.txt'); + }); + }); + + describe('assignments', () => { + it('should round-trip simple assignment', () => { + expectRoundTrip('VAR=value'); + }); + + it('should round-trip assignment with command', () => { + expectRoundTrip('VAR=value echo $VAR'); + }); + }); + + describe('control flow', () => { + it('should round-trip if statement', () => { + expectRoundTrip('if test -f file; then echo exists; fi'); + }); + + it('should round-trip while loop', () => { + expectRoundTrip('while true; do echo loop; done'); + }); + + it('should round-trip for loop', () => { + expectRoundTrip('for i in 1 2 3; do echo $i; done'); + }); + }); + + describe('grouping', () => { + it('should round-trip subshell', () => { + expectRoundTrip('(echo hello)'); + }); + }); + + describe('functions', () => { + it('should round-trip function definition', () => { + expectRoundTrip('myfunc() { echo hello; }'); + }); + }); +}); diff --git a/packages/bash-parser/jest.config.js b/packages/bash-parser/jest.config.js new file mode 100644 index 0000000..0cdb26d --- /dev/null +++ b/packages/bash-parser/jest.config.js @@ -0,0 +1,9 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.test.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + collectCoverageFrom: ['src/**/*.ts'], + coverageDirectory: 'coverage', + verbose: true +}; diff --git a/packages/bash-parser/package.json b/packages/bash-parser/package.json new file mode 100644 index 0000000..3aeb9d0 --- /dev/null +++ b/packages/bash-parser/package.json @@ -0,0 +1,42 @@ +{ + "name": "bash-parser", + "version": "0.0.1", + "author": "Constructive ", + "description": "Bash/shell command parser and deparser", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/dockerjs", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/dockerjs" + }, + "bugs": { + "url": "https://github.com/constructive-io/dockerjs/issues" + }, + "scripts": { + "copy": "makage assets", + "clean": "makage clean dist", + "prepublishOnly": "npm run build", + "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", + "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", + "lint": "cd ../.. && eslint packages/bash-parser --fix", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "bash", + "shell", + "parser", + "ast", + "deparser" + ], + "devDependencies": { + "makage": "^0.1.8" + } +} diff --git a/packages/bash-parser/src/clean.ts b/packages/bash-parser/src/clean.ts new file mode 100644 index 0000000..3a39a0a --- /dev/null +++ b/packages/bash-parser/src/clean.ts @@ -0,0 +1,79 @@ +import { Node, Script } from './types'; + +/** + * Transform function type + */ +type TransformFn = (value: any, key: string, parent: any) => any; + +/** + * Transform options - map of property names to transform functions + */ +type TransformOptions = Record; + +/** + * No-op transform function - removes the property + */ +export const noop = (): undefined => undefined; + +/** + * Deep transform an object + */ +function transform(obj: any, options: TransformOptions): any { + if (obj === null || obj === undefined) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(item => transform(item, options)); + } + + if (typeof obj === 'object') { + const result: any = {}; + for (const key of Object.keys(obj)) { + const value = obj[key]; + + // Check if there's a transform function for this key + if (key in options) { + const transformed = options[key](value, key, obj); + if (transformed !== undefined) { + result[key] = transformed; + } + // If undefined, skip the property (remove it) + } else { + // Recursively transform nested objects + result[key] = transform(value, options); + } + } + return result; + } + + return obj; +} + +/** + * Clean AST tree by removing location/position information + * This is used for comparing ASTs in round-trip testing + */ +export function cleanTree(tree: T): T { + return transform(tree, { + // Remove range/position information + range: noop, + + // Normalize text strings (trim whitespace) + text: (value: any) => { + if (typeof value === 'string') { + return value.trim(); + } + return value; + } + }) as T; +} + +/** + * Compare two ASTs for equality after cleaning + */ +export function compareAst(ast1: any, ast2: any): boolean { + const clean1 = cleanTree(ast1); + const clean2 = cleanTree(ast2); + return JSON.stringify(clean1) === JSON.stringify(clean2); +} diff --git a/packages/bash-parser/src/deparser.ts b/packages/bash-parser/src/deparser.ts new file mode 100644 index 0000000..85b739d --- /dev/null +++ b/packages/bash-parser/src/deparser.ts @@ -0,0 +1,371 @@ +import { + AssignmentWord, + CaseClause, + CaseItem, + Command, + CompoundList, + ForClause, + FunctionDefinition, + IfClause, + LogicalExpression, + Node, + Pipeline, + Redirect, + Script, + SimpleCommand, + Subshell, + UntilClause, + WhileClause, + Word, +} from './types'; + +/** + * Deparser options + */ +export interface DeparserOptions { + newline?: string; + indent?: string; +} + +/** + * Bash Deparser - converts AST back to source + */ +export class Deparser { + private options: DeparserOptions; + private indentLevel: number = 0; + + constructor(options: DeparserOptions = {}) { + this.options = { + newline: '\n', + indent: ' ', + ...options + }; + } + + /** + * Deparse AST to source string + */ + deparse(node: Script | Node): string { + if ('type' in node) { + switch (node.type) { + case 'Script': + return this.deparseScript(node as Script); + case 'SimpleCommand': + return this.deparseSimpleCommand(node as SimpleCommand); + case 'Pipeline': + return this.deparsePipeline(node as Pipeline); + case 'LogicalExpression': + return this.deparseLogicalExpression(node as LogicalExpression); + case 'Subshell': + return this.deparseSubshell(node as Subshell); + case 'CompoundList': + return this.deparseCompoundList(node as CompoundList); + case 'IfClause': + return this.deparseIf(node as IfClause); + case 'WhileClause': + return this.deparseWhile(node as WhileClause); + case 'UntilClause': + return this.deparseUntil(node as UntilClause); + case 'ForClause': + return this.deparseFor(node as ForClause); + case 'CaseClause': + return this.deparseCase(node as CaseClause); + case 'FunctionDefinition': + return this.deparseFunction(node as FunctionDefinition); + case 'Word': + return this.deparseWord(node as Word); + case 'AssignmentWord': + return (node as AssignmentWord).text; + case 'Redirect': + return this.deparseRedirect(node as Redirect); + default: + throw new Error(`Unknown node type: ${(node as any).type}`); + } + } + throw new Error('Invalid node'); + } + + /** + * Get current indentation + */ + private getIndent(): string { + return this.options.indent!.repeat(this.indentLevel); + } + + /** + * Deparse script + */ + private deparseScript(script: Script): string { + return script.commands + .map(cmd => this.deparseCommand(cmd)) + .join(this.options.newline); + } + + /** + * Deparse any command + */ + private deparseCommand(command: Command): string { + switch (command.type) { + case 'SimpleCommand': + return this.deparseSimpleCommand(command); + case 'Pipeline': + return this.deparsePipeline(command); + case 'LogicalExpression': + return this.deparseLogicalExpression(command); + case 'Subshell': + return this.deparseSubshell(command); + case 'CompoundList': + return this.deparseCompoundList(command); + case 'IfClause': + return this.deparseIf(command); + case 'WhileClause': + return this.deparseWhile(command); + case 'UntilClause': + return this.deparseUntil(command); + case 'ForClause': + return this.deparseFor(command); + case 'CaseClause': + return this.deparseCase(command); + case 'FunctionDefinition': + return this.deparseFunction(command); + default: + throw new Error(`Unknown command type: ${(command as any).type}`); + } + } + + /** + * Deparse simple command + */ + private deparseSimpleCommand(cmd: SimpleCommand): string { + const parts: string[] = []; + + // Prefix (assignments) + if (cmd.prefix) { + for (const assignment of cmd.prefix) { + parts.push(assignment.text); + } + } + + // Command name + if (cmd.name) { + parts.push(this.deparseWord(cmd.name)); + } + + // Suffix (arguments and redirections) + if (cmd.suffix) { + for (const item of cmd.suffix) { + if (item.type === 'Word') { + parts.push(this.deparseWord(item)); + } else if (item.type === 'Redirect') { + parts.push(this.deparseRedirect(item)); + } + } + } + + return parts.join(' '); + } + + /** + * Deparse word + */ + private deparseWord(word: Word): string { + return word.text; + } + + /** + * Deparse redirect + */ + private deparseRedirect(redirect: Redirect): string { + let result = ''; + + if (redirect.numberIo !== undefined) { + result += redirect.numberIo; + } + + result += redirect.op; + + if (redirect.file) { + result += this.deparseWord(redirect.file); + } + + return result; + } + + /** + * Deparse pipeline + */ + private deparsePipeline(pipeline: Pipeline): string { + const parts: string[] = []; + + if (pipeline.bang) { + parts.push('!'); + } + + parts.push( + pipeline.commands + .map(cmd => this.deparseCommand(cmd)) + .join(' | ') + ); + + return parts.join(' '); + } + + /** + * Deparse logical expression + */ + private deparseLogicalExpression(expr: LogicalExpression): string { + const left = this.deparseCommand(expr.left); + const right = this.deparseCommand(expr.right); + return `${left} ${expr.op} ${right}`; + } + + /** + * Deparse subshell + */ + private deparseSubshell(subshell: Subshell): string { + const list = this.deparseCompoundListInline(subshell.list); + return `(${list})`; + } + + /** + * Deparse compound list + */ + private deparseCompoundList(list: CompoundList): string { + return list.commands + .map(cmd => this.deparseCommand(cmd)) + .join('; '); + } + + /** + * Deparse compound list inline (for subshells, etc.) + */ + private deparseCompoundListInline(list: CompoundList): string { + return list.commands + .map(cmd => this.deparseCommand(cmd)) + .join('; '); + } + + /** + * Deparse if clause + */ + private deparseIf(ifClause: IfClause): string { + const parts: string[] = []; + + parts.push('if'); + parts.push(this.deparseCompoundListInline(ifClause.condition)); + parts.push('; then'); + parts.push(this.deparseCompoundListInline(ifClause.then)); + + if (ifClause.else) { + if (ifClause.else.type === 'IfClause') { + // elif + parts.push('; el' + this.deparseIf(ifClause.else).substring(0)); + return parts.join(' ').replace('; elif', '; elif').replace('; fi; fi', '; fi'); + } else { + parts.push('; else'); + parts.push(this.deparseCompoundListInline(ifClause.else)); + } + } + + parts.push('; fi'); + + return parts.join(' '); + } + + /** + * Deparse while clause + */ + private deparseWhile(whileClause: WhileClause): string { + const condition = this.deparseCompoundListInline(whileClause.condition); + const body = this.deparseCompoundListInline(whileClause.body); + return `while ${condition}; do ${body}; done`; + } + + /** + * Deparse until clause + */ + private deparseUntil(untilClause: UntilClause): string { + const condition = this.deparseCompoundListInline(untilClause.condition); + const body = this.deparseCompoundListInline(untilClause.body); + return `until ${condition}; do ${body}; done`; + } + + /** + * Deparse for clause + */ + private deparseFor(forClause: ForClause): string { + const parts: string[] = ['for', forClause.name]; + + if (forClause.wordlist && forClause.wordlist.length > 0) { + parts.push('in'); + parts.push(forClause.wordlist.map(w => this.deparseWord(w)).join(' ')); + } + + parts.push(';'); + parts.push('do'); + parts.push(this.deparseCompoundListInline(forClause.body)); + parts.push(';'); + parts.push('done'); + + return parts.join(' '); + } + + /** + * Deparse case clause + */ + private deparseCase(caseClause: CaseClause): string { + const parts: string[] = []; + + parts.push('case'); + parts.push(this.deparseWord(caseClause.word)); + parts.push('in'); + + for (const caseItem of caseClause.cases) { + parts.push(this.deparseCaseItem(caseItem)); + } + + parts.push('esac'); + + return parts.join(' '); + } + + /** + * Deparse case item + */ + private deparseCaseItem(caseItem: CaseItem): string { + const pattern = caseItem.pattern.map(w => this.deparseWord(w)).join('|'); + let result = `${pattern})`; + + if (caseItem.body) { + result += ' ' + this.deparseCompoundListInline(caseItem.body); + } + + result += ' ;;'; + + return result; + } + + /** + * Deparse function definition + */ + private deparseFunction(func: FunctionDefinition): string { + const body = func.body.type === 'Subshell' + ? this.deparseSubshell(func.body) + : `{ ${this.deparseCompoundListInline(func.body)}; }`; + + return `${func.name}() ${body}`; + } +} + +/** + * Deparse AST to source string + */ +export function deparse(node: Script | Node, options?: DeparserOptions): string { + const deparser = new Deparser(options); + return deparser.deparse(node); +} + +/** + * Synchronous deparse (same as deparse, for API consistency) + */ +export const deparseSync = deparse; diff --git a/packages/bash-parser/src/index.ts b/packages/bash-parser/src/index.ts new file mode 100644 index 0000000..d0717ee --- /dev/null +++ b/packages/bash-parser/src/index.ts @@ -0,0 +1,14 @@ +// Types +export * from './types'; + +// Lexer +export { Lexer, Token, TokenType } from './lexer'; + +// Parser +export { parse,Parser, ParserOptions } from './parser'; + +// Deparser +export { deparse, Deparser, DeparserOptions, deparseSync } from './deparser'; + +// Clean utilities +export { cleanTree, compareAst, noop } from './clean'; diff --git a/packages/bash-parser/src/lexer.ts b/packages/bash-parser/src/lexer.ts new file mode 100644 index 0000000..e4c9ab6 --- /dev/null +++ b/packages/bash-parser/src/lexer.ts @@ -0,0 +1,482 @@ +import { Position, Range } from './types'; + +/** + * Token types for bash lexer + */ +export enum TokenType { + // Words and identifiers + WORD = 'WORD', + NAME = 'NAME', + ASSIGNMENT_WORD = 'ASSIGNMENT_WORD', + + // Operators + PIPE = 'PIPE', + AND_IF = 'AND_IF', + OR_IF = 'OR_IF', + DSEMI = 'DSEMI', + SEMI = 'SEMI', + AMP = 'AMP', + NEWLINE = 'NEWLINE', + + // Redirections + LESS = 'LESS', + GREAT = 'GREAT', + DLESS = 'DLESS', + DGREAT = 'DGREAT', + LESSAND = 'LESSAND', + GREATAND = 'GREATAND', + LESSGREAT = 'LESSGREAT', + DLESSDASH = 'DLESSDASH', + CLOBBER = 'CLOBBER', + TLESS = 'TLESS', + + // Reserved words + IF = 'IF', + THEN = 'THEN', + ELSE = 'ELSE', + ELIF = 'ELIF', + FI = 'FI', + DO = 'DO', + DONE = 'DONE', + CASE = 'CASE', + ESAC = 'ESAC', + WHILE = 'WHILE', + UNTIL = 'UNTIL', + FOR = 'FOR', + IN = 'IN', + FUNCTION = 'FUNCTION', + BANG = 'BANG', + + // Grouping + LPAREN = 'LPAREN', + RPAREN = 'RPAREN', + LBRACE = 'LBRACE', + RBRACE = 'RBRACE', + + // Special + IO_NUMBER = 'IO_NUMBER', + EOF = 'EOF', + WHITESPACE = 'WHITESPACE', +} + +/** + * Token interface + */ +export interface Token { + type: TokenType; + value: string; + range: Range; +} + +/** + * Reserved words mapping + */ +const RESERVED_WORDS: Record = { + if: TokenType.IF, + then: TokenType.THEN, + else: TokenType.ELSE, + elif: TokenType.ELIF, + fi: TokenType.FI, + do: TokenType.DO, + done: TokenType.DONE, + case: TokenType.CASE, + esac: TokenType.ESAC, + while: TokenType.WHILE, + until: TokenType.UNTIL, + for: TokenType.FOR, + in: TokenType.IN, + function: TokenType.FUNCTION, + '!': TokenType.BANG, +}; + +/** + * Bash Lexer + */ +export class Lexer { + private input: string; + private pos: number = 0; + private line: number = 1; + private column: number = 0; + + constructor(input: string) { + this.input = input; + } + + /** + * Get current position + */ + private getPosition(): Position { + return { + line: this.line, + column: this.column, + offset: this.pos + }; + } + + /** + * Peek at current character + */ + private peek(offset: number = 0): string { + return this.input[this.pos + offset] || ''; + } + + /** + * Advance position by one character + */ + private advance(): string { + const char = this.input[this.pos]; + this.pos++; + if (char === '\n') { + this.line++; + this.column = 0; + } else { + this.column++; + } + return char; + } + + /** + * Check if at end of input + */ + private isAtEnd(): boolean { + return this.pos >= this.input.length; + } + + /** + * Check if character is whitespace (not newline) + */ + private isWhitespace(char: string): boolean { + return char === ' ' || char === '\t'; + } + + /** + * Check if character is a digit + */ + private isDigit(char: string): boolean { + return char >= '0' && char <= '9'; + } + + /** + * Check if character can start a word + */ + private isWordChar(char: string): boolean { + return char !== '' && + !this.isWhitespace(char) && + char !== '\n' && + char !== '|' && + char !== '&' && + char !== ';' && + char !== '(' && + char !== ')' && + char !== '<' && + char !== '>' && + char !== '{' && + char !== '}'; + } + + /** + * Skip whitespace (not newlines) + */ + private skipWhitespace(): void { + while (!this.isAtEnd() && this.isWhitespace(this.peek())) { + this.advance(); + } + } + + /** + * Read a single-quoted string + */ + private readSingleQuoted(): string { + let result = "'"; + this.advance(); // opening quote + while (!this.isAtEnd() && this.peek() !== "'") { + result += this.advance(); + } + if (this.peek() === "'") { + result += this.advance(); + } + return result; + } + + /** + * Read a double-quoted string + */ + private readDoubleQuoted(): string { + let result = '"'; + this.advance(); // opening quote + while (!this.isAtEnd() && this.peek() !== '"') { + if (this.peek() === '\\' && (this.peek(1) === '"' || this.peek(1) === '\\' || this.peek(1) === '$' || this.peek(1) === '`')) { + result += this.advance(); // backslash + result += this.advance(); // escaped char + } else { + result += this.advance(); + } + } + if (this.peek() === '"') { + result += this.advance(); + } + return result; + } + + /** + * Read a word token + */ + private readWord(): string { + let result = ''; + while (!this.isAtEnd() && this.isWordChar(this.peek())) { + const char = this.peek(); + if (char === "'") { + result += this.readSingleQuoted(); + } else if (char === '"') { + result += this.readDoubleQuoted(); + } else if (char === '\\') { + result += this.advance(); // backslash + if (!this.isAtEnd()) { + result += this.advance(); // escaped char + } + } else if (char === '$') { + result += this.readExpansion(); + } else if (char === '`') { + result += this.readBacktickSubstitution(); + } else { + result += this.advance(); + } + } + return result; + } + + /** + * Read an expansion ($VAR, ${VAR}, $(cmd), $((expr))) + */ + private readExpansion(): string { + let result = this.advance(); // $ + if (this.peek() === '(') { + if (this.peek(1) === '(') { + // Arithmetic expansion $((expr)) + result += this.advance(); // ( + result += this.advance(); // ( + let depth = 2; + while (!this.isAtEnd() && depth > 0) { + if (this.peek() === '(') depth++; + if (this.peek() === ')') depth--; + result += this.advance(); + } + } else { + // Command substitution $(cmd) + result += this.advance(); // ( + let depth = 1; + while (!this.isAtEnd() && depth > 0) { + if (this.peek() === '(') depth++; + if (this.peek() === ')') depth--; + result += this.advance(); + } + } + } else if (this.peek() === '{') { + // Parameter expansion ${VAR} + result += this.advance(); // { + let depth = 1; + while (!this.isAtEnd() && depth > 0) { + if (this.peek() === '{') depth++; + if (this.peek() === '}') depth--; + result += this.advance(); + } + } else { + // Simple variable $VAR + while (!this.isAtEnd() && /[a-zA-Z0-9_]/.test(this.peek())) { + result += this.advance(); + } + } + return result; + } + + /** + * Read backtick command substitution + */ + private readBacktickSubstitution(): string { + let result = this.advance(); // ` + while (!this.isAtEnd() && this.peek() !== '`') { + if (this.peek() === '\\') { + result += this.advance(); + if (!this.isAtEnd()) { + result += this.advance(); + } + } else { + result += this.advance(); + } + } + if (this.peek() === '`') { + result += this.advance(); + } + return result; + } + + /** + * Read a comment + */ + private readComment(): void { + while (!this.isAtEnd() && this.peek() !== '\n') { + this.advance(); + } + } + + /** + * Get next token + */ + nextToken(): Token { + this.skipWhitespace(); + + if (this.isAtEnd()) { + return { + type: TokenType.EOF, + value: '', + range: { start: this.getPosition(), end: this.getPosition() } + }; + } + + const start = this.getPosition(); + const char = this.peek(); + + // Comment + if (char === '#') { + this.readComment(); + return this.nextToken(); + } + + // Newline + if (char === '\n') { + this.advance(); + return { + type: TokenType.NEWLINE, + value: '\n', + range: { start, end: this.getPosition() } + }; + } + + // Operators + if (char === '|') { + this.advance(); + if (this.peek() === '|') { + this.advance(); + return { type: TokenType.OR_IF, value: '||', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.PIPE, value: '|', range: { start, end: this.getPosition() } }; + } + + if (char === '&') { + this.advance(); + if (this.peek() === '&') { + this.advance(); + return { type: TokenType.AND_IF, value: '&&', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.AMP, value: '&', range: { start, end: this.getPosition() } }; + } + + if (char === ';') { + this.advance(); + if (this.peek() === ';') { + this.advance(); + return { type: TokenType.DSEMI, value: ';;', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.SEMI, value: ';', range: { start, end: this.getPosition() } }; + } + + // Redirections + if (char === '<') { + this.advance(); + if (this.peek() === '<') { + this.advance(); + if (this.peek() === '-') { + this.advance(); + return { type: TokenType.DLESSDASH, value: '<<-', range: { start, end: this.getPosition() } }; + } + if (this.peek() === '<') { + this.advance(); + return { type: TokenType.TLESS, value: '<<<', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.DLESS, value: '<<', range: { start, end: this.getPosition() } }; + } + if (this.peek() === '&') { + this.advance(); + return { type: TokenType.LESSAND, value: '<&', range: { start, end: this.getPosition() } }; + } + if (this.peek() === '>') { + this.advance(); + return { type: TokenType.LESSGREAT, value: '<>', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.LESS, value: '<', range: { start, end: this.getPosition() } }; + } + + if (char === '>') { + this.advance(); + if (this.peek() === '>') { + this.advance(); + return { type: TokenType.DGREAT, value: '>>', range: { start, end: this.getPosition() } }; + } + if (this.peek() === '&') { + this.advance(); + return { type: TokenType.GREATAND, value: '>&', range: { start, end: this.getPosition() } }; + } + if (this.peek() === '|') { + this.advance(); + return { type: TokenType.CLOBBER, value: '>|', range: { start, end: this.getPosition() } }; + } + return { type: TokenType.GREAT, value: '>', range: { start, end: this.getPosition() } }; + } + + // Grouping + if (char === '(') { + this.advance(); + return { type: TokenType.LPAREN, value: '(', range: { start, end: this.getPosition() } }; + } + + if (char === ')') { + this.advance(); + return { type: TokenType.RPAREN, value: ')', range: { start, end: this.getPosition() } }; + } + + if (char === '{') { + this.advance(); + return { type: TokenType.LBRACE, value: '{', range: { start, end: this.getPosition() } }; + } + + if (char === '}') { + this.advance(); + return { type: TokenType.RBRACE, value: '}', range: { start, end: this.getPosition() } }; + } + + // IO number (digit followed by < or >) + if (this.isDigit(char) && (this.peek(1) === '<' || this.peek(1) === '>')) { + const num = this.advance(); + return { type: TokenType.IO_NUMBER, value: num, range: { start, end: this.getPosition() } }; + } + + // Word + const word = this.readWord(); + const end = this.getPosition(); + + // Check for reserved words + if (word in RESERVED_WORDS) { + return { type: RESERVED_WORDS[word], value: word, range: { start, end } }; + } + + // Check for assignment word (NAME=VALUE) + if (word.includes('=') && /^[a-zA-Z_][a-zA-Z0-9_]*=/.test(word)) { + return { type: TokenType.ASSIGNMENT_WORD, value: word, range: { start, end } }; + } + + return { type: TokenType.WORD, value: word, range: { start, end } }; + } + + /** + * Tokenize entire input + */ + tokenize(): Token[] { + const tokens: Token[] = []; + let token: Token; + do { + token = this.nextToken(); + tokens.push(token); + } while (token.type !== TokenType.EOF); + return tokens; + } +} diff --git a/packages/bash-parser/src/parser.ts b/packages/bash-parser/src/parser.ts new file mode 100644 index 0000000..7c20590 --- /dev/null +++ b/packages/bash-parser/src/parser.ts @@ -0,0 +1,800 @@ +import { Lexer, Token, TokenType } from './lexer'; +import { + AssignmentWord, + CaseClause, + CaseItem, + Command, + CompoundList, + ForClause, + FunctionDefinition, + IfClause, + Redirect, + RedirectOp, + Script, + SimpleCommand, + Subshell, + UntilClause, + WhileClause, + Word, +} from './types'; + +/** + * Parser options + */ +export interface ParserOptions { + // Reserved for future options +} + +/** + * Bash Parser + */ +export class Parser { + private tokens: Token[] = []; + private pos: number = 0; + private options: ParserOptions; + + constructor(options: ParserOptions = {}) { + this.options = options; + } + + /** + * Parse bash source into AST + */ + parse(source: string): Script { + const lexer = new Lexer(source); + this.tokens = lexer.tokenize(); + this.pos = 0; + + const commands: Command[] = []; + + this.skipNewlines(); + + while (!this.isAtEnd()) { + const command = this.parseCommand(); + if (command) { + commands.push(command); + } + this.skipNewlinesAndSeparators(); + } + + return { + type: 'Script', + commands + }; + } + + /** + * Check if at end of tokens + */ + private isAtEnd(): boolean { + return this.pos >= this.tokens.length || this.peek().type === TokenType.EOF; + } + + /** + * Peek at current token + */ + private peek(offset: number = 0): Token { + const idx = this.pos + offset; + if (idx >= this.tokens.length) { + return this.tokens[this.tokens.length - 1]; + } + return this.tokens[idx]; + } + + /** + * Advance to next token + */ + private advance(): Token { + if (!this.isAtEnd()) { + this.pos++; + } + return this.tokens[this.pos - 1]; + } + + /** + * Check if current token matches type + */ + private check(type: TokenType): boolean { + return this.peek().type === type; + } + + /** + * Consume token if it matches, otherwise error + */ + private expect(type: TokenType): Token { + if (this.check(type)) { + return this.advance(); + } + throw new Error(`Expected ${type}, got ${this.peek().type} at position ${this.pos}`); + } + + /** + * Skip newlines + */ + private skipNewlines(): void { + while (this.check(TokenType.NEWLINE)) { + this.advance(); + } + } + + /** + * Skip newlines and separators + */ + private skipNewlinesAndSeparators(): void { + while (this.check(TokenType.NEWLINE) || this.check(TokenType.SEMI) || this.check(TokenType.AMP)) { + this.advance(); + } + } + + /** + * Parse a command (handles logical operators) + */ + private parseCommand(): Command | null { + return this.parseLogicalOr(); + } + + /** + * Parse logical OR (||) + */ + private parseLogicalOr(): Command | null { + let left = this.parseLogicalAnd(); + if (!left) return null; + + while (this.check(TokenType.OR_IF)) { + this.advance(); + this.skipNewlines(); + const right = this.parseLogicalAnd(); + if (!right) { + throw new Error('Expected command after ||'); + } + left = { + type: 'LogicalExpression', + op: '||', + left, + right + }; + } + + return left; + } + + /** + * Parse logical AND (&&) + */ + private parseLogicalAnd(): Command | null { + let left = this.parsePipeline(); + if (!left) return null; + + while (this.check(TokenType.AND_IF)) { + this.advance(); + this.skipNewlines(); + const right = this.parsePipeline(); + if (!right) { + throw new Error('Expected command after &&'); + } + left = { + type: 'LogicalExpression', + op: '&&', + left, + right + }; + } + + return left; + } + + /** + * Parse pipeline (|) + */ + private parsePipeline(): Command | null { + let bang = false; + if (this.check(TokenType.BANG)) { + bang = true; + this.advance(); + } + + const first = this.parseCompoundCommand(); + if (!first) return null; + + const commands: Command[] = [first]; + + while (this.check(TokenType.PIPE)) { + this.advance(); + this.skipNewlines(); + const next = this.parseCompoundCommand(); + if (!next) { + throw new Error('Expected command after |'); + } + commands.push(next); + } + + if (commands.length === 1 && !bang) { + return first; + } + + return { + type: 'Pipeline', + commands, + bang: bang || undefined + }; + } + + /** + * Parse compound command or simple command + */ + private parseCompoundCommand(): Command | null { + const token = this.peek(); + + switch (token.type) { + case TokenType.IF: + return this.parseIf(); + case TokenType.WHILE: + return this.parseWhile(); + case TokenType.UNTIL: + return this.parseUntil(); + case TokenType.FOR: + return this.parseFor(); + case TokenType.CASE: + return this.parseCase(); + case TokenType.LPAREN: + return this.parseSubshell(); + case TokenType.LBRACE: + return this.parseBraceGroup(); + case TokenType.FUNCTION: + return this.parseFunction(); + default: + // Check for function definition (name () { ... }) + if (token.type === TokenType.WORD && this.peek(1).type === TokenType.LPAREN && this.peek(2).type === TokenType.RPAREN) { + return this.parseFunctionShorthand(); + } + return this.parseSimpleCommand(); + } + } + + /** + * Parse simple command + */ + private parseSimpleCommand(): SimpleCommand | null { + const prefix: AssignmentWord[] = []; + const suffix: (Word | Redirect)[] = []; + let name: Word | undefined; + + // Parse prefix (assignments before command name) + while (this.check(TokenType.ASSIGNMENT_WORD)) { + const token = this.advance(); + prefix.push({ + type: 'AssignmentWord', + text: token.value, + range: token.range + }); + } + + // Parse redirections before command name + while (this.isRedirectOp()) { + const redirect = this.parseRedirect(); + if (redirect) suffix.push(redirect); + } + + // Parse command name + if (this.check(TokenType.WORD)) { + const token = this.advance(); + name = { + type: 'Word', + text: token.value, + range: token.range + }; + } + + // Parse suffix (arguments and redirections) + while (true) { + if (this.isRedirectOp()) { + const redirect = this.parseRedirect(); + if (redirect) suffix.push(redirect); + } else if (this.check(TokenType.WORD)) { + const token = this.advance(); + suffix.push({ + type: 'Word', + text: token.value, + range: token.range + }); + } else { + break; + } + } + + if (!name && prefix.length === 0 && suffix.length === 0) { + return null; + } + + return { + type: 'SimpleCommand', + name, + prefix: prefix.length > 0 ? prefix : undefined, + suffix: suffix.length > 0 ? suffix : undefined + }; + } + + /** + * Check if current token is a redirect operator + */ + private isRedirectOp(): boolean { + const type = this.peek().type; + return type === TokenType.LESS || + type === TokenType.GREAT || + type === TokenType.DLESS || + type === TokenType.DGREAT || + type === TokenType.LESSAND || + type === TokenType.GREATAND || + type === TokenType.LESSGREAT || + type === TokenType.DLESSDASH || + type === TokenType.CLOBBER || + type === TokenType.TLESS || + type === TokenType.IO_NUMBER; + } + + /** + * Parse redirect + */ + private parseRedirect(): Redirect | null { + let numberIo: number | undefined; + + // Check for IO number + if (this.check(TokenType.IO_NUMBER)) { + numberIo = parseInt(this.advance().value, 10); + } + + const opToken = this.peek(); + let op: RedirectOp; + + switch (opToken.type) { + case TokenType.LESS: + op = '<'; + break; + case TokenType.GREAT: + op = '>'; + break; + case TokenType.DLESS: + op = '<<'; + break; + case TokenType.DGREAT: + op = '>>'; + break; + case TokenType.LESSAND: + op = '<&'; + break; + case TokenType.GREATAND: + op = '>&'; + break; + case TokenType.LESSGREAT: + op = '<>'; + break; + case TokenType.DLESSDASH: + op = '<<-'; + break; + case TokenType.CLOBBER: + op = '>|'; + break; + case TokenType.TLESS: + op = '<<<'; + break; + default: + return null; + } + + this.advance(); + + // Parse file/word + if (this.check(TokenType.WORD)) { + const fileToken = this.advance(); + return { + type: 'Redirect', + op, + file: { + type: 'Word', + text: fileToken.value, + range: fileToken.range + }, + numberIo, + range: opToken.range + }; + } + + return { + type: 'Redirect', + op, + numberIo, + range: opToken.range + }; + } + + /** + * Parse if clause + */ + private parseIf(): IfClause { + const start = this.expect(TokenType.IF); + this.skipNewlines(); + + const condition = this.parseCompoundList(); + + this.expect(TokenType.THEN); + this.skipNewlines(); + + const then = this.parseCompoundList(); + + let elseClause: CompoundList | IfClause | undefined; + + if (this.check(TokenType.ELIF)) { + elseClause = this.parseElif(); + } else if (this.check(TokenType.ELSE)) { + this.advance(); + this.skipNewlines(); + elseClause = this.parseCompoundList(); + } + + this.expect(TokenType.FI); + + return { + type: 'IfClause', + condition, + then, + else: elseClause, + range: start.range + }; + } + + /** + * Parse elif as nested if + */ + private parseElif(): IfClause { + this.expect(TokenType.ELIF); + this.skipNewlines(); + + const condition = this.parseCompoundList(); + + this.expect(TokenType.THEN); + this.skipNewlines(); + + const then = this.parseCompoundList(); + + let elseClause: CompoundList | IfClause | undefined; + + if (this.check(TokenType.ELIF)) { + elseClause = this.parseElif(); + } else if (this.check(TokenType.ELSE)) { + this.advance(); + this.skipNewlines(); + elseClause = this.parseCompoundList(); + } + + return { + type: 'IfClause', + condition, + then, + else: elseClause + }; + } + + /** + * Parse while clause + */ + private parseWhile(): WhileClause { + const start = this.expect(TokenType.WHILE); + this.skipNewlines(); + + const condition = this.parseCompoundList(); + + this.expect(TokenType.DO); + this.skipNewlines(); + + const body = this.parseCompoundList(); + + this.expect(TokenType.DONE); + + return { + type: 'WhileClause', + condition, + body, + range: start.range + }; + } + + /** + * Parse until clause + */ + private parseUntil(): UntilClause { + const start = this.expect(TokenType.UNTIL); + this.skipNewlines(); + + const condition = this.parseCompoundList(); + + this.expect(TokenType.DO); + this.skipNewlines(); + + const body = this.parseCompoundList(); + + this.expect(TokenType.DONE); + + return { + type: 'UntilClause', + condition, + body, + range: start.range + }; + } + + /** + * Parse for clause + */ + private parseFor(): ForClause { + const start = this.expect(TokenType.FOR); + + const nameToken = this.expect(TokenType.WORD); + const name = nameToken.value; + + this.skipNewlines(); + + let wordlist: Word[] | undefined; + + if (this.check(TokenType.IN)) { + this.advance(); + wordlist = []; + while (this.check(TokenType.WORD)) { + const token = this.advance(); + wordlist.push({ + type: 'Word', + text: token.value, + range: token.range + }); + } + } + + this.skipNewlinesAndSeparators(); + this.expect(TokenType.DO); + this.skipNewlines(); + + const body = this.parseCompoundList(); + + this.expect(TokenType.DONE); + + return { + type: 'ForClause', + name, + wordlist, + body, + range: start.range + }; + } + + /** + * Parse case clause + */ + private parseCase(): CaseClause { + const start = this.expect(TokenType.CASE); + + const wordToken = this.expect(TokenType.WORD); + const word: Word = { + type: 'Word', + text: wordToken.value, + range: wordToken.range + }; + + this.skipNewlines(); + this.expect(TokenType.IN); + this.skipNewlines(); + + const cases: CaseItem[] = []; + + while (!this.check(TokenType.ESAC)) { + const caseItem = this.parseCaseItem(); + if (caseItem) { + cases.push(caseItem); + } + this.skipNewlines(); + } + + this.expect(TokenType.ESAC); + + return { + type: 'CaseClause', + word, + cases, + range: start.range + }; + } + + /** + * Parse case item + */ + private parseCaseItem(): CaseItem | null { + // Skip optional ( + if (this.check(TokenType.LPAREN)) { + this.advance(); + } + + const pattern: Word[] = []; + + // Parse pattern + while (this.check(TokenType.WORD)) { + const token = this.advance(); + pattern.push({ + type: 'Word', + text: token.value, + range: token.range + }); + + if (this.check(TokenType.PIPE)) { + this.advance(); + } else { + break; + } + } + + if (pattern.length === 0) { + return null; + } + + this.expect(TokenType.RPAREN); + this.skipNewlines(); + + let body: CompoundList | undefined; + + if (!this.check(TokenType.DSEMI) && !this.check(TokenType.ESAC)) { + body = this.parseCompoundList(); + } + + if (this.check(TokenType.DSEMI)) { + this.advance(); + } + + return { + type: 'CaseItem', + pattern, + body + }; + } + + /** + * Parse subshell + */ + private parseSubshell(): Subshell { + const start = this.expect(TokenType.LPAREN); + this.skipNewlines(); + + const list = this.parseCompoundList(); + + this.expect(TokenType.RPAREN); + + return { + type: 'Subshell', + list, + range: start.range + }; + } + + /** + * Parse brace group + */ + private parseBraceGroup(): CompoundList { + this.expect(TokenType.LBRACE); + this.skipNewlines(); + + const list = this.parseCompoundList(); + + this.expect(TokenType.RBRACE); + + return list; + } + + /** + * Parse function definition (function name { ... }) + */ + private parseFunction(): FunctionDefinition { + const start = this.expect(TokenType.FUNCTION); + + const nameToken = this.expect(TokenType.WORD); + const name = nameToken.value; + + // Optional () + if (this.check(TokenType.LPAREN)) { + this.advance(); + this.expect(TokenType.RPAREN); + } + + this.skipNewlines(); + + const body = this.parseFunctionBody(); + + return { + type: 'FunctionDefinition', + name, + body, + range: start.range + }; + } + + /** + * Parse function shorthand (name () { ... }) + */ + private parseFunctionShorthand(): FunctionDefinition { + const nameToken = this.expect(TokenType.WORD); + const name = nameToken.value; + + this.expect(TokenType.LPAREN); + this.expect(TokenType.RPAREN); + + this.skipNewlines(); + + const body = this.parseFunctionBody(); + + return { + type: 'FunctionDefinition', + name, + body, + range: nameToken.range + }; + } + + /** + * Parse function body + */ + private parseFunctionBody(): CompoundList | Subshell { + if (this.check(TokenType.LPAREN)) { + return this.parseSubshell(); + } + + return this.parseBraceGroup(); + } + + /** + * Parse compound list (list of commands) + */ + private parseCompoundList(): CompoundList { + const commands: Command[] = []; + + while (true) { + this.skipNewlines(); + + // Check for terminators + if (this.isAtEnd() || + this.check(TokenType.THEN) || + this.check(TokenType.ELSE) || + this.check(TokenType.ELIF) || + this.check(TokenType.FI) || + this.check(TokenType.DO) || + this.check(TokenType.DONE) || + this.check(TokenType.ESAC) || + this.check(TokenType.RPAREN) || + this.check(TokenType.RBRACE) || + this.check(TokenType.DSEMI)) { + break; + } + + const command = this.parseCommand(); + if (command) { + commands.push(command); + } else { + break; + } + + // Check for separator + if (this.check(TokenType.SEMI) || this.check(TokenType.AMP) || this.check(TokenType.NEWLINE)) { + this.advance(); + } else { + break; + } + } + + return { + type: 'CompoundList', + commands + }; + } +} + +/** + * Parse bash source into AST + */ +export function parse(source: string, options?: ParserOptions): Script { + const parser = new Parser(options); + return parser.parse(source); +} diff --git a/packages/bash-parser/src/types.ts b/packages/bash-parser/src/types.ts new file mode 100644 index 0000000..207a609 --- /dev/null +++ b/packages/bash-parser/src/types.ts @@ -0,0 +1,261 @@ +/** + * Position in source code + */ +export interface Position { + line: number; + column: number; + offset: number; +} + +/** + * Range in source code + */ +export interface Range { + start: Position; + end: Position; +} + +/** + * Base node interface + */ +export interface BaseNode { + type: string; + range?: Range; +} + +/** + * Script - root node containing a list of commands + */ +export interface Script extends BaseNode { + type: 'Script'; + commands: Command[]; +} + +/** + * Union type for all command types + */ +export type Command = + | SimpleCommand + | Pipeline + | LogicalExpression + | Subshell + | CompoundList + | IfClause + | WhileClause + | UntilClause + | ForClause + | CaseClause + | FunctionDefinition; + +/** + * Simple command (e.g., `echo hello`) + */ +export interface SimpleCommand extends BaseNode { + type: 'SimpleCommand'; + name?: Word; + prefix?: AssignmentWord[]; + suffix?: (Word | Redirect)[]; +} + +/** + * Word - a token that can be expanded + */ +export interface Word extends BaseNode { + type: 'Word'; + text: string; + expansion?: Expansion[]; +} + +/** + * Assignment word (e.g., `VAR=value`) + */ +export interface AssignmentWord extends BaseNode { + type: 'AssignmentWord'; + text: string; + expansion?: Expansion[]; +} + +/** + * Union type for all expansion types + */ +export type Expansion = + | ParameterExpansion + | CommandSubstitution + | ArithmeticExpansion; + +/** + * Parameter expansion (e.g., `$VAR`, `${VAR}`, `${VAR:-default}`) + */ +export interface ParameterExpansion extends BaseNode { + type: 'ParameterExpansion'; + parameter: string; + kind?: 'default' | 'assign' | 'error' | 'alternative' | 'length' | 'prefix' | 'suffix'; + word?: Word; + op?: string; +} + +/** + * Command substitution (e.g., `$(command)` or `` `command` ``) + */ +export interface CommandSubstitution extends BaseNode { + type: 'CommandSubstitution'; + command: Script; + backtick?: boolean; +} + +/** + * Arithmetic expansion (e.g., `$((1 + 2))`) + */ +export interface ArithmeticExpansion extends BaseNode { + type: 'ArithmeticExpansion'; + expression: string; +} + +/** + * Redirect (e.g., `> file`, `2>&1`, `< input`) + */ +export interface Redirect extends BaseNode { + type: 'Redirect'; + op: RedirectOp; + file?: Word; + numberIo?: number; + heredoc?: HereDoc; +} + +/** + * Redirect operators + */ +export type RedirectOp = + | '>' + | '>>' + | '<' + | '<<' + | '<<-' + | '<<<' + | '<>' + | '>&' + | '<&' + | '>|'; + +/** + * Here document + */ +export interface HereDoc extends BaseNode { + type: 'HereDoc'; + delimiter: string; + content: string; + quoted?: boolean; +} + +/** + * Pipeline (e.g., `cmd1 | cmd2 | cmd3`) + */ +export interface Pipeline extends BaseNode { + type: 'Pipeline'; + commands: Command[]; + bang?: boolean; +} + +/** + * Logical expression (e.g., `cmd1 && cmd2`, `cmd1 || cmd2`) + */ +export interface LogicalExpression extends BaseNode { + type: 'LogicalExpression'; + op: '&&' | '||'; + left: Command; + right: Command; +} + +/** + * Subshell (e.g., `(cmd1; cmd2)`) + */ +export interface Subshell extends BaseNode { + type: 'Subshell'; + list: CompoundList; +} + +/** + * Compound list - a list of commands + */ +export interface CompoundList extends BaseNode { + type: 'CompoundList'; + commands: Command[]; +} + +/** + * If clause + */ +export interface IfClause extends BaseNode { + type: 'IfClause'; + condition: CompoundList; + then: CompoundList; + else?: CompoundList | IfClause; +} + +/** + * While clause + */ +export interface WhileClause extends BaseNode { + type: 'WhileClause'; + condition: CompoundList; + body: CompoundList; +} + +/** + * Until clause + */ +export interface UntilClause extends BaseNode { + type: 'UntilClause'; + condition: CompoundList; + body: CompoundList; +} + +/** + * For clause + */ +export interface ForClause extends BaseNode { + type: 'ForClause'; + name: string; + wordlist?: Word[]; + body: CompoundList; +} + +/** + * Case clause + */ +export interface CaseClause extends BaseNode { + type: 'CaseClause'; + word: Word; + cases: CaseItem[]; +} + +/** + * Case item + */ +export interface CaseItem extends BaseNode { + type: 'CaseItem'; + pattern: Word[]; + body?: CompoundList; +} + +/** + * Function definition + */ +export interface FunctionDefinition extends BaseNode { + type: 'FunctionDefinition'; + name: string; + body: CompoundList | Subshell; +} + +/** + * Union type for all AST nodes + */ +export type Node = + | Script + | Command + | Word + | AssignmentWord + | Redirect + | HereDoc + | CompoundList + | CaseItem; diff --git a/packages/bash-parser/test-utils/index.ts b/packages/bash-parser/test-utils/index.ts new file mode 100644 index 0000000..cdbb69f --- /dev/null +++ b/packages/bash-parser/test-utils/index.ts @@ -0,0 +1,112 @@ +import { readFileSync } from 'fs'; +import * as path from 'path'; + +import { cleanTree } from '../src/clean'; +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; +import { Script } from '../src/types'; + +/** + * Test utilities for bash-parser + */ +export class TestUtils { + /** + * Parse bash source + */ + parse(source: string): Script { + return parse(source); + } + + /** + * Deparse AST to source + */ + deparse(ast: Script): string { + return deparse(ast); + } + + /** + * Clean AST for comparison + */ + clean(ast: Script): Script { + return cleanTree(ast); + } + + /** + * Round-trip test: parse -> deparse -> parse -> compare cleaned ASTs + */ + async expectAstMatch(testName: string, source: string): Promise { + // First parse + const ast1 = this.parse(source); + + // Deparse + const deparsed = this.deparse(ast1); + + // Second parse + const ast2 = this.parse(deparsed); + + // Clean both ASTs + const clean1 = this.clean(ast1); + const clean2 = this.clean(ast2); + + // Compare + const json1 = JSON.stringify(clean1, null, 2); + const json2 = JSON.stringify(clean2, null, 2); + + if (json1 !== json2) { + const diff = require('jest-diff').diff(json1, json2); + throw new Error( + `AST mismatch for ${testName}:\n` + + `Original source:\n${source}\n\n` + + `Deparsed:\n${deparsed}\n\n` + + `AST diff:\n${diff}` + ); + } + } +} + +/** + * Fixture-based test utilities + */ +export class FixtureTestUtils extends TestUtils { + private fixtures: Record; + + constructor() { + super(); + const GENERATED_JSON = path.join(__dirname, '../../__fixtures__/generated/generated.json'); + try { + this.fixtures = JSON.parse(readFileSync(GENERATED_JSON, 'utf-8')); + } catch { + this.fixtures = {}; + } + } + + /** + * Get test entries, optionally filtered + */ + getTestEntries(filters: string[]): [string, string][] { + if (filters.length === 0) { + return Object.entries(this.fixtures); + } + return Object.entries(this.fixtures).filter(([relPath]) => + filters.includes(relPath) + ); + } + + /** + * Run fixture tests + */ + async runFixtureTests(filters: string[]): Promise { + if (filters.length === 0) { + console.log('no filters provided, skipping tests.'); + return; + } + const entries = this.getTestEntries(filters); + for (const [relativePath, source] of entries) { + try { + await this.expectAstMatch(relativePath, source); + } catch (err) { + throw err; + } + } + } +} diff --git a/packages/bash-parser/tsconfig.esm.json b/packages/bash-parser/tsconfig.esm.json new file mode 100644 index 0000000..aa8f22b --- /dev/null +++ b/packages/bash-parser/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ES2020", + "outDir": "dist/esm" + } +} diff --git a/packages/bash-parser/tsconfig.json b/packages/bash-parser/tsconfig.json new file mode 100644 index 0000000..c1ce63f --- /dev/null +++ b/packages/bash-parser/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "__tests__"] +} diff --git a/packages/docker-parser/README.md b/packages/docker-parser/README.md new file mode 100644 index 0000000..d17e84b --- /dev/null +++ b/packages/docker-parser/README.md @@ -0,0 +1,81 @@ +# docker-parser + +Dockerfile parser and deparser for JavaScript/TypeScript. + +## Installation + +```bash +npm install docker-parser +``` + +## Usage + +### Parsing + +```typescript +import { parse } from 'docker-parser'; + +const source = ` +FROM node:18-alpine +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +EXPOSE 3000 +CMD ["node", "server.js"] +`; + +const ast = parse(source); +console.log(JSON.stringify(ast, null, 2)); +``` + +### Deparsing + +```typescript +import { parse, deparse } from 'docker-parser'; + +const source = 'FROM node:18-alpine'; +const ast = parse(source); +const output = deparse(ast); +console.log(output); // FROM node:18-alpine +``` + +### AST Comparison + +```typescript +import { parse, cleanTree } from 'docker-parser'; + +const ast1 = parse('FROM node:18'); +const ast2 = parse('FROM node:18'); + +const clean1 = cleanTree(ast1); +const clean2 = cleanTree(ast2); + +// Compare ASTs without position information +console.log(JSON.stringify(clean1) === JSON.stringify(clean2)); // true +``` + +## Supported Instructions + +- FROM (with platform, AS alias, digest) +- RUN (shell and exec form, with mount flags) +- CMD (shell and exec form) +- ENTRYPOINT (shell and exec form) +- COPY (with --from, --chown, --chmod, --link) +- ADD (with --chown, --chmod, --checksum) +- ENV +- ARG +- WORKDIR +- USER +- EXPOSE +- VOLUME +- LABEL +- SHELL +- HEALTHCHECK +- STOPSIGNAL +- ONBUILD +- MAINTAINER (deprecated) + +## License + +MIT diff --git a/packages/docker-parser/__tests__/deparser.test.ts b/packages/docker-parser/__tests__/deparser.test.ts new file mode 100644 index 0000000..756f13f --- /dev/null +++ b/packages/docker-parser/__tests__/deparser.test.ts @@ -0,0 +1,151 @@ +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; + +describe('docker-deparser', () => { + describe('deparse', () => { + it('should deparse FROM instruction', () => { + const ast = parse('FROM node:18-alpine'); + const result = deparse(ast); + expect(result).toBe('FROM node:18-alpine'); + }); + + it('should deparse FROM with AS alias', () => { + const ast = parse('FROM node:18 AS builder'); + const result = deparse(ast); + expect(result).toBe('FROM node:18 AS builder'); + }); + + it('should deparse FROM with platform', () => { + const ast = parse('FROM --platform=linux/amd64 node:18'); + const result = deparse(ast); + expect(result).toBe('FROM --platform=linux/amd64 node:18'); + }); + + it('should deparse RUN instruction (shell form)', () => { + const ast = parse('FROM alpine\nRUN echo hello'); + const result = deparse(ast); + expect(result).toContain('RUN echo hello'); + }); + + it('should deparse RUN instruction (exec form)', () => { + const ast = parse('FROM alpine\nRUN ["echo", "hello"]'); + const result = deparse(ast); + expect(result).toContain('RUN ["echo","hello"]'); + }); + + it('should deparse COPY instruction', () => { + const ast = parse('FROM alpine\nCOPY src/ dest/'); + const result = deparse(ast); + expect(result).toContain('COPY src/ dest/'); + }); + + it('should deparse COPY with --from flag', () => { + const ast = parse('FROM alpine\nCOPY --from=builder /app /app'); + const result = deparse(ast); + expect(result).toContain('COPY --from=builder /app /app'); + }); + + it('should deparse ENV instruction', () => { + const ast = parse('FROM alpine\nENV NODE_ENV=production'); + const result = deparse(ast); + expect(result).toContain('ENV NODE_ENV=production'); + }); + + it('should deparse ARG instruction', () => { + const ast = parse('FROM alpine\nARG VERSION=1.0.0'); + const result = deparse(ast); + expect(result).toContain('ARG VERSION=1.0.0'); + }); + + it('should deparse WORKDIR instruction', () => { + const ast = parse('FROM alpine\nWORKDIR /app'); + const result = deparse(ast); + expect(result).toContain('WORKDIR /app'); + }); + + it('should deparse USER instruction', () => { + const ast = parse('FROM alpine\nUSER node:node'); + const result = deparse(ast); + expect(result).toContain('USER node:node'); + }); + + it('should deparse EXPOSE instruction', () => { + const ast = parse('FROM alpine\nEXPOSE 80 443/tcp'); + const result = deparse(ast); + expect(result).toContain('EXPOSE 80 443/tcp'); + }); + + it('should deparse VOLUME instruction', () => { + const ast = parse('FROM alpine\nVOLUME /data'); + const result = deparse(ast); + expect(result).toContain('VOLUME /data'); + }); + + it('should deparse LABEL instruction', () => { + const ast = parse('FROM alpine\nLABEL version=1.0'); + const result = deparse(ast); + expect(result).toContain('LABEL version=1.0'); + }); + + it('should deparse CMD instruction', () => { + const ast = parse('FROM alpine\nCMD ["node", "server.js"]'); + const result = deparse(ast); + expect(result).toContain('CMD ["node","server.js"]'); + }); + + it('should deparse ENTRYPOINT instruction', () => { + const ast = parse('FROM alpine\nENTRYPOINT ["python", "app.py"]'); + const result = deparse(ast); + expect(result).toContain('ENTRYPOINT ["python","app.py"]'); + }); + + it('should deparse SHELL instruction', () => { + const ast = parse('FROM alpine\nSHELL ["/bin/bash", "-c"]'); + const result = deparse(ast); + expect(result).toContain('SHELL ["/bin/bash","-c"]'); + }); + + it('should deparse HEALTHCHECK instruction', () => { + const ast = parse('FROM alpine\nHEALTHCHECK --interval=30s CMD ["curl", "-f", "http://localhost/"]'); + const result = deparse(ast); + expect(result).toContain('HEALTHCHECK --interval=30s CMD ["curl","-f","http://localhost/"]'); + }); + + it('should deparse HEALTHCHECK NONE', () => { + const ast = parse('FROM alpine\nHEALTHCHECK NONE'); + const result = deparse(ast); + expect(result).toContain('HEALTHCHECK NONE'); + }); + + it('should deparse STOPSIGNAL instruction', () => { + const ast = parse('FROM alpine\nSTOPSIGNAL SIGTERM'); + const result = deparse(ast); + expect(result).toContain('STOPSIGNAL SIGTERM'); + }); + + it('should deparse multi-stage build', () => { + const source = `FROM node:18 AS builder +WORKDIR /app + +FROM node:18-alpine +COPY --from=builder /app /app`; + + const ast = parse(source); + const result = deparse(ast); + + expect(result).toContain('FROM node:18 AS builder'); + expect(result).toContain('FROM node:18-alpine'); + expect(result).toContain('COPY --from=builder /app /app'); + }); + + it('should deparse parser directives', () => { + const source = `# escape=\` +FROM alpine`; + + const ast = parse(source); + const result = deparse(ast); + + expect(result).toContain('# escape=`'); + }); + }); +}); diff --git a/packages/docker-parser/__tests__/parser.test.ts b/packages/docker-parser/__tests__/parser.test.ts new file mode 100644 index 0000000..31ff4d7 --- /dev/null +++ b/packages/docker-parser/__tests__/parser.test.ts @@ -0,0 +1,276 @@ +import { parse } from '../src/parser'; +import { CopyInstruction, RunInstruction } from '../src/types'; + +describe('docker-parser', () => { + describe('parse', () => { + it('should parse a simple FROM instruction', () => { + const source = 'FROM node:18-alpine'; + const ast = parse(source); + + expect(ast.type).toBe('Dockerfile'); + expect(ast.stages).toHaveLength(1); + expect(ast.stages[0].from.image).toBe('node'); + expect(ast.stages[0].from.tag).toBe('18-alpine'); + }); + + it('should parse FROM with AS alias', () => { + const source = 'FROM node:18 AS builder'; + const ast = parse(source); + + expect(ast.stages[0].from.name).toBe('builder'); + }); + + it('should parse FROM with platform', () => { + const source = 'FROM --platform=linux/amd64 node:18'; + const ast = parse(source); + + expect(ast.stages[0].from.platform).toBe('linux/amd64'); + }); + + it('should parse FROM with digest', () => { + const source = 'FROM node@sha256:abc123'; + const ast = parse(source); + + expect(ast.stages[0].from.image).toBe('node'); + expect(ast.stages[0].from.digest).toBe('sha256:abc123'); + }); + + it('should parse RUN instruction (shell form)', () => { + const source = 'FROM alpine\nRUN echo hello'; + const ast = parse(source); + + const run = ast.stages[0].instructions[0] as RunInstruction; + expect(run.type).toBe('RunInstruction'); + expect(run.command).toBe('echo hello'); + expect(run.isExec).toBe(false); + }); + + it('should parse RUN instruction (exec form)', () => { + const source = 'FROM alpine\nRUN ["echo", "hello"]'; + const ast = parse(source); + + const run = ast.stages[0].instructions[0] as RunInstruction; + expect(run.type).toBe('RunInstruction'); + expect(run.command).toEqual(['echo', 'hello']); + expect(run.isExec).toBe(true); + }); + + it('should parse COPY instruction', () => { + const source = 'FROM alpine\nCOPY src/ dest/'; + const ast = parse(source); + + const copy = ast.stages[0].instructions[0] as CopyInstruction; + expect(copy.type).toBe('CopyInstruction'); + expect(copy.sources).toEqual(['src/']); + expect(copy.destination).toBe('dest/'); + }); + + it('should parse COPY with --from flag', () => { + const source = 'FROM alpine\nCOPY --from=builder /app /app'; + const ast = parse(source); + + const copy = ast.stages[0].instructions[0] as CopyInstruction; + expect(copy.from).toBe('builder'); + }); + + it('should parse ENV instruction', () => { + const source = 'FROM alpine\nENV NODE_ENV=production'; + const ast = parse(source); + + const env = ast.stages[0].instructions[0]; + expect(env.type).toBe('EnvInstruction'); + if (env.type === 'EnvInstruction') { + expect(env.variables).toEqual([{ key: 'NODE_ENV', value: 'production' }]); + } + }); + + it('should parse ARG instruction', () => { + const source = 'FROM alpine\nARG VERSION=1.0.0'; + const ast = parse(source); + + const arg = ast.stages[0].instructions[0]; + expect(arg.type).toBe('ArgInstruction'); + if (arg.type === 'ArgInstruction') { + expect(arg.name).toBe('VERSION'); + expect(arg.defaultValue).toBe('1.0.0'); + } + }); + + it('should parse WORKDIR instruction', () => { + const source = 'FROM alpine\nWORKDIR /app'; + const ast = parse(source); + + const workdir = ast.stages[0].instructions[0]; + expect(workdir.type).toBe('WorkdirInstruction'); + if (workdir.type === 'WorkdirInstruction') { + expect(workdir.path).toBe('/app'); + } + }); + + it('should parse USER instruction', () => { + const source = 'FROM alpine\nUSER node:node'; + const ast = parse(source); + + const user = ast.stages[0].instructions[0]; + expect(user.type).toBe('UserInstruction'); + if (user.type === 'UserInstruction') { + expect(user.user).toBe('node'); + expect(user.group).toBe('node'); + } + }); + + it('should parse EXPOSE instruction', () => { + const source = 'FROM alpine\nEXPOSE 80 443/tcp'; + const ast = parse(source); + + const expose = ast.stages[0].instructions[0]; + expect(expose.type).toBe('ExposeInstruction'); + if (expose.type === 'ExposeInstruction') { + expect(expose.ports).toHaveLength(2); + expect(expose.ports[0].port).toBe('80'); + expect(expose.ports[1].port).toBe('443'); + expect(expose.ports[1].protocol).toBe('tcp'); + } + }); + + it('should parse VOLUME instruction', () => { + const source = 'FROM alpine\nVOLUME /data'; + const ast = parse(source); + + const volume = ast.stages[0].instructions[0]; + expect(volume.type).toBe('VolumeInstruction'); + if (volume.type === 'VolumeInstruction') { + expect(volume.paths).toEqual(['/data']); + } + }); + + it('should parse LABEL instruction', () => { + const source = 'FROM alpine\nLABEL version=1.0'; + const ast = parse(source); + + const label = ast.stages[0].instructions[0]; + expect(label.type).toBe('LabelInstruction'); + if (label.type === 'LabelInstruction') { + expect(label.labels).toEqual([{ key: 'version', value: '1.0' }]); + } + }); + + it('should parse CMD instruction', () => { + const source = 'FROM alpine\nCMD ["node", "server.js"]'; + const ast = parse(source); + + const cmd = ast.stages[0].instructions[0]; + expect(cmd.type).toBe('CmdInstruction'); + if (cmd.type === 'CmdInstruction') { + expect(cmd.command).toEqual(['node', 'server.js']); + expect(cmd.isExec).toBe(true); + } + }); + + it('should parse ENTRYPOINT instruction', () => { + const source = 'FROM alpine\nENTRYPOINT ["python", "app.py"]'; + const ast = parse(source); + + const entrypoint = ast.stages[0].instructions[0]; + expect(entrypoint.type).toBe('EntrypointInstruction'); + if (entrypoint.type === 'EntrypointInstruction') { + expect(entrypoint.command).toEqual(['python', 'app.py']); + expect(entrypoint.isExec).toBe(true); + } + }); + + it('should parse SHELL instruction', () => { + const source = 'FROM alpine\nSHELL ["/bin/bash", "-c"]'; + const ast = parse(source); + + const shell = ast.stages[0].instructions[0]; + expect(shell.type).toBe('ShellInstruction'); + if (shell.type === 'ShellInstruction') { + expect(shell.shell).toEqual(['/bin/bash', '-c']); + } + }); + + it('should parse HEALTHCHECK instruction', () => { + const source = 'FROM alpine\nHEALTHCHECK --interval=30s CMD ["curl", "-f", "http://localhost/"]'; + const ast = parse(source); + + const healthcheck = ast.stages[0].instructions[0]; + expect(healthcheck.type).toBe('HealthcheckInstruction'); + if (healthcheck.type === 'HealthcheckInstruction') { + expect(healthcheck.interval).toBe('30s'); + expect(healthcheck.command?.command).toEqual(['curl', '-f', 'http://localhost/']); + } + }); + + it('should parse HEALTHCHECK NONE', () => { + const source = 'FROM alpine\nHEALTHCHECK NONE'; + const ast = parse(source); + + const healthcheck = ast.stages[0].instructions[0]; + expect(healthcheck.type).toBe('HealthcheckInstruction'); + if (healthcheck.type === 'HealthcheckInstruction') { + expect(healthcheck.none).toBe(true); + } + }); + + it('should parse STOPSIGNAL instruction', () => { + const source = 'FROM alpine\nSTOPSIGNAL SIGTERM'; + const ast = parse(source); + + const stopsignal = ast.stages[0].instructions[0]; + expect(stopsignal.type).toBe('StopsignalInstruction'); + if (stopsignal.type === 'StopsignalInstruction') { + expect(stopsignal.signal).toBe('SIGTERM'); + } + }); + + it('should parse multi-stage build', () => { + const source = `FROM node:18 AS builder +WORKDIR /app +RUN npm install + +FROM node:18-alpine +COPY --from=builder /app /app +CMD ["node", "index.js"]`; + + const ast = parse(source); + + expect(ast.stages).toHaveLength(2); + expect(ast.stages[0].from.name).toBe('builder'); + expect(ast.stages[1].from.tag).toBe('18-alpine'); + }); + + it('should parse parser directives', () => { + const source = `# escape=\` +FROM alpine +RUN echo hello`; + + const ast = parse(source); + + expect(ast.directives).toHaveLength(1); + expect(ast.directives[0].directive).toBe('escape'); + expect(ast.directives[0].value).toBe('`'); + }); + + it('should include bashAst for shell-form RUN instructions (heterogeneous parsing)', () => { + const source = 'FROM alpine\nRUN echo hello && npm install'; + const ast = parse(source); + + const run = ast.stages[0].instructions[0] as RunInstruction; + expect(run.type).toBe('RunInstruction'); + expect(run.isExec).toBe(false); + expect(run.bashAst).toBeDefined(); + expect((run.bashAst as { type: string }).type).toBe('Script'); + }); + + it('should not include bashAst for exec-form RUN instructions', () => { + const source = 'FROM alpine\nRUN ["echo", "hello"]'; + const ast = parse(source); + + const run = ast.stages[0].instructions[0] as RunInstruction; + expect(run.type).toBe('RunInstruction'); + expect(run.isExec).toBe(true); + expect(run.bashAst).toBeUndefined(); + }); + }); +}); diff --git a/packages/docker-parser/__tests__/roundtrip.test.ts b/packages/docker-parser/__tests__/roundtrip.test.ts new file mode 100644 index 0000000..205851a --- /dev/null +++ b/packages/docker-parser/__tests__/roundtrip.test.ts @@ -0,0 +1,180 @@ +import { cleanTree } from '../src/clean'; +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; + +describe('docker-parser round-trip', () => { + /** + * Round-trip test helper: parse -> deparse -> parse -> compare cleaned ASTs + */ + function expectRoundTrip(source: string): void { + const ast1 = parse(source); + const deparsed = deparse(ast1); + const ast2 = parse(deparsed); + + const clean1 = cleanTree(ast1); + const clean2 = cleanTree(ast2); + + expect(clean2).toEqual(clean1); + } + + describe('basic instructions', () => { + it('should round-trip FROM instruction', () => { + expectRoundTrip('FROM node:18-alpine'); + }); + + it('should round-trip FROM with AS alias', () => { + expectRoundTrip('FROM node:18 AS builder'); + }); + + it('should round-trip FROM with platform', () => { + expectRoundTrip('FROM --platform=linux/amd64 node:18'); + }); + + it('should round-trip FROM with digest', () => { + expectRoundTrip('FROM node@sha256:abc123'); + }); + + it('should round-trip RUN instruction (shell form)', () => { + expectRoundTrip('FROM alpine\nRUN echo hello'); + }); + + it('should round-trip RUN instruction (exec form)', () => { + expectRoundTrip('FROM alpine\nRUN ["echo", "hello"]'); + }); + + it('should round-trip COPY instruction', () => { + expectRoundTrip('FROM alpine\nCOPY src/ dest/'); + }); + + it('should round-trip COPY with --from flag', () => { + expectRoundTrip('FROM alpine\nCOPY --from=builder /app /app'); + }); + + it('should round-trip ADD instruction', () => { + expectRoundTrip('FROM alpine\nADD https://example.com/file.tar.gz /app/'); + }); + + it('should round-trip ENV instruction', () => { + expectRoundTrip('FROM alpine\nENV NODE_ENV=production'); + }); + + it('should round-trip ARG instruction', () => { + expectRoundTrip('FROM alpine\nARG VERSION=1.0.0'); + }); + + it('should round-trip ARG without default', () => { + expectRoundTrip('FROM alpine\nARG VERSION'); + }); + + it('should round-trip WORKDIR instruction', () => { + expectRoundTrip('FROM alpine\nWORKDIR /app'); + }); + + it('should round-trip USER instruction', () => { + expectRoundTrip('FROM alpine\nUSER node'); + }); + + it('should round-trip USER with group', () => { + expectRoundTrip('FROM alpine\nUSER node:node'); + }); + + it('should round-trip EXPOSE instruction', () => { + expectRoundTrip('FROM alpine\nEXPOSE 80'); + }); + + it('should round-trip EXPOSE with protocol', () => { + expectRoundTrip('FROM alpine\nEXPOSE 80/tcp 443/tcp'); + }); + + it('should round-trip VOLUME instruction', () => { + expectRoundTrip('FROM alpine\nVOLUME /data'); + }); + + it('should round-trip LABEL instruction', () => { + expectRoundTrip('FROM alpine\nLABEL version=1.0'); + }); + + it('should round-trip CMD instruction (exec form)', () => { + expectRoundTrip('FROM alpine\nCMD ["node", "server.js"]'); + }); + + it('should round-trip CMD instruction (shell form)', () => { + expectRoundTrip('FROM alpine\nCMD node server.js'); + }); + + it('should round-trip ENTRYPOINT instruction', () => { + expectRoundTrip('FROM alpine\nENTRYPOINT ["python", "app.py"]'); + }); + + it('should round-trip SHELL instruction', () => { + expectRoundTrip('FROM alpine\nSHELL ["/bin/bash", "-c"]'); + }); + + it('should round-trip HEALTHCHECK instruction', () => { + expectRoundTrip('FROM alpine\nHEALTHCHECK --interval=30s CMD ["curl", "-f", "http://localhost/"]'); + }); + + it('should round-trip HEALTHCHECK NONE', () => { + expectRoundTrip('FROM alpine\nHEALTHCHECK NONE'); + }); + + it('should round-trip STOPSIGNAL instruction', () => { + expectRoundTrip('FROM alpine\nSTOPSIGNAL SIGTERM'); + }); + }); + + describe('multi-stage builds', () => { + it('should round-trip simple multi-stage build', () => { + expectRoundTrip(`FROM node:18 AS builder +WORKDIR /app + +FROM node:18-alpine +COPY --from=builder /app /app`); + }); + + it('should round-trip complex multi-stage build', () => { + expectRoundTrip(`FROM golang:1.21 AS builder +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN go build -o /app/server + +FROM alpine:3.18 +COPY --from=builder /app/server /usr/local/bin/server +EXPOSE 8080 +ENTRYPOINT ["/usr/local/bin/server"]`); + }); + }); + + describe('parser directives', () => { + it('should round-trip escape directive', () => { + expectRoundTrip(`# escape=\` +FROM alpine`); + }); + }); + + describe('complete Dockerfiles', () => { + it('should round-trip a typical Node.js Dockerfile', () => { + expectRoundTrip(`FROM node:18-alpine +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +EXPOSE 3000 +CMD ["node", "server.js"]`); + }); + + it('should round-trip a Python Dockerfile with ENV and ARG', () => { + expectRoundTrip(`FROM python:3.11-slim +ENV PYTHONUNBUFFERED=1 +ARG VERSION=1.0.0 +WORKDIR /app +COPY requirements.txt . +RUN pip install -r requirements.txt +COPY . . +USER nobody +ENTRYPOINT ["python", "app.py"]`); + }); + }); +}); diff --git a/packages/docker-parser/jest.config.js b/packages/docker-parser/jest.config.js new file mode 100644 index 0000000..0cdb26d --- /dev/null +++ b/packages/docker-parser/jest.config.js @@ -0,0 +1,9 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.test.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + collectCoverageFrom: ['src/**/*.ts'], + coverageDirectory: 'coverage', + verbose: true +}; diff --git a/packages/docker-parser/package.json b/packages/docker-parser/package.json new file mode 100644 index 0000000..18f519b --- /dev/null +++ b/packages/docker-parser/package.json @@ -0,0 +1,45 @@ +{ + "name": "docker-parser", + "version": "0.0.1", + "author": "Constructive ", + "description": "Dockerfile parser and deparser", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/dockerjs", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/dockerjs" + }, + "bugs": { + "url": "https://github.com/constructive-io/dockerjs/issues" + }, + "scripts": { + "copy": "makage assets", + "clean": "makage clean dist", + "prepublishOnly": "npm run build", + "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", + "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", + "lint": "cd ../.. && eslint packages/docker-parser --fix", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "docker", + "dockerfile", + "parser", + "ast", + "deparser" + ], + "dependencies": { + "bash-parser": "workspace:*" + }, + "devDependencies": { + "makage": "^0.1.8" + } +} diff --git a/packages/docker-parser/scripts/generate-fixtures.ts b/packages/docker-parser/scripts/generate-fixtures.ts new file mode 100644 index 0000000..95d98c1 --- /dev/null +++ b/packages/docker-parser/scripts/generate-fixtures.ts @@ -0,0 +1,45 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +const FIXTURES_DIR = path.join(__dirname, '../../../__fixtures__/docker'); +const OUTPUT_FILE = path.join(FIXTURES_DIR, 'generated/generated.json'); + +function collectFixtures(dir: string, basePath: string = ''): Record { + const fixtures: Record = {}; + + const entries = fs.readdirSync(dir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name; + + if (entry.isDirectory()) { + if (entry.name !== 'generated') { + Object.assign(fixtures, collectFixtures(fullPath, relativePath)); + } + } else if (entry.name.endsWith('.dockerfile') || entry.name === 'Dockerfile') { + const content = fs.readFileSync(fullPath, 'utf-8'); + fixtures[relativePath] = content; + } + } + + return fixtures; +} + +function main() { + console.log('Collecting fixtures from:', FIXTURES_DIR); + + const fixtures = collectFixtures(FIXTURES_DIR); + + // Ensure output directory exists + const outputDir = path.dirname(OUTPUT_FILE); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + fs.writeFileSync(OUTPUT_FILE, JSON.stringify(fixtures, null, 2)); + + console.log(`Generated ${Object.keys(fixtures).length} fixtures to:`, OUTPUT_FILE); +} + +main(); diff --git a/packages/docker-parser/src/clean.ts b/packages/docker-parser/src/clean.ts new file mode 100644 index 0000000..c9d3cb3 --- /dev/null +++ b/packages/docker-parser/src/clean.ts @@ -0,0 +1,114 @@ +import { Dockerfile,Node } from './types'; + +/** + * Transform function type + */ +type TransformFn = (value: any, key: string, parent: any) => any; + +/** + * Transform options - map of property names to transform functions + */ +type TransformOptions = Record; + +/** + * No-op transform function - removes the property + */ +export const noop = (): undefined => undefined; + +/** + * Deep transform an object + */ +function transform(obj: any, options: TransformOptions): any { + if (obj === null || obj === undefined) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(item => transform(item, options)); + } + + if (typeof obj === 'object') { + const result: any = {}; + for (const key of Object.keys(obj)) { + const value = obj[key]; + + // Check if there's a transform function for this key + if (key in options) { + const transformed = options[key](value, key, obj); + if (transformed !== undefined) { + result[key] = transformed; + } + // If undefined, skip the property (remove it) + } else { + // Recursively transform nested objects + result[key] = transform(value, options); + } + } + return result; + } + + return obj; +} + +/** + * Clean AST tree by removing location/position information + * This is used for comparing ASTs in round-trip testing + */ +export function cleanTree(tree: T): T { + return transform(tree, { + // Remove range/position information + range: noop, + + // Normalize whitespace in command strings + command: (value: any) => { + if (typeof value === 'string') { + return value.trim().replace(/\s+/g, ' '); + } + if (Array.isArray(value)) { + return value.map(v => typeof v === 'string' ? v.trim() : v); + } + return value; + }, + + // Normalize path strings + path: (value: any) => { + if (typeof value === 'string') { + return value.trim(); + } + return value; + }, + + // Normalize maintainer strings + maintainer: (value: any) => { + if (typeof value === 'string') { + return value.trim(); + } + return value; + }, + + // Normalize signal strings + signal: (value: any) => { + if (typeof value === 'string') { + return value.trim(); + } + return value; + }, + + // Normalize value strings in env/label + value: (value: any) => { + if (typeof value === 'string') { + return value.trim(); + } + return value; + } + }) as T; +} + +/** + * Compare two ASTs for equality after cleaning + */ +export function compareAst(ast1: any, ast2: any): boolean { + const clean1 = cleanTree(ast1); + const clean2 = cleanTree(ast2); + return JSON.stringify(clean1) === JSON.stringify(clean2); +} diff --git a/packages/docker-parser/src/deparser.ts b/packages/docker-parser/src/deparser.ts new file mode 100644 index 0000000..0a82fd4 --- /dev/null +++ b/packages/docker-parser/src/deparser.ts @@ -0,0 +1,505 @@ +import { + AddInstruction, + ArgInstruction, + CmdInstruction, + Comment, + CopyInstruction, + Dockerfile, + EntrypointInstruction, + EnvInstruction, + ExposeInstruction, + FromInstruction, + HealthcheckInstruction, + Instruction, + LabelInstruction, + MaintainerInstruction, + MountFlag, + Node, + OnbuildInstruction, + ParserDirective, + RunInstruction, + ShellInstruction, + Stage, + StopsignalInstruction, + UserInstruction, + VolumeInstruction, + WorkdirInstruction, +} from './types'; + +/** + * Deparser options + */ +export interface DeparserOptions { + newline?: string; + indent?: string; +} + +/** + * Dockerfile Deparser - converts AST back to source + */ +export class Deparser { + private options: DeparserOptions; + + constructor(options: DeparserOptions = {}) { + this.options = { + newline: '\n', + indent: '', + ...options + }; + } + + /** + * Deparse Dockerfile AST to source string + */ + deparse(node: Dockerfile | Node): string { + if ('type' in node) { + switch (node.type) { + case 'Dockerfile': + return this.deparseDockerfile(node as Dockerfile); + case 'ParserDirective': + return this.deparseDirective(node as ParserDirective); + case 'Stage': + return this.deparseStage(node as Stage); + case 'Comment': + return this.deparseComment(node as Comment); + case 'FromInstruction': + return this.deparseFrom(node as FromInstruction); + case 'RunInstruction': + return this.deparseRun(node as RunInstruction); + case 'CmdInstruction': + return this.deparseCmd(node as CmdInstruction); + case 'EntrypointInstruction': + return this.deparseEntrypoint(node as EntrypointInstruction); + case 'CopyInstruction': + return this.deparseCopy(node as CopyInstruction); + case 'AddInstruction': + return this.deparseAdd(node as AddInstruction); + case 'EnvInstruction': + return this.deparseEnv(node as EnvInstruction); + case 'ArgInstruction': + return this.deparseArg(node as ArgInstruction); + case 'WorkdirInstruction': + return this.deparseWorkdir(node as WorkdirInstruction); + case 'UserInstruction': + return this.deparseUser(node as UserInstruction); + case 'ExposeInstruction': + return this.deparseExpose(node as ExposeInstruction); + case 'VolumeInstruction': + return this.deparseVolume(node as VolumeInstruction); + case 'LabelInstruction': + return this.deparseLabel(node as LabelInstruction); + case 'ShellInstruction': + return this.deparseShell(node as ShellInstruction); + case 'HealthcheckInstruction': + return this.deparseHealthcheck(node as HealthcheckInstruction); + case 'StopsignalInstruction': + return this.deparseStopsignal(node as StopsignalInstruction); + case 'OnbuildInstruction': + return this.deparseOnbuild(node as OnbuildInstruction); + case 'MaintainerInstruction': + return this.deparseMaintainer(node as MaintainerInstruction); + default: + throw new Error(`Unknown node type: ${(node as any).type}`); + } + } + throw new Error('Invalid node'); + } + + /** + * Deparse entire Dockerfile + */ + private deparseDockerfile(dockerfile: Dockerfile): string { + const lines: string[] = []; + + // Directives first + for (const directive of dockerfile.directives) { + lines.push(this.deparseDirective(directive)); + } + + // Then stages + for (const stage of dockerfile.stages) { + if (lines.length > 0) { + lines.push(''); + } + lines.push(this.deparseStage(stage)); + } + + return lines.join(this.options.newline); + } + + /** + * Deparse parser directive + */ + private deparseDirective(directive: ParserDirective): string { + return `# ${directive.directive}=${directive.value}`; + } + + /** + * Deparse build stage + */ + private deparseStage(stage: Stage): string { + const lines: string[] = []; + + // FROM instruction + lines.push(this.deparseFrom(stage.from)); + + // Other instructions + for (const instruction of stage.instructions) { + lines.push(this.deparseInstruction(instruction)); + } + + return lines.join(this.options.newline); + } + + /** + * Deparse comment + */ + private deparseComment(comment: Comment): string { + return `# ${comment.value}`; + } + + /** + * Deparse any instruction + */ + private deparseInstruction(instruction: Instruction): string { + switch (instruction.type) { + case 'FromInstruction': + return this.deparseFrom(instruction); + case 'RunInstruction': + return this.deparseRun(instruction); + case 'CmdInstruction': + return this.deparseCmd(instruction); + case 'EntrypointInstruction': + return this.deparseEntrypoint(instruction); + case 'CopyInstruction': + return this.deparseCopy(instruction); + case 'AddInstruction': + return this.deparseAdd(instruction); + case 'EnvInstruction': + return this.deparseEnv(instruction); + case 'ArgInstruction': + return this.deparseArg(instruction); + case 'WorkdirInstruction': + return this.deparseWorkdir(instruction); + case 'UserInstruction': + return this.deparseUser(instruction); + case 'ExposeInstruction': + return this.deparseExpose(instruction); + case 'VolumeInstruction': + return this.deparseVolume(instruction); + case 'LabelInstruction': + return this.deparseLabel(instruction); + case 'ShellInstruction': + return this.deparseShell(instruction); + case 'HealthcheckInstruction': + return this.deparseHealthcheck(instruction); + case 'StopsignalInstruction': + return this.deparseStopsignal(instruction); + case 'OnbuildInstruction': + return this.deparseOnbuild(instruction); + case 'MaintainerInstruction': + return this.deparseMaintainer(instruction); + default: + throw new Error(`Unknown instruction type: ${(instruction as any).type}`); + } + } + + /** + * Deparse FROM instruction + */ + private deparseFrom(from: FromInstruction): string { + const parts: string[] = ['FROM']; + + if (from.platform) { + parts.push(`--platform=${from.platform}`); + } + + let imageRef = from.image; + if (from.tag) { + imageRef += `:${from.tag}`; + } + if (from.digest) { + imageRef += `@${from.digest}`; + } + parts.push(imageRef); + + if (from.name) { + parts.push('AS', from.name); + } + + return parts.join(' '); + } + + /** + * Deparse RUN instruction + */ + private deparseRun(run: RunInstruction): string { + const parts: string[] = ['RUN']; + + // Mount flags + if (run.mount) { + for (const mount of run.mount) { + parts.push(this.deparseMountFlag(mount)); + } + } + + // Network flag + if (run.network) { + parts.push(`--network=${run.network}`); + } + + // Security flag + if (run.security) { + parts.push(`--security=${run.security}`); + } + + // Command + if (run.isExec && Array.isArray(run.command)) { + parts.push(JSON.stringify(run.command)); + } else { + parts.push(run.command as string); + } + + return parts.join(' '); + } + + /** + * Deparse mount flag + */ + private deparseMountFlag(mount: MountFlag): string { + const opts: string[] = []; + + if (mount.type) opts.push(`type=${mount.type}`); + if (mount.target) opts.push(`target=${mount.target}`); + if (mount.source) opts.push(`source=${mount.source}`); + if (mount.from) opts.push(`from=${mount.from}`); + if (mount.id) opts.push(`id=${mount.id}`); + if (mount.sharing) opts.push(`sharing=${mount.sharing}`); + if (mount.readonly) opts.push('readonly'); + if (mount.required) opts.push('required'); + if (mount.mode) opts.push(`mode=${mount.mode}`); + if (mount.uid) opts.push(`uid=${mount.uid}`); + if (mount.gid) opts.push(`gid=${mount.gid}`); + + return `--mount=${opts.join(',')}`; + } + + /** + * Deparse CMD instruction + */ + private deparseCmd(cmd: CmdInstruction): string { + if (cmd.isExec && Array.isArray(cmd.command)) { + return `CMD ${JSON.stringify(cmd.command)}`; + } + return `CMD ${cmd.command}`; + } + + /** + * Deparse ENTRYPOINT instruction + */ + private deparseEntrypoint(entrypoint: EntrypointInstruction): string { + if (entrypoint.isExec && Array.isArray(entrypoint.command)) { + return `ENTRYPOINT ${JSON.stringify(entrypoint.command)}`; + } + return `ENTRYPOINT ${entrypoint.command}`; + } + + /** + * Deparse COPY instruction + */ + private deparseCopy(copy: CopyInstruction): string { + const parts: string[] = ['COPY']; + + if (copy.from) parts.push(`--from=${copy.from}`); + if (copy.chown) parts.push(`--chown=${copy.chown}`); + if (copy.chmod) parts.push(`--chmod=${copy.chmod}`); + if (copy.link) parts.push('--link'); + if (copy.parents) parts.push('--parents'); + if (copy.exclude) { + for (const exc of copy.exclude) { + parts.push(`--exclude=${exc}`); + } + } + + parts.push(...copy.sources); + parts.push(copy.destination); + + return parts.join(' '); + } + + /** + * Deparse ADD instruction + */ + private deparseAdd(add: AddInstruction): string { + const parts: string[] = ['ADD']; + + if (add.chown) parts.push(`--chown=${add.chown}`); + if (add.chmod) parts.push(`--chmod=${add.chmod}`); + if (add.link) parts.push('--link'); + if (add.checksum) parts.push(`--checksum=${add.checksum}`); + if (add.keepGitDir) parts.push('--keep-git-dir'); + if (add.exclude) { + for (const exc of add.exclude) { + parts.push(`--exclude=${exc}`); + } + } + + parts.push(...add.sources); + parts.push(add.destination); + + return parts.join(' '); + } + + /** + * Deparse ENV instruction + */ + private deparseEnv(env: EnvInstruction): string { + const parts: string[] = ['ENV']; + + for (const variable of env.variables) { + const value = this.needsQuotes(variable.value) + ? `"${variable.value}"` + : variable.value; + parts.push(`${variable.key}=${value}`); + } + + return parts.join(' '); + } + + /** + * Deparse ARG instruction + */ + private deparseArg(arg: ArgInstruction): string { + if (arg.defaultValue !== undefined) { + return `ARG ${arg.name}=${arg.defaultValue}`; + } + return `ARG ${arg.name}`; + } + + /** + * Deparse WORKDIR instruction + */ + private deparseWorkdir(workdir: WorkdirInstruction): string { + return `WORKDIR ${workdir.path}`; + } + + /** + * Deparse USER instruction + */ + private deparseUser(user: UserInstruction): string { + if (user.group) { + return `USER ${user.user}:${user.group}`; + } + return `USER ${user.user}`; + } + + /** + * Deparse EXPOSE instruction + */ + private deparseExpose(expose: ExposeInstruction): string { + const ports = expose.ports.map(p => { + if (p.protocol) { + return `${p.port}/${p.protocol}`; + } + return String(p.port); + }); + return `EXPOSE ${ports.join(' ')}`; + } + + /** + * Deparse VOLUME instruction + */ + private deparseVolume(volume: VolumeInstruction): string { + if (volume.paths.length === 1) { + return `VOLUME ${volume.paths[0]}`; + } + return `VOLUME ${JSON.stringify(volume.paths)}`; + } + + /** + * Deparse LABEL instruction + */ + private deparseLabel(label: LabelInstruction): string { + const parts: string[] = ['LABEL']; + + for (const entry of label.labels) { + const value = this.needsQuotes(entry.value) + ? `"${entry.value}"` + : entry.value; + parts.push(`${entry.key}=${value}`); + } + + return parts.join(' '); + } + + /** + * Deparse SHELL instruction + */ + private deparseShell(shell: ShellInstruction): string { + return `SHELL ${JSON.stringify(shell.shell)}`; + } + + /** + * Deparse HEALTHCHECK instruction + */ + private deparseHealthcheck(healthcheck: HealthcheckInstruction): string { + if (healthcheck.none) { + return 'HEALTHCHECK NONE'; + } + + const parts: string[] = ['HEALTHCHECK']; + + if (healthcheck.interval) parts.push(`--interval=${healthcheck.interval}`); + if (healthcheck.timeout) parts.push(`--timeout=${healthcheck.timeout}`); + if (healthcheck.startPeriod) parts.push(`--start-period=${healthcheck.startPeriod}`); + if (healthcheck.startInterval) parts.push(`--start-interval=${healthcheck.startInterval}`); + if (healthcheck.retries !== undefined) parts.push(`--retries=${healthcheck.retries}`); + + if (healthcheck.command) { + parts.push(this.deparseCmd(healthcheck.command)); + } + + return parts.join(' '); + } + + /** + * Deparse STOPSIGNAL instruction + */ + private deparseStopsignal(stopsignal: StopsignalInstruction): string { + return `STOPSIGNAL ${stopsignal.signal}`; + } + + /** + * Deparse ONBUILD instruction + */ + private deparseOnbuild(onbuild: OnbuildInstruction): string { + return `ONBUILD ${this.deparseInstruction(onbuild.trigger)}`; + } + + /** + * Deparse MAINTAINER instruction + */ + private deparseMaintainer(maintainer: MaintainerInstruction): string { + return `MAINTAINER ${maintainer.maintainer}`; + } + + /** + * Check if value needs quotes + */ + private needsQuotes(value: string): boolean { + return value.includes(' ') || value.includes('\t') || value.includes('"') || value.includes("'"); + } +} + +/** + * Deparse Dockerfile AST to source string + */ +export function deparse(node: Dockerfile | Node, options?: DeparserOptions): string { + const deparser = new Deparser(options); + return deparser.deparse(node); +} + +/** + * Synchronous deparse (same as deparse, for API consistency) + */ +export const deparseSync = deparse; diff --git a/packages/docker-parser/src/index.ts b/packages/docker-parser/src/index.ts new file mode 100644 index 0000000..d0717ee --- /dev/null +++ b/packages/docker-parser/src/index.ts @@ -0,0 +1,14 @@ +// Types +export * from './types'; + +// Lexer +export { Lexer, Token, TokenType } from './lexer'; + +// Parser +export { parse,Parser, ParserOptions } from './parser'; + +// Deparser +export { deparse, Deparser, DeparserOptions, deparseSync } from './deparser'; + +// Clean utilities +export { cleanTree, compareAst, noop } from './clean'; diff --git a/packages/docker-parser/src/lexer.ts b/packages/docker-parser/src/lexer.ts new file mode 100644 index 0000000..380c2f7 --- /dev/null +++ b/packages/docker-parser/src/lexer.ts @@ -0,0 +1,445 @@ +import { Position, Range } from './types'; + +/** + * Token types for Dockerfile lexer + */ +export enum TokenType { + // Instructions + FROM = 'FROM', + RUN = 'RUN', + CMD = 'CMD', + LABEL = 'LABEL', + MAINTAINER = 'MAINTAINER', + EXPOSE = 'EXPOSE', + ENV = 'ENV', + ADD = 'ADD', + COPY = 'COPY', + ENTRYPOINT = 'ENTRYPOINT', + VOLUME = 'VOLUME', + USER = 'USER', + WORKDIR = 'WORKDIR', + ARG = 'ARG', + ONBUILD = 'ONBUILD', + STOPSIGNAL = 'STOPSIGNAL', + HEALTHCHECK = 'HEALTHCHECK', + SHELL = 'SHELL', + + // Other tokens + COMMENT = 'COMMENT', + DIRECTIVE = 'DIRECTIVE', + STRING = 'STRING', + QUOTED_STRING = 'QUOTED_STRING', + JSON_ARRAY = 'JSON_ARRAY', + NEWLINE = 'NEWLINE', + WHITESPACE = 'WHITESPACE', + CONTINUATION = 'CONTINUATION', + FLAG = 'FLAG', + EQUALS = 'EQUALS', + EOF = 'EOF', + UNKNOWN = 'UNKNOWN', +} + +/** + * Token interface + */ +export interface Token { + type: TokenType; + value: string; + range: Range; +} + +/** + * Instruction keywords + */ +const INSTRUCTIONS = new Set([ + 'FROM', 'RUN', 'CMD', 'LABEL', 'MAINTAINER', 'EXPOSE', 'ENV', + 'ADD', 'COPY', 'ENTRYPOINT', 'VOLUME', 'USER', 'WORKDIR', + 'ARG', 'ONBUILD', 'STOPSIGNAL', 'HEALTHCHECK', 'SHELL' +]); + +/** + * Dockerfile Lexer + */ +export class Lexer { + private input: string; + private pos: number = 0; + private line: number = 1; + private column: number = 0; + private escapeChar: string = '\\'; + private atLineStart: boolean = true; + + constructor(input: string) { + this.input = input; + } + + /** + * Set the escape character (from parser directive) + */ + setEscapeChar(char: string): void { + if (char === '\\' || char === '`') { + this.escapeChar = char; + } + } + + /** + * Get current position + */ + private getPosition(): Position { + return { + line: this.line, + column: this.column, + offset: this.pos + }; + } + + /** + * Peek at current character + */ + private peek(offset: number = 0): string { + return this.input[this.pos + offset] || ''; + } + + /** + * Advance position by one character + */ + private advance(): string { + const char = this.input[this.pos]; + this.pos++; + if (char === '\n') { + this.line++; + this.column = 0; + this.atLineStart = true; + } else { + this.column++; + if (char !== ' ' && char !== '\t') { + this.atLineStart = false; + } + } + return char; + } + + /** + * Check if at end of input + */ + private isAtEnd(): boolean { + return this.pos >= this.input.length; + } + + /** + * Skip whitespace (not newlines) + */ + private skipWhitespace(): void { + while (!this.isAtEnd() && (this.peek() === ' ' || this.peek() === '\t')) { + this.advance(); + } + } + + /** + * Read until end of line, handling continuations + */ + private readToEndOfLine(): string { + let result = ''; + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === '\n') { + break; + } + if (char === '\r') { + this.advance(); + continue; + } + if (char === this.escapeChar && (this.peek(1) === '\n' || this.peek(1) === '\r')) { + // Line continuation + this.advance(); // escape char + if (this.peek() === '\r') this.advance(); + if (this.peek() === '\n') this.advance(); + result += ' '; + continue; + } + result += this.advance(); + } + return result; + } + + /** + * Read a quoted string + */ + private readQuotedString(quote: string): string { + let result = quote; + this.advance(); // opening quote + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === quote) { + result += this.advance(); + break; + } + if (char === '\\' && this.peek(1) === quote) { + result += this.advance(); // backslash + result += this.advance(); // escaped quote + continue; + } + if (char === '\n') { + break; + } + result += this.advance(); + } + return result; + } + + /** + * Read a JSON array + */ + private readJsonArray(): string { + let result = ''; + let depth = 0; + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === '[') { + depth++; + result += this.advance(); + } else if (char === ']') { + depth--; + result += this.advance(); + if (depth === 0) break; + } else if (char === '"') { + result += this.readQuotedString('"'); + } else if (char === '\n' && depth === 0) { + break; + } else { + result += this.advance(); + } + } + return result; + } + + /** + * Read an identifier/word + */ + private readWord(): string { + let result = ''; + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === ' ' || char === '\t' || char === '\n' || char === '\r' || char === '=') { + break; + } + if (char === this.escapeChar && (this.peek(1) === '\n' || this.peek(1) === '\r')) { + // Line continuation + this.advance(); + if (this.peek() === '\r') this.advance(); + if (this.peek() === '\n') this.advance(); + continue; + } + result += this.advance(); + } + return result; + } + + /** + * Check if this looks like a parser directive + */ + private isDirective(): boolean { + if (this.peek() !== '#') return false; + // Look ahead for directive pattern: # directive=value + let i = 1; + while (this.peek(i) === ' ' || this.peek(i) === '\t') i++; + let word = ''; + while (this.peek(i) && /[a-zA-Z]/.test(this.peek(i))) { + word += this.peek(i); + i++; + } + while (this.peek(i) === ' ' || this.peek(i) === '\t') i++; + return this.peek(i) === '=' && (word.toLowerCase() === 'escape' || word.toLowerCase() === 'syntax'); + } + + /** + * Read until end of line without handling continuations + * Used for directive values where we don't want escape handling + */ + private readToEndOfLineRaw(): string { + let result = ''; + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === '\n' || char === '\r') { + break; + } + result += this.advance(); + } + return result; + } + + /** + * Read a comment or directive + */ + private readComment(): Token { + const start = this.getPosition(); + this.advance(); // # + + // Check for directive + this.skipWhitespace(); + const wordStart = this.pos; + let word = ''; + while (!this.isAtEnd() && /[a-zA-Z]/.test(this.peek())) { + word += this.advance(); + } + + this.skipWhitespace(); + + if (this.peek() === '=' && (word.toLowerCase() === 'escape' || word.toLowerCase() === 'syntax')) { + this.advance(); // = + this.skipWhitespace(); + // Use raw read for directive values to avoid escape character issues + const value = this.readToEndOfLineRaw().trim(); + const end = this.getPosition(); + return { + type: TokenType.DIRECTIVE, + value: `${word.toLowerCase()}=${value}`, + range: { start, end } + }; + } + + // Regular comment - reset and read the whole line + this.pos = wordStart; + const value = this.readToEndOfLine(); + const end = this.getPosition(); + return { + type: TokenType.COMMENT, + value: value.trim(), + range: { start, end } + }; + } + + /** + * Get next token + */ + nextToken(): Token { + // Skip whitespace at start of line + if (this.atLineStart) { + this.skipWhitespace(); + } + + if (this.isAtEnd()) { + return { + type: TokenType.EOF, + value: '', + range: { start: this.getPosition(), end: this.getPosition() } + }; + } + + const start = this.getPosition(); + const char = this.peek(); + + // Newline + if (char === '\n') { + this.advance(); + return { + type: TokenType.NEWLINE, + value: '\n', + range: { start, end: this.getPosition() } + }; + } + + // Carriage return + if (char === '\r') { + this.advance(); + if (this.peek() === '\n') { + this.advance(); + } + return { + type: TokenType.NEWLINE, + value: '\n', + range: { start, end: this.getPosition() } + }; + } + + // Comment or directive (only at line start) + if (char === '#' && this.atLineStart) { + return this.readComment(); + } + + // Whitespace + if (char === ' ' || char === '\t') { + let value = ''; + while (!this.isAtEnd() && (this.peek() === ' ' || this.peek() === '\t')) { + value += this.advance(); + } + return { + type: TokenType.WHITESPACE, + value, + range: { start, end: this.getPosition() } + }; + } + + // JSON array + if (char === '[') { + const value = this.readJsonArray(); + return { + type: TokenType.JSON_ARRAY, + value, + range: { start, end: this.getPosition() } + }; + } + + // Quoted string + if (char === '"' || char === "'") { + const value = this.readQuotedString(char); + return { + type: TokenType.QUOTED_STRING, + value, + range: { start, end: this.getPosition() } + }; + } + + // Flag (--something) + if (char === '-' && this.peek(1) === '-') { + const value = this.readWord(); + return { + type: TokenType.FLAG, + value, + range: { start, end: this.getPosition() } + }; + } + + // Equals + if (char === '=') { + this.advance(); + return { + type: TokenType.EQUALS, + value: '=', + range: { start, end: this.getPosition() } + }; + } + + // Word (instruction or string) + // Save atLineStart before reading the word since readWord will change it + const wasAtLineStart = this.atLineStart; + const word = this.readWord(); + const upperWord = word.toUpperCase(); + + if (INSTRUCTIONS.has(upperWord) && wasAtLineStart) { + return { + type: TokenType[upperWord as keyof typeof TokenType] || TokenType.STRING, + value: word, + range: { start, end: this.getPosition() } + }; + } + + return { + type: TokenType.STRING, + value: word, + range: { start, end: this.getPosition() } + }; + } + + /** + * Tokenize entire input + */ + tokenize(): Token[] { + const tokens: Token[] = []; + let token: Token; + do { + token = this.nextToken(); + tokens.push(token); + } while (token.type !== TokenType.EOF); + return tokens; + } +} diff --git a/packages/docker-parser/src/parser.ts b/packages/docker-parser/src/parser.ts new file mode 100644 index 0000000..347327a --- /dev/null +++ b/packages/docker-parser/src/parser.ts @@ -0,0 +1,1056 @@ +import { parse as parseBash } from 'bash-parser'; + +import { Lexer, Token, TokenType } from './lexer'; +import { + AddInstruction, + ArgInstruction, + CmdInstruction, + Comment, + CopyInstruction, + Dockerfile, + EntrypointInstruction, + EnvInstruction, + EnvVariable, + ExposeInstruction, + FromInstruction, + HealthcheckInstruction, + Instruction, + LabelEntry, + LabelInstruction, + MaintainerInstruction, + MountFlag, + OnbuildInstruction, + ParserDirective, + PortSpec, + RunInstruction, + ShellInstruction, + Stage, + StopsignalInstruction, + UserInstruction, + VolumeInstruction, + WorkdirInstruction, +} from './types'; + +/** + * Parser options + */ +export interface ParserOptions { + includeComments?: boolean; +} + +/** + * Dockerfile Parser + */ +export class Parser { + private tokens: Token[] = []; + private pos: number = 0; + private escapeChar: string = '\\'; + private options: ParserOptions; + + constructor(options: ParserOptions = {}) { + this.options = { + includeComments: true, + ...options + }; + } + + /** + * Parse Dockerfile source into AST + */ + parse(source: string): Dockerfile { + const lexer = new Lexer(source); + + // First pass: look for escape directive + const tempTokens = lexer.tokenize(); + for (const token of tempTokens) { + if (token.type === TokenType.DIRECTIVE) { + const [directive, value] = token.value.split('='); + if (directive === 'escape' && (value === '\\' || value === '`')) { + this.escapeChar = value; + break; + } + } + if (token.type !== TokenType.NEWLINE && token.type !== TokenType.WHITESPACE && token.type !== TokenType.COMMENT) { + break; + } + } + + // Second pass with correct escape character + const lexer2 = new Lexer(source); + lexer2.setEscapeChar(this.escapeChar); + this.tokens = lexer2.tokenize(); + this.pos = 0; + + const dockerfile: Dockerfile = { + type: 'Dockerfile', + directives: [], + stages: [], + comments: [] + }; + + // Parse directives first + while (!this.isAtEnd()) { + this.skipWhitespaceAndNewlines(); + if (this.isAtEnd()) break; + + const token = this.peek(); + if (token.type === TokenType.DIRECTIVE) { + dockerfile.directives.push(this.parseDirective()); + } else if (token.type === TokenType.COMMENT) { + if (this.options.includeComments) { + dockerfile.comments.push(this.parseComment()); + } else { + this.advance(); + } + } else { + break; + } + } + + // Parse stages and instructions + let currentStage: Stage | null = null; + + while (!this.isAtEnd()) { + this.skipWhitespaceAndNewlines(); + if (this.isAtEnd()) break; + + const token = this.peek(); + + if (token.type === TokenType.COMMENT) { + if (this.options.includeComments) { + dockerfile.comments.push(this.parseComment()); + } else { + this.advance(); + } + continue; + } + + if (token.type === TokenType.FROM) { + const from = this.parseFrom(); + currentStage = { + type: 'Stage', + from, + instructions: [], + name: from.name, + range: from.range + }; + dockerfile.stages.push(currentStage); + continue; + } + + // Parse other instructions + const instruction = this.parseInstruction(); + if (instruction) { + if (currentStage) { + currentStage.instructions.push(instruction); + } else { + // Instructions before first FROM (like ARG) + if (!dockerfile.stages.length) { + // Create a virtual stage for pre-FROM instructions + currentStage = { + type: 'Stage', + from: { + type: 'FromInstruction', + instruction: 'FROM', + image: 'scratch' + }, + instructions: [instruction] + }; + dockerfile.stages.push(currentStage); + } + } + } + } + + return dockerfile; + } + + /** + * Check if at end of tokens + */ + private isAtEnd(): boolean { + return this.pos >= this.tokens.length || this.peek().type === TokenType.EOF; + } + + /** + * Peek at current token + */ + private peek(offset: number = 0): Token { + const idx = this.pos + offset; + if (idx >= this.tokens.length) { + return this.tokens[this.tokens.length - 1]; + } + return this.tokens[idx]; + } + + /** + * Advance to next token + */ + private advance(): Token { + if (!this.isAtEnd()) { + this.pos++; + } + return this.tokens[this.pos - 1]; + } + + /** + * Skip whitespace and newlines + */ + private skipWhitespaceAndNewlines(): void { + while (!this.isAtEnd()) { + const token = this.peek(); + if (token.type === TokenType.WHITESPACE || token.type === TokenType.NEWLINE) { + this.advance(); + } else { + break; + } + } + } + + /** + * Skip whitespace only + */ + private skipWhitespace(): void { + while (!this.isAtEnd() && this.peek().type === TokenType.WHITESPACE) { + this.advance(); + } + } + + /** + * Collect arguments until newline + * Combines key=value tokens into single arguments + */ + private collectArguments(): string[] { + const args: string[] = []; + this.skipWhitespace(); + + while (!this.isAtEnd()) { + const token = this.peek(); + if (token.type === TokenType.NEWLINE || token.type === TokenType.EOF) { + break; + } + if (token.type === TokenType.WHITESPACE) { + this.advance(); + continue; + } + + // Check if this is a key=value pattern (STRING EQUALS STRING) + if (token.type === TokenType.STRING && this.peek(1).type === TokenType.EQUALS) { + let combined = token.value; + this.advance(); // STRING + combined += this.advance().value; // EQUALS + if (!this.isAtEnd() && this.peek().type !== TokenType.WHITESPACE && + this.peek().type !== TokenType.NEWLINE && this.peek().type !== TokenType.EOF) { + combined += this.advance().value; // value + } + args.push(combined); + } else { + args.push(token.value); + this.advance(); + } + } + + return args; + } + + /** + * Collect rest of line as single string + */ + private collectRestOfLine(): string { + const parts: string[] = []; + this.skipWhitespace(); + + while (!this.isAtEnd()) { + const token = this.peek(); + if (token.type === TokenType.NEWLINE || token.type === TokenType.EOF) { + break; + } + parts.push(token.value); + this.advance(); + } + + return parts.join('').trim(); + } + + /** + * Parse parser directive + */ + private parseDirective(): ParserDirective { + const token = this.advance(); + const [directive, value] = token.value.split('='); + return { + type: 'ParserDirective', + directive, + value, + range: token.range + }; + } + + /** + * Parse comment + */ + private parseComment(): Comment { + const token = this.advance(); + return { + type: 'Comment', + value: token.value, + range: token.range + }; + } + + /** + * Parse FROM instruction + */ + private parseFrom(): FromInstruction { + const startToken = this.advance(); // FROM + this.skipWhitespace(); + + let platform: string | undefined; + let image = ''; + let tag: string | undefined; + let digest: string | undefined; + let name: string | undefined; + + // Check for --platform flag + if (this.peek().type === TokenType.FLAG && this.peek().value.startsWith('--platform')) { + const flag = this.advance().value; + if (flag.includes('=')) { + platform = flag.split('=')[1]; + } else { + this.skipWhitespace(); + if (this.peek().type === TokenType.EQUALS) { + this.advance(); + } + this.skipWhitespace(); + platform = this.advance().value; + } + this.skipWhitespace(); + } + + // Parse image reference + const imageToken = this.advance(); + const imageRef = imageToken.value; + + // Parse image:tag@digest + if (imageRef.includes('@')) { + const [beforeDigest, digestPart] = imageRef.split('@'); + digest = digestPart; + if (beforeDigest.includes(':')) { + const [imagePart, tagPart] = beforeDigest.split(':'); + image = imagePart; + tag = tagPart; + } else { + image = beforeDigest; + } + } else if (imageRef.includes(':')) { + const [imagePart, tagPart] = imageRef.split(':'); + image = imagePart; + tag = tagPart; + } else { + image = imageRef; + } + + this.skipWhitespace(); + + // Check for AS alias + if (!this.isAtEnd() && this.peek().type === TokenType.STRING) { + const maybeAs = this.peek().value.toUpperCase(); + if (maybeAs === 'AS') { + this.advance(); // AS + this.skipWhitespace(); + name = this.advance().value; + } + } + + return { + type: 'FromInstruction', + instruction: 'FROM', + image, + tag, + digest, + name, + platform, + range: startToken.range + }; + } + + /** + * Parse instruction based on type + */ + private parseInstruction(): Instruction | null { + const token = this.peek(); + + switch (token.type) { + case TokenType.RUN: + return this.parseRun(); + case TokenType.CMD: + return this.parseCmd(); + case TokenType.ENTRYPOINT: + return this.parseEntrypoint(); + case TokenType.COPY: + return this.parseCopy(); + case TokenType.ADD: + return this.parseAdd(); + case TokenType.ENV: + return this.parseEnv(); + case TokenType.ARG: + return this.parseArg(); + case TokenType.WORKDIR: + return this.parseWorkdir(); + case TokenType.USER: + return this.parseUser(); + case TokenType.EXPOSE: + return this.parseExpose(); + case TokenType.VOLUME: + return this.parseVolume(); + case TokenType.LABEL: + return this.parseLabel(); + case TokenType.SHELL: + return this.parseShell(); + case TokenType.HEALTHCHECK: + return this.parseHealthcheck(); + case TokenType.STOPSIGNAL: + return this.parseStopsignal(); + case TokenType.ONBUILD: + return this.parseOnbuild(); + case TokenType.MAINTAINER: + return this.parseMaintainer(); + default: + // Skip unknown tokens + this.advance(); + return null; + } + } + + /** + * Parse RUN instruction + */ + private parseRun(): RunInstruction { + const startToken = this.advance(); // RUN + this.skipWhitespace(); + + const mounts: MountFlag[] = []; + let network: string | undefined; + let security: string | undefined; + + // Parse flags + while (this.peek().type === TokenType.FLAG) { + const flag = this.advance().value; + if (flag.startsWith('--mount')) { + mounts.push(this.parseMountFlag(flag)); + } else if (flag.startsWith('--network')) { + network = this.extractFlagValue(flag, 'network'); + } else if (flag.startsWith('--security')) { + security = this.extractFlagValue(flag, 'security'); + } + this.skipWhitespace(); + } + + // Check for JSON array (exec form) + if (this.peek().type === TokenType.JSON_ARRAY) { + const jsonStr = this.advance().value; + const command = JSON.parse(jsonStr) as string[]; + return { + type: 'RunInstruction', + instruction: 'RUN', + command, + isExec: true, + mount: mounts.length > 0 ? mounts : undefined, + network, + security, + range: startToken.range + }; + } + + // Shell form - also parse with bash-parser for heterogeneous AST + const command = this.collectRestOfLine(); + let bashAst: unknown; + try { + bashAst = parseBash(command); + } catch { + // If bash parsing fails, leave bashAst undefined + } + return { + type: 'RunInstruction', + instruction: 'RUN', + command, + isExec: false, + mount: mounts.length > 0 ? mounts : undefined, + network, + security, + bashAst, + range: startToken.range + }; + } + + /** + * Parse mount flag + */ + private parseMountFlag(flag: string): MountFlag { + const mount: MountFlag = { type: 'bind' }; + const value = flag.replace('--mount=', '').replace('--mount', ''); + + if (value) { + const parts = value.split(','); + for (const part of parts) { + const [key, val] = part.split('='); + switch (key) { + case 'type': + mount.type = val; + break; + case 'target': + case 'dst': + case 'destination': + mount.target = val; + break; + case 'source': + case 'src': + mount.source = val; + break; + case 'from': + mount.from = val; + break; + case 'id': + mount.id = val; + break; + case 'sharing': + mount.sharing = val; + break; + case 'readonly': + case 'ro': + mount.readonly = val !== 'false'; + break; + case 'required': + mount.required = val !== 'false'; + break; + case 'mode': + mount.mode = val; + break; + case 'uid': + mount.uid = val; + break; + case 'gid': + mount.gid = val; + break; + } + } + } + + return mount; + } + + /** + * Extract value from flag + */ + private extractFlagValue(flag: string, _name: string): string { + if (flag.includes('=')) { + return flag.split('=')[1]; + } + this.skipWhitespace(); + if (this.peek().type === TokenType.EQUALS) { + this.advance(); + this.skipWhitespace(); + } + return this.advance().value; + } + + /** + * Parse CMD instruction + */ + private parseCmd(): CmdInstruction { + const startToken = this.advance(); // CMD + this.skipWhitespace(); + + if (this.peek().type === TokenType.JSON_ARRAY) { + const jsonStr = this.advance().value; + const command = JSON.parse(jsonStr) as string[]; + return { + type: 'CmdInstruction', + instruction: 'CMD', + command, + isExec: true, + range: startToken.range + }; + } + + const command = this.collectRestOfLine(); + return { + type: 'CmdInstruction', + instruction: 'CMD', + command, + isExec: false, + range: startToken.range + }; + } + + /** + * Parse ENTRYPOINT instruction + */ + private parseEntrypoint(): EntrypointInstruction { + const startToken = this.advance(); // ENTRYPOINT + this.skipWhitespace(); + + if (this.peek().type === TokenType.JSON_ARRAY) { + const jsonStr = this.advance().value; + const command = JSON.parse(jsonStr) as string[]; + return { + type: 'EntrypointInstruction', + instruction: 'ENTRYPOINT', + command, + isExec: true, + range: startToken.range + }; + } + + const command = this.collectRestOfLine(); + return { + type: 'EntrypointInstruction', + instruction: 'ENTRYPOINT', + command, + isExec: false, + range: startToken.range + }; + } + + /** + * Parse COPY instruction + */ + private parseCopy(): CopyInstruction { + const startToken = this.advance(); // COPY + this.skipWhitespace(); + + let from: string | undefined; + let chown: string | undefined; + let chmod: string | undefined; + let link: boolean | undefined; + let parents: boolean | undefined; + const exclude: string[] = []; + + // Parse flags + while (this.peek().type === TokenType.FLAG) { + const flag = this.advance().value; + if (flag.startsWith('--from')) { + from = this.extractFlagValue(flag, 'from'); + } else if (flag.startsWith('--chown')) { + chown = this.extractFlagValue(flag, 'chown'); + } else if (flag.startsWith('--chmod')) { + chmod = this.extractFlagValue(flag, 'chmod'); + } else if (flag === '--link') { + link = true; + } else if (flag === '--parents') { + parents = true; + } else if (flag.startsWith('--exclude')) { + exclude.push(this.extractFlagValue(flag, 'exclude')); + } + this.skipWhitespace(); + } + + const args = this.collectArguments(); + const destination = args.pop() || ''; + const sources = args; + + return { + type: 'CopyInstruction', + instruction: 'COPY', + sources, + destination, + from, + chown, + chmod, + link, + parents, + exclude: exclude.length > 0 ? exclude : undefined, + range: startToken.range + }; + } + + /** + * Parse ADD instruction + */ + private parseAdd(): AddInstruction { + const startToken = this.advance(); // ADD + this.skipWhitespace(); + + let chown: string | undefined; + let chmod: string | undefined; + let link: boolean | undefined; + let checksum: string | undefined; + let keepGitDir: boolean | undefined; + const exclude: string[] = []; + + // Parse flags + while (this.peek().type === TokenType.FLAG) { + const flag = this.advance().value; + if (flag.startsWith('--chown')) { + chown = this.extractFlagValue(flag, 'chown'); + } else if (flag.startsWith('--chmod')) { + chmod = this.extractFlagValue(flag, 'chmod'); + } else if (flag === '--link') { + link = true; + } else if (flag.startsWith('--checksum')) { + checksum = this.extractFlagValue(flag, 'checksum'); + } else if (flag === '--keep-git-dir') { + keepGitDir = true; + } else if (flag.startsWith('--exclude')) { + exclude.push(this.extractFlagValue(flag, 'exclude')); + } + this.skipWhitespace(); + } + + const args = this.collectArguments(); + const destination = args.pop() || ''; + const sources = args; + + return { + type: 'AddInstruction', + instruction: 'ADD', + sources, + destination, + chown, + chmod, + link, + checksum, + keepGitDir, + exclude: exclude.length > 0 ? exclude : undefined, + range: startToken.range + }; + } + + /** + * Parse ENV instruction + */ + private parseEnv(): EnvInstruction { + const startToken = this.advance(); // ENV + this.skipWhitespace(); + + const variables: EnvVariable[] = []; + const args = this.collectArguments(); + + // Check for key=value or key value format + if (args.length === 2 && !args[0].includes('=')) { + // Old format: ENV key value + variables.push({ key: args[0], value: args[1] }); + } else { + // New format: ENV key=value key2=value2 + for (const arg of args) { + if (arg.includes('=')) { + const eqIdx = arg.indexOf('='); + const key = arg.substring(0, eqIdx); + const value = arg.substring(eqIdx + 1); + variables.push({ key, value: this.unquote(value) }); + } + } + } + + return { + type: 'EnvInstruction', + instruction: 'ENV', + variables, + range: startToken.range + }; + } + + /** + * Parse ARG instruction + */ + private parseArg(): ArgInstruction { + const startToken = this.advance(); // ARG + this.skipWhitespace(); + + const arg = this.collectRestOfLine(); + let name: string; + let defaultValue: string | undefined; + + if (arg.includes('=')) { + const eqIdx = arg.indexOf('='); + name = arg.substring(0, eqIdx); + defaultValue = arg.substring(eqIdx + 1); + } else { + name = arg; + } + + return { + type: 'ArgInstruction', + instruction: 'ARG', + name, + defaultValue, + range: startToken.range + }; + } + + /** + * Parse WORKDIR instruction + */ + private parseWorkdir(): WorkdirInstruction { + const startToken = this.advance(); // WORKDIR + this.skipWhitespace(); + + const path = this.collectRestOfLine(); + + return { + type: 'WorkdirInstruction', + instruction: 'WORKDIR', + path, + range: startToken.range + }; + } + + /** + * Parse USER instruction + */ + private parseUser(): UserInstruction { + const startToken = this.advance(); // USER + this.skipWhitespace(); + + const userSpec = this.collectRestOfLine(); + let user: string; + let group: string | undefined; + + if (userSpec.includes(':')) { + [user, group] = userSpec.split(':'); + } else { + user = userSpec; + } + + return { + type: 'UserInstruction', + instruction: 'USER', + user, + group, + range: startToken.range + }; + } + + /** + * Parse EXPOSE instruction + */ + private parseExpose(): ExposeInstruction { + const startToken = this.advance(); // EXPOSE + this.skipWhitespace(); + + const args = this.collectArguments(); + const ports: PortSpec[] = []; + + for (const arg of args) { + if (arg.includes('/')) { + const [port, protocol] = arg.split('/'); + ports.push({ port, protocol: protocol as 'tcp' | 'udp' }); + } else { + ports.push({ port: arg }); + } + } + + return { + type: 'ExposeInstruction', + instruction: 'EXPOSE', + ports, + range: startToken.range + }; + } + + /** + * Parse VOLUME instruction + */ + private parseVolume(): VolumeInstruction { + const startToken = this.advance(); // VOLUME + this.skipWhitespace(); + + let paths: string[]; + + if (this.peek().type === TokenType.JSON_ARRAY) { + const jsonStr = this.advance().value; + paths = JSON.parse(jsonStr) as string[]; + } else { + paths = this.collectArguments(); + } + + return { + type: 'VolumeInstruction', + instruction: 'VOLUME', + paths, + range: startToken.range + }; + } + + /** + * Parse LABEL instruction + */ + private parseLabel(): LabelInstruction { + const startToken = this.advance(); // LABEL + this.skipWhitespace(); + + const labels: LabelEntry[] = []; + const args = this.collectArguments(); + + for (const arg of args) { + if (arg.includes('=')) { + const eqIdx = arg.indexOf('='); + const key = arg.substring(0, eqIdx); + const value = arg.substring(eqIdx + 1); + labels.push({ key, value: this.unquote(value) }); + } + } + + return { + type: 'LabelInstruction', + instruction: 'LABEL', + labels, + range: startToken.range + }; + } + + /** + * Parse SHELL instruction + */ + private parseShell(): ShellInstruction { + const startToken = this.advance(); // SHELL + this.skipWhitespace(); + + let shell: string[]; + + if (this.peek().type === TokenType.JSON_ARRAY) { + const jsonStr = this.advance().value; + shell = JSON.parse(jsonStr) as string[]; + } else { + shell = this.collectArguments(); + } + + return { + type: 'ShellInstruction', + instruction: 'SHELL', + shell, + range: startToken.range + }; + } + + /** + * Parse HEALTHCHECK instruction + */ + private parseHealthcheck(): HealthcheckInstruction { + const startToken = this.advance(); // HEALTHCHECK + this.skipWhitespace(); + + // Check for NONE + if (this.peek().type === TokenType.STRING && this.peek().value.toUpperCase() === 'NONE') { + this.advance(); + return { + type: 'HealthcheckInstruction', + instruction: 'HEALTHCHECK', + none: true, + range: startToken.range + }; + } + + let interval: string | undefined; + let timeout: string | undefined; + let startPeriod: string | undefined; + let startInterval: string | undefined; + let retries: number | undefined; + + // Parse flags + while (this.peek().type === TokenType.FLAG) { + const flag = this.advance().value; + if (flag.startsWith('--interval')) { + interval = this.extractFlagValue(flag, 'interval'); + } else if (flag.startsWith('--timeout')) { + timeout = this.extractFlagValue(flag, 'timeout'); + } else if (flag.startsWith('--start-period')) { + startPeriod = this.extractFlagValue(flag, 'start-period'); + } else if (flag.startsWith('--start-interval')) { + startInterval = this.extractFlagValue(flag, 'start-interval'); + } else if (flag.startsWith('--retries')) { + retries = parseInt(this.extractFlagValue(flag, 'retries'), 10); + } + this.skipWhitespace(); + } + + // Parse CMD (may be tokenized as STRING since it's not at line start) + let command: CmdInstruction | undefined; + if (this.peek().type === TokenType.CMD || + (this.peek().type === TokenType.STRING && this.peek().value.toUpperCase() === 'CMD')) { + command = this.parseCmd(); + } + + return { + type: 'HealthcheckInstruction', + instruction: 'HEALTHCHECK', + interval, + timeout, + startPeriod, + startInterval, + retries, + command, + range: startToken.range + }; + } + + /** + * Parse STOPSIGNAL instruction + */ + private parseStopsignal(): StopsignalInstruction { + const startToken = this.advance(); // STOPSIGNAL + this.skipWhitespace(); + + const signal = this.collectRestOfLine(); + + return { + type: 'StopsignalInstruction', + instruction: 'STOPSIGNAL', + signal, + range: startToken.range + }; + } + + /** + * Parse ONBUILD instruction + */ + private parseOnbuild(): OnbuildInstruction { + const startToken = this.advance(); // ONBUILD + this.skipWhitespace(); + + const trigger = this.parseInstruction(); + + return { + type: 'OnbuildInstruction', + instruction: 'ONBUILD', + trigger: trigger!, + range: startToken.range + }; + } + + /** + * Parse MAINTAINER instruction (deprecated) + */ + private parseMaintainer(): MaintainerInstruction { + const startToken = this.advance(); // MAINTAINER + this.skipWhitespace(); + + const maintainer = this.collectRestOfLine(); + + return { + type: 'MaintainerInstruction', + instruction: 'MAINTAINER', + maintainer, + range: startToken.range + }; + } + + /** + * Remove quotes from string + */ + private unquote(str: string): string { + if ((str.startsWith('"') && str.endsWith('"')) || + (str.startsWith("'") && str.endsWith("'"))) { + return str.slice(1, -1); + } + return str; + } +} + +/** + * Parse Dockerfile source into AST + */ +export function parse(source: string, options?: ParserOptions): Dockerfile { + const parser = new Parser(options); + return parser.parse(source); +} diff --git a/packages/docker-parser/src/types.ts b/packages/docker-parser/src/types.ts new file mode 100644 index 0000000..a958239 --- /dev/null +++ b/packages/docker-parser/src/types.ts @@ -0,0 +1,338 @@ +/** + * Position in source code + */ +export interface Position { + line: number; + column: number; + offset: number; +} + +/** + * Range in source code + */ +export interface Range { + start: Position; + end: Position; +} + +/** + * Base node interface + */ +export interface BaseNode { + type: string; + range?: Range; +} + +/** + * Dockerfile AST root node + */ +export interface Dockerfile extends BaseNode { + type: 'Dockerfile'; + directives: ParserDirective[]; + stages: Stage[]; + comments: Comment[]; +} + +/** + * Parser directive (e.g., # escape=\ or # syntax=docker/dockerfile:1) + */ +export interface ParserDirective extends BaseNode { + type: 'ParserDirective'; + directive: string; + value: string; +} + +/** + * Build stage (starts with FROM) + */ +export interface Stage extends BaseNode { + type: 'Stage'; + from: FromInstruction; + instructions: Instruction[]; + name?: string; +} + +/** + * Comment node + */ +export interface Comment extends BaseNode { + type: 'Comment'; + value: string; +} + +/** + * Base instruction interface + */ +export interface BaseInstruction extends BaseNode { + instruction: string; +} + +/** + * FROM instruction + */ +export interface FromInstruction extends BaseInstruction { + type: 'FromInstruction'; + instruction: 'FROM'; + image: string; + tag?: string; + digest?: string; + name?: string; + platform?: string; +} + +/** + * RUN instruction + * When isExec is false (shell form), bashAst contains the parsed bash AST + */ +export interface RunInstruction extends BaseInstruction { + type: 'RunInstruction'; + instruction: 'RUN'; + command: string | string[]; + isExec: boolean; + mount?: MountFlag[]; + network?: string; + security?: string; + bashAst?: unknown; // Bash Script AST from bash-parser (heterogeneous parsing) +} + +/** + * Mount flag for RUN instruction + */ +export interface MountFlag { + type: string; + target?: string; + source?: string; + from?: string; + id?: string; + sharing?: string; + readonly?: boolean; + required?: boolean; + mode?: string; + uid?: string; + gid?: string; +} + +/** + * CMD instruction + */ +export interface CmdInstruction extends BaseInstruction { + type: 'CmdInstruction'; + instruction: 'CMD'; + command: string | string[]; + isExec: boolean; +} + +/** + * ENTRYPOINT instruction + */ +export interface EntrypointInstruction extends BaseInstruction { + type: 'EntrypointInstruction'; + instruction: 'ENTRYPOINT'; + command: string | string[]; + isExec: boolean; +} + +/** + * COPY instruction + */ +export interface CopyInstruction extends BaseInstruction { + type: 'CopyInstruction'; + instruction: 'COPY'; + sources: string[]; + destination: string; + from?: string; + chown?: string; + chmod?: string; + link?: boolean; + parents?: boolean; + exclude?: string[]; +} + +/** + * ADD instruction + */ +export interface AddInstruction extends BaseInstruction { + type: 'AddInstruction'; + instruction: 'ADD'; + sources: string[]; + destination: string; + chown?: string; + chmod?: string; + link?: boolean; + checksum?: string; + keepGitDir?: boolean; + exclude?: string[]; +} + +/** + * ENV instruction + */ +export interface EnvInstruction extends BaseInstruction { + type: 'EnvInstruction'; + instruction: 'ENV'; + variables: EnvVariable[]; +} + +/** + * Environment variable + */ +export interface EnvVariable { + key: string; + value: string; +} + +/** + * ARG instruction + */ +export interface ArgInstruction extends BaseInstruction { + type: 'ArgInstruction'; + instruction: 'ARG'; + name: string; + defaultValue?: string; +} + +/** + * WORKDIR instruction + */ +export interface WorkdirInstruction extends BaseInstruction { + type: 'WorkdirInstruction'; + instruction: 'WORKDIR'; + path: string; +} + +/** + * USER instruction + */ +export interface UserInstruction extends BaseInstruction { + type: 'UserInstruction'; + instruction: 'USER'; + user: string; + group?: string; +} + +/** + * EXPOSE instruction + */ +export interface ExposeInstruction extends BaseInstruction { + type: 'ExposeInstruction'; + instruction: 'EXPOSE'; + ports: PortSpec[]; +} + +/** + * Port specification + */ +export interface PortSpec { + port: number | string; + protocol?: 'tcp' | 'udp'; +} + +/** + * VOLUME instruction + */ +export interface VolumeInstruction extends BaseInstruction { + type: 'VolumeInstruction'; + instruction: 'VOLUME'; + paths: string[]; +} + +/** + * LABEL instruction + */ +export interface LabelInstruction extends BaseInstruction { + type: 'LabelInstruction'; + instruction: 'LABEL'; + labels: LabelEntry[]; +} + +/** + * Label entry + */ +export interface LabelEntry { + key: string; + value: string; +} + +/** + * SHELL instruction + */ +export interface ShellInstruction extends BaseInstruction { + type: 'ShellInstruction'; + instruction: 'SHELL'; + shell: string[]; +} + +/** + * HEALTHCHECK instruction + */ +export interface HealthcheckInstruction extends BaseInstruction { + type: 'HealthcheckInstruction'; + instruction: 'HEALTHCHECK'; + none?: boolean; + interval?: string; + timeout?: string; + startPeriod?: string; + startInterval?: string; + retries?: number; + command?: CmdInstruction; +} + +/** + * STOPSIGNAL instruction + */ +export interface StopsignalInstruction extends BaseInstruction { + type: 'StopsignalInstruction'; + instruction: 'STOPSIGNAL'; + signal: string; +} + +/** + * ONBUILD instruction + */ +export interface OnbuildInstruction extends BaseInstruction { + type: 'OnbuildInstruction'; + instruction: 'ONBUILD'; + trigger: Instruction; +} + +/** + * MAINTAINER instruction (deprecated) + */ +export interface MaintainerInstruction extends BaseInstruction { + type: 'MaintainerInstruction'; + instruction: 'MAINTAINER'; + maintainer: string; +} + +/** + * Union type for all instructions + */ +export type Instruction = + | FromInstruction + | RunInstruction + | CmdInstruction + | EntrypointInstruction + | CopyInstruction + | AddInstruction + | EnvInstruction + | ArgInstruction + | WorkdirInstruction + | UserInstruction + | ExposeInstruction + | VolumeInstruction + | LabelInstruction + | ShellInstruction + | HealthcheckInstruction + | StopsignalInstruction + | OnbuildInstruction + | MaintainerInstruction; + +/** + * Union type for all AST nodes + */ +export type Node = + | Dockerfile + | ParserDirective + | Stage + | Comment + | Instruction; diff --git a/packages/docker-parser/test-utils/index.ts b/packages/docker-parser/test-utils/index.ts new file mode 100644 index 0000000..83b0a81 --- /dev/null +++ b/packages/docker-parser/test-utils/index.ts @@ -0,0 +1,112 @@ +import { readFileSync } from 'fs'; +import * as path from 'path'; + +import { cleanTree } from '../src/clean'; +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; +import { Dockerfile } from '../src/types'; + +/** + * Test utilities for docker-parser + */ +export class TestUtils { + /** + * Parse Dockerfile source + */ + parse(source: string): Dockerfile { + return parse(source); + } + + /** + * Deparse AST to source + */ + deparse(ast: Dockerfile): string { + return deparse(ast); + } + + /** + * Clean AST for comparison + */ + clean(ast: Dockerfile): Dockerfile { + return cleanTree(ast); + } + + /** + * Round-trip test: parse -> deparse -> parse -> compare cleaned ASTs + */ + async expectAstMatch(testName: string, source: string): Promise { + // First parse + const ast1 = this.parse(source); + + // Deparse + const deparsed = this.deparse(ast1); + + // Second parse + const ast2 = this.parse(deparsed); + + // Clean both ASTs + const clean1 = this.clean(ast1); + const clean2 = this.clean(ast2); + + // Compare + const json1 = JSON.stringify(clean1, null, 2); + const json2 = JSON.stringify(clean2, null, 2); + + if (json1 !== json2) { + const diff = require('jest-diff').diff(json1, json2); + throw new Error( + `AST mismatch for ${testName}:\n` + + `Original source:\n${source}\n\n` + + `Deparsed:\n${deparsed}\n\n` + + `AST diff:\n${diff}` + ); + } + } +} + +/** + * Fixture-based test utilities + */ +export class FixtureTestUtils extends TestUtils { + private fixtures: Record; + + constructor() { + super(); + const GENERATED_JSON = path.join(__dirname, '../../__fixtures__/generated/generated.json'); + try { + this.fixtures = JSON.parse(readFileSync(GENERATED_JSON, 'utf-8')); + } catch { + this.fixtures = {}; + } + } + + /** + * Get test entries, optionally filtered + */ + getTestEntries(filters: string[]): [string, string][] { + if (filters.length === 0) { + return Object.entries(this.fixtures); + } + return Object.entries(this.fixtures).filter(([relPath]) => + filters.includes(relPath) + ); + } + + /** + * Run fixture tests + */ + async runFixtureTests(filters: string[]): Promise { + if (filters.length === 0) { + console.log('no filters provided, skipping tests.'); + return; + } + const entries = this.getTestEntries(filters); + for (const [relativePath, source] of entries) { + try { + await this.expectAstMatch(relativePath, source); + } catch (err) { + throw err; + } + } + } +} diff --git a/packages/docker-parser/tsconfig.esm.json b/packages/docker-parser/tsconfig.esm.json new file mode 100644 index 0000000..aa8f22b --- /dev/null +++ b/packages/docker-parser/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ES2020", + "outDir": "dist/esm" + } +} diff --git a/packages/docker-parser/tsconfig.json b/packages/docker-parser/tsconfig.json new file mode 100644 index 0000000..c1ce63f --- /dev/null +++ b/packages/docker-parser/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "__tests__"] +} diff --git a/packages/dockerjs/LICENSE b/packages/dockerjs/LICENSE deleted file mode 100644 index 153d3dd..0000000 --- a/packages/dockerjs/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2026 Dan Lynch - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/dockerjs/Makefile b/packages/dockerjs/Makefile deleted file mode 100644 index 9d7c062..0000000 --- a/packages/dockerjs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -EXTENSION = dockerjs -DATA = sql/dockerjs--0.0.1.sql - -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) - \ No newline at end of file diff --git a/packages/dockerjs/README.md b/packages/dockerjs/README.md deleted file mode 100644 index e464521..0000000 --- a/packages/dockerjs/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# dockerjs - -

- -

- -

- - - - -

- -## Developing - -This is a pnpm module within a pnpm workspace. - -```sh -# Install dependencies -pnpm install - -# Run tests -pnpm test - -# Run tests in watch mode -pnpm test:watch - -# Build the module -pnpm build - -# Lint the code -pnpm lint -``` - -## Credits - -**Built by the [Constructive](https://constructive.io) team. If you like our work, contribute on [GitHub](https://github.com/constructive-io).** - -## Disclaimer - -AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. - -No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/packages/dockerjs/__tests__/basic.test.ts b/packages/dockerjs/__tests__/basic.test.ts deleted file mode 100644 index 5dbacab..0000000 --- a/packages/dockerjs/__tests__/basic.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('first test', () => { - it('should pass', () => { - expect(1 + 1).toBe(2); - }); -}); - diff --git a/packages/dockerjs/dockerjs.control b/packages/dockerjs/dockerjs.control deleted file mode 100644 index 4ab109f..0000000 --- a/packages/dockerjs/dockerjs.control +++ /dev/null @@ -1,7 +0,0 @@ -# dockerjs extension -comment = 'dockerjs extension' -default_version = '0.0.1' -module_pathname = '$libdir/dockerjs' -requires = 'uuid-ossp,plpgsql' -relocatable = false -superuser = false diff --git a/packages/dockerjs/jest.config.js b/packages/dockerjs/jest.config.js deleted file mode 100644 index 10b083a..0000000 --- a/packages/dockerjs/jest.config.js +++ /dev/null @@ -1,20 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - - // Match both __tests__ and colocated test files - testMatch: ['**/?(*.)+(test|spec).{ts,tsx,js,jsx}'], - - // Ignore build artifacts and type declarations - testPathIgnorePatterns: ['/dist/', '\\.d\\.ts$'], - modulePathIgnorePatterns: ['/dist/'], - - // Only watch js, ts, and sql files - watchPathIgnorePatterns: [ - '/dist/', - '/node_modules/' - ], - - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', 'sql'], -}; \ No newline at end of file diff --git a/packages/dockerjs/package.json b/packages/dockerjs/package.json deleted file mode 100644 index abd93b2..0000000 --- a/packages/dockerjs/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "dockerjs", - "version": "0.0.1", - "author": "Dan Lynch ", - "description": "dockerjs", - "homepage": "https://github.com/pyramation/dockerjs", - "license": "MIT", - "publishConfig": { - "access": "public", - "directory": "dist" - }, - "repository": { - "type": "git", - "url": "https://github.com/pyramation/dockerjs" - }, - "bugs": { - "url": "https://github.com/pyramation/dockerjs/issues" - }, - "scripts": { - "clean": "makage clean", - "prepack": "npm run build", - "build": "makage build", - "build:dev": "makage build --dev", - "lint": "eslint . --fix", - "test": "jest --passWithNoTests", - "test:watch": "jest --watch" - }, - "keywords": [], - "devDependencies": { - "makage": "0.1.9" - } -} diff --git a/packages/dockerjs/pgpm.plan b/packages/dockerjs/pgpm.plan deleted file mode 100644 index 542f229..0000000 --- a/packages/dockerjs/pgpm.plan +++ /dev/null @@ -1,3 +0,0 @@ -%syntax-version=1.0.0 -%project=dockerjs -%uri=dockerjs \ No newline at end of file diff --git a/pgpm.json b/pgpm.json deleted file mode 100644 index e20d138..0000000 --- a/pgpm.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "packages": [ - "packages/*", - "extensions/*" - ] -} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..eab3fda --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7321 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 + '@types/node': + specifier: ^20.12.7 + version: 20.19.27 + '@typescript-eslint/eslint-plugin': + specifier: ^8.47.0 + version: 8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: ^8.47.0 + version: 8.52.0(eslint@9.39.2)(typescript@5.9.3) + eslint: + specifier: ^9.39.1 + version: 9.39.2 + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@9.39.2) + eslint-plugin-simple-import-sort: + specifier: ^12.1.0 + version: 12.1.1(eslint@9.39.2) + eslint-plugin-unused-imports: + specifier: ^4.0.0 + version: 4.3.0(@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) + jest: + specifier: ^30.2.0 + version: 30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + jest-diff: + specifier: 30.2.0 + version: 30.2.0 + lerna: + specifier: ^8.2.4 + version: 8.2.4(@types/node@20.19.27)(encoding@0.1.13) + makage: + specifier: ^0.1.8 + version: 0.1.10 + prettier: + specifier: ^3.0.2 + version: 3.7.4 + ts-jest: + specifier: ^29.4.6 + version: 29.4.6(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)))(typescript@5.9.3) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + typescript: + specifier: ^5.1.6 + version: 5.9.3 + + packages/bash-parser: + devDependencies: + makage: + specifier: ^0.1.8 + version: 0.1.10 + publishDirectory: dist + + packages/docker-parser: + dependencies: + bash-parser: + specifier: workspace:* + version: link:../bash-parser/dist + devDependencies: + makage: + specifier: ^0.1.8 + version: 0.1.10 + publishDirectory: dist + +packages: + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@hutson/parse-repository-url@3.0.2': + resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} + engines: {node: '>=6.9.0'} + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/string-locale-compare@1.1.0': + resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@30.2.0': + resolution: {integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/core@30.2.0': + resolution: {integrity: sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment@30.2.0': + resolution: {integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.2.0': + resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect@30.2.0': + resolution: {integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/fake-timers@30.2.0': + resolution: {integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.2.0': + resolution: {integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.2.0': + resolution: {integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.2.0': + resolution: {integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-result@30.2.0': + resolution: {integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-sequencer@30.2.0': + resolution: {integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/transform@30.2.0': + resolution: {integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@30.2.0': + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@lerna/create@8.2.4': + resolution: {integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==} + engines: {node: '>=18.0.0'} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@napi-rs/wasm-runtime@0.2.4': + resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + + '@npmcli/agent@2.2.2': + resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/arborist@7.5.4': + resolution: {integrity: sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==} + engines: {node: ^16.14.0 || >=18.0.0} + hasBin: true + + '@npmcli/fs@3.1.1': + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/git@5.0.8': + resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/installed-package-contents@2.1.0': + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + '@npmcli/map-workspaces@3.0.6': + resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/metavuln-calculator@7.1.1': + resolution: {integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/name-from-folder@2.0.0': + resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/node-gyp@3.0.0': + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/package-json@5.2.0': + resolution: {integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/promise-spawn@7.0.2': + resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/query@3.1.0': + resolution: {integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/redact@2.0.1': + resolution: {integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/run-script@8.1.0': + resolution: {integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@nx/devkit@20.8.3': + resolution: {integrity: sha512-5lbfJ6ICFOiGeirldQOU5fQ/W/VQ8L3dfWnmHG4UgpWSLoK/YFdRf4lTB4rS0aDXsBL0gyWABz3sZGLPGNYnPA==} + peerDependencies: + nx: '>= 19 <= 21' + + '@nx/nx-darwin-arm64@20.8.3': + resolution: {integrity: sha512-BeYnPAcnaerg6q+qR0bAb0nebwwrsvm4STSVqqVlaqLmmQpU3Bfpx44CEa5d6T9b0V11ZqVE/bkmRhMqhUcrhw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@nx/nx-darwin-x64@20.8.3': + resolution: {integrity: sha512-RIFg1VkQ4jhI+ErqEZuIeGBcJGD8t+u9J5CdQBDIASd8QRhtudBkiYLYCJb+qaQly09G7nVfxuyItlS2uRW3qA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@nx/nx-freebsd-x64@20.8.3': + resolution: {integrity: sha512-boQTgMUdnqpZhHMrV/xgnp/dTg5dfxw8I4d16NBwmW4j+Sez7zi/dydgsJpfZsj8TicOHvPu6KK4W5wzp82NPw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@nx/nx-linux-arm-gnueabihf@20.8.3': + resolution: {integrity: sha512-wpiNyY1igx1rLN3EsTLum2lDtblFijdBZB9/9u/6UDub4z9CaQ4yaC4h9n5v7yFYILwfL44YTsQKzrE+iv0y1Q==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@nx/nx-linux-arm64-gnu@20.8.3': + resolution: {integrity: sha512-nbi/eZtJfWxuDwdUCiP+VJolFubtrz6XxVtB26eMAkODnREOKELHZtMOrlm8JBZCdtWCvTqibq9Az74XsqSfdA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nx/nx-linux-arm64-musl@20.8.3': + resolution: {integrity: sha512-LTTGzI8YVPlF1v0YlVf+exM+1q7rpsiUbjTTHJcfHFRU5t4BsiZD54K19Y1UBg1XFx5cwhEaIomSmJ88RwPPVQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nx/nx-linux-x64-gnu@20.8.3': + resolution: {integrity: sha512-SlA4GtXvQbSzSIWLgiIiLBOjdINPOUR/im+TUbaEMZ8wiGrOY8cnk0PVt95TIQJVBeXBCeb5HnoY0lHJpMOODg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nx/nx-linux-x64-musl@20.8.3': + resolution: {integrity: sha512-MNzkEwPktp5SQH9dJDH2wP9hgG9LsBDhKJXJfKw6sUI/6qz5+/aAjFziKy+zBnhU4AO1yXt5qEWzR8lDcIriVQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nx/nx-win32-arm64-msvc@20.8.3': + resolution: {integrity: sha512-qUV7CyXKwRCM/lkvyS6Xa1MqgAuK5da6w27RAehh7LATBUKn1I4/M7DGn6L7ERCxpZuh1TrDz9pUzEy0R+Ekkg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@nx/nx-win32-x64-msvc@20.8.3': + resolution: {integrity: sha512-gX1G8u6W6EPX6PO/wv07+B++UHyCHBXyVWXITA3Kv6HoSajOxIa2Kk1rv1iDQGmX1WWxBaj3bUyYJAFBDITe4w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + + '@octokit/core@5.2.2': + resolution: {integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@9.0.6': + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.1.1': + resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@24.2.0': + resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} + + '@octokit/plugin-enterprise-rest@6.0.1': + resolution: {integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==} + + '@octokit/plugin-paginate-rest@11.4.4-cjs.2': + resolution: {integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-request-log@4.0.1': + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1': + resolution: {integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5 + + '@octokit/request-error@5.1.1': + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} + engines: {node: '>= 18'} + + '@octokit/request@8.4.1': + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} + engines: {node: '>= 18'} + + '@octokit/rest@20.1.2': + resolution: {integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==} + engines: {node: '>= 18'} + + '@octokit/types@13.10.0': + resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@sigstore/bundle@2.3.2': + resolution: {integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/core@1.1.0': + resolution: {integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/protobuf-specs@0.3.3': + resolution: {integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/sign@2.3.2': + resolution: {integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/tuf@2.3.4': + resolution: {integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/verify@1.2.1': + resolution: {integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinclair/typebox@0.34.47': + resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@13.0.5': + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tufjs/canonical-json@2.0.0': + resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@tufjs/models@2.0.1': + resolution: {integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/minimatch@3.0.5': + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node@20.19.27': + resolution: {integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@typescript-eslint/eslint-plugin@8.52.0': + resolution: {integrity: sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.52.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.52.0': + resolution: {integrity: sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.52.0': + resolution: {integrity: sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.52.0': + resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.52.0': + resolution: {integrity: sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.52.0': + resolution: {integrity: sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.52.0': + resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.52.0': + resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.52.0': + resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.52.0': + resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + '@yarnpkg/parsers@3.0.2': + resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} + engines: {node: '>=18.12.0'} + + '@zkochan/js-yaml@0.0.7': + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} + hasBin: true + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + add-stream@1.0.0: + resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-differ@3.0.0: + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + arrify@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + babel-jest@30.2.0: + resolution: {integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-0 + + babel-plugin-istanbul@7.0.1: + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} + + babel-plugin-jest-hoist@30.2.0: + resolution: {integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} + peerDependencies: + '@babel/core': ^7.0.0 || ^8.0.0-0 + + babel-preset-jest@30.2.0: + resolution: {integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.9.14: + resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==} + hasBin: true + + before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + + bin-links@4.0.4: + resolution: {integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + byte-size@8.1.1: + resolution: {integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==} + engines: {node: '>=12.17'} + + cacache@18.0.4: + resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001763: + resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==} + + chalk@4.1.0: + resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} + engines: {node: '>=10'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} + + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.6.1: + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + cmd-shim@6.0.3: + resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.3: + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + columnify@1.6.0: + resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==} + engines: {node: '>=8.0.0'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-core@5.0.1: + resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} + engines: {node: '>=14'} + + conventional-changelog-preset-loader@3.0.0: + resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} + engines: {node: '>=14'} + + conventional-changelog-writer@6.0.1: + resolution: {integrity: sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==} + engines: {node: '>=14'} + hasBin: true + + conventional-commits-filter@3.0.0: + resolution: {integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==} + engines: {node: '>=14'} + + conventional-commits-parser@4.0.0: + resolution: {integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==} + engines: {node: '>=14'} + hasBin: true + + conventional-recommended-bump@7.0.1: + resolution: {integrity: sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==} + engines: {node: '>=14'} + hasBin: true + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + dargs@7.0.0: + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} + + dateformat@3.0.3: + resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + dedent@1.7.1: + resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + + detect-indent@5.0.0: + resolution: {integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==} + engines: {node: '>=4'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.267: + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + envinfo@7.13.0: + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} + engines: {node: '>=4'} + hasBin: true + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-simple-import-sort@12.1.1: + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} + peerDependencies: + eslint: '>=5.0.0' + + eslint-plugin-unused-imports@4.3.0: + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + execa@5.0.0: + resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==} + engines: {node: '>=10'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + + expect@30.2.0: + resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + front-matter@4.0.2: + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@11.3.3: + resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} + engines: {node: '>=14.14'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-pkg-repo@4.2.1: + resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} + engines: {node: '>=6.9.0'} + hasBin: true + + get-port@5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.0: + resolution: {integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==} + engines: {node: '>=10'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + git-raw-commits@3.0.0: + resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} + engines: {node: '>=14'} + hasBin: true + + git-remote-origin-url@2.0.0: + resolution: {integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==} + engines: {node: '>=4'} + + git-semver-tags@5.0.1: + resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} + engines: {node: '>=14'} + hasBin: true + + git-up@7.0.0: + resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} + + git-url-parse@14.0.0: + resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==} + + gitconfiglocal@1.0.0: + resolution: {integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + hasBin: true + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore-walk@6.0.5: + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + init-package-json@6.0.3: + resolution: {integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==} + engines: {node: ^16.14.0 || >=18.0.0} + + inquirer@8.2.7: + resolution: {integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==} + engines: {node: '>=12.0.0'} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-ssh@1.4.1: + resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} + + is-stream@2.0.0: + resolution: {integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==} + engines: {node: '>=8'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-text-path@1.0.1: + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@30.2.0: + resolution: {integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-circus@30.2.0: + resolution: {integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-cli@30.2.0: + resolution: {integrity: sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@30.2.0: + resolution: {integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-diff@30.2.0: + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-docblock@30.2.0: + resolution: {integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-each@30.2.0: + resolution: {integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-environment-node@30.2.0: + resolution: {integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@30.2.0: + resolution: {integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-leak-detector@30.2.0: + resolution: {integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.2.0: + resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@30.2.0: + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.2.0: + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@30.0.1: + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@30.2.0: + resolution: {integrity: sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve@30.2.0: + resolution: {integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runner@30.2.0: + resolution: {integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runtime@30.2.0: + resolution: {integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-snapshot@30.2.0: + resolution: {integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.2.0: + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-validate@30.2.0: + resolution: {integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-watcher@30.2.0: + resolution: {integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-worker@30.2.0: + resolution: {integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest@30.2.0: + resolution: {integrity: sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stringify-nice@1.1.4: + resolution: {integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + just-diff-apply@5.5.0: + resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} + + just-diff@6.0.2: + resolution: {integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + lerna@8.2.4: + resolution: {integrity: sha512-0gaVWDIVT7fLfprfwpYcQajb7dBJv3EGavjG7zvJ+TmGx3/wovl5GklnSwM2/WeE0Z2wrIz7ndWhBcDUHVjOcQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + libnpmaccess@8.0.6: + resolution: {integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==} + engines: {node: ^16.14.0 || >=18.0.0} + + libnpmpublish@9.0.9: + resolution: {integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==} + engines: {node: ^16.14.0 || >=18.0.0} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lines-and-columns@2.0.3: + resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + load-json-file@4.0.0: + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} + + load-json-file@6.2.0: + resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==} + engines: {node: '>=8'} + + locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.ismatch@4.4.0: + resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + makage@0.1.10: + resolution: {integrity: sha512-IQKuRbHOrDgVNlydle+XRO5iMyaozBq4Bb9vhEzwxtvzyk08JkQo5qpfFRep0dSum53gECdX2gBoTmkWDHIfJA==} + hasBin: true + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + make-fetch-happen@13.0.1: + resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} + engines: {node: ^16.14.0 || >=18.0.0} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + meow@8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} + + minimatch@3.0.5: + resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@2.0.1: + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass-fetch@3.0.5: + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + modify-values@1.0.1: + resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} + engines: {node: '>=0.10.0'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multimatch@5.0.0: + resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} + engines: {node: '>=10'} + + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-fetch@2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp@10.3.1: + resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==} + engines: {node: ^16.14.0 || >=18.0.0} + hasBin: true + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-machine-id@1.1.12: + resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-bundled@3.0.1: + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-package-arg@11.0.2: + resolution: {integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-packlist@8.0.2: + resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-pick-manifest@9.1.0: + resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-registry-fetch@17.1.0: + resolution: {integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nx@20.8.3: + resolution: {integrity: sha512-8w815WSMWar3A/LFzwtmEY+E8cVW62lMiFuPDXje+C8O8hFndfvscP56QHNMn2Zdhz3q0+BZUe+se4Em1BKYdA==} + hasBin: true + peerDependencies: + '@swc-node/register': ^1.8.0 + '@swc/core': ^1.3.85 + peerDependenciesMeta: + '@swc-node/register': + optional: true + '@swc/core': + optional: true + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@5.3.0: + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-limit@1.3.0: + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map-series@2.1.0: + resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==} + engines: {node: '>=8'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-pipe@3.1.0: + resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} + engines: {node: '>=8'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-reduce@2.1.0: + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-try@1.0.0: + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + p-waterfall@2.1.1: + resolution: {integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==} + engines: {node: '>=8'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + pacote@18.0.6: + resolution: {integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==} + engines: {node: ^16.14.0 || >=18.0.0} + hasBin: true + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-conflict-json@3.0.1: + resolution: {integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-path@7.1.0: + resolution: {integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==} + + parse-url@8.1.0: + resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} + + path-type@3.0.0: + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pify@5.0.0: + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.7.4: + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + proggy@2.0.0: + resolution: {integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + promise-all-reject-late@1.0.1: + resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} + + promise-call-limit@3.0.2: + resolution: {integrity: sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + promzard@1.0.2: + resolution: {integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + protocols@2.0.2: + resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + read-cmd-shim@4.0.0: + resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-pkg-up@3.0.0: + resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} + engines: {node: '>=4'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@3.0.0: + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + read@3.0.1: + resolution: {integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + rimraf@4.4.1: + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} + hasBin: true + + run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sigstore@2.3.1: + resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + sort-keys@2.0.0: + resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} + engines: {node: '>=4'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.22: + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + + split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + + split@1.0.1: + resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + temp-dir@1.0.0: + resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} + engines: {node: '>=4'} + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-extensions@1.9.0: + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} + + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + treeverse@3.0.0: + resolution: {integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-jest@29.4.6: + resolution: {integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 || ^30.0.0 + '@jest/types': ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + esbuild: '*' + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tuf-js@2.2.1: + resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} + engines: {node: ^16.14.0 || >=18.0.0} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.4.1: + resolution: {integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==} + engines: {node: '>=6'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + upath@2.0.1: + resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} + engines: {node: '>=4'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + walk-up-path@3.0.1: + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@2.4.3: + resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + write-json-file@3.2.0: + resolution: {integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==} + engines: {node: '>=6'} + + write-pkg@4.0.0: + resolution: {integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==} + engines: {node: '>=8'} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.5': {} + + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + + '@babel/traverse@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bcoe/v8-coverage@0.2.3': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)': + dependencies: + eslint: 9.39.2 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.3': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.2': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@hutson/parse-repository-url@3.0.2': {} + + '@inquirer/external-editor@1.0.3(@types/node@20.19.27)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 20.19.27 + + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/string-locale-compare@1.1.0': {} + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.2 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@30.2.0': + dependencies: + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + chalk: 4.1.2 + jest-message-util: 30.2.0 + jest-util: 30.2.0 + slash: 3.0.0 + + '@jest/core@30.2.0(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3))': + dependencies: + '@jest/console': 30.2.0 + '@jest/pattern': 30.0.1 + '@jest/reporters': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.3.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-changed-files: 30.2.0 + jest-config: 30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + jest-haste-map: 30.2.0 + jest-message-util: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-resolve-dependencies: 30.2.0 + jest-runner: 30.2.0 + jest-runtime: 30.2.0 + jest-snapshot: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 + jest-watcher: 30.2.0 + micromatch: 4.0.8 + pretty-format: 30.2.0 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + '@jest/diff-sequences@30.0.1': {} + + '@jest/environment@30.2.0': + dependencies: + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + jest-mock: 30.2.0 + + '@jest/expect-utils@30.2.0': + dependencies: + '@jest/get-type': 30.1.0 + + '@jest/expect@30.2.0': + dependencies: + expect: 30.2.0 + jest-snapshot: 30.2.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@30.2.0': + dependencies: + '@jest/types': 30.2.0 + '@sinonjs/fake-timers': 13.0.5 + '@types/node': 20.19.27 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 + + '@jest/get-type@30.1.0': {} + + '@jest/globals@30.2.0': + dependencies: + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/types': 30.2.0 + jest-mock: 30.2.0 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.0.1': + dependencies: + '@types/node': 20.19.27 + jest-regex-util: 30.0.1 + + '@jest/reporters@30.2.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 20.19.27 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit-x: 0.2.2 + glob: 10.5.0 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + jest-message-util: 30.2.0 + jest-util: 30.2.0 + jest-worker: 30.2.0 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.47 + + '@jest/snapshot-utils@30.2.0': + dependencies: + '@jest/types': 30.2.0 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 + + '@jest/source-map@30.0.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@30.2.0': + dependencies: + '@jest/console': 30.2.0 + '@jest/types': 30.2.0 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + + '@jest/test-sequencer@30.2.0': + dependencies: + '@jest/test-result': 30.2.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.2.0 + slash: 3.0.0 + + '@jest/transform@30.2.0': + dependencies: + '@babel/core': 7.28.5 + '@jest/types': 30.2.0 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 7.0.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.2.0 + jest-regex-util: 30.0.1 + jest-util: 30.2.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + + '@jest/types@30.2.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 20.19.27 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lerna/create@8.2.4(@types/node@20.19.27)(encoding@0.1.13)(typescript@5.9.3)': + dependencies: + '@npmcli/arborist': 7.5.4 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 + '@nx/devkit': 20.8.3(nx@20.8.3) + '@octokit/plugin-enterprise-rest': 6.0.1 + '@octokit/rest': 20.1.2 + aproba: 2.0.0 + byte-size: 8.1.1 + chalk: 4.1.0 + clone-deep: 4.0.1 + cmd-shim: 6.0.3 + color-support: 1.1.3 + columnify: 1.6.0 + console-control-strings: 1.1.0 + conventional-changelog-core: 5.0.1 + conventional-recommended-bump: 7.0.1 + cosmiconfig: 9.0.0(typescript@5.9.3) + dedent: 1.5.3 + execa: 5.0.0 + fs-extra: 11.3.3 + get-stream: 6.0.0 + git-url-parse: 14.0.0 + glob-parent: 6.0.2 + graceful-fs: 4.2.11 + has-unicode: 2.0.1 + ini: 1.3.8 + init-package-json: 6.0.3 + inquirer: 8.2.7(@types/node@20.19.27) + is-ci: 3.0.1 + is-stream: 2.0.0 + js-yaml: 4.1.0 + libnpmpublish: 9.0.9 + load-json-file: 6.2.0 + make-dir: 4.0.0 + minimatch: 3.0.5 + multimatch: 5.0.0 + node-fetch: 2.6.7(encoding@0.1.13) + npm-package-arg: 11.0.2 + npm-packlist: 8.0.2 + npm-registry-fetch: 17.1.0 + nx: 20.8.3 + p-map: 4.0.0 + p-map-series: 2.1.0 + p-queue: 6.6.2 + p-reduce: 2.1.0 + pacote: 18.0.6 + pify: 5.0.0 + read-cmd-shim: 4.0.0 + resolve-from: 5.0.0 + rimraf: 4.4.1 + semver: 7.7.3 + set-blocking: 2.0.0 + signal-exit: 3.0.7 + slash: 3.0.0 + ssri: 10.0.6 + string-width: 4.2.3 + tar: 6.2.1 + temp-dir: 1.0.0 + through: 2.3.8 + tinyglobby: 0.2.12 + upath: 2.0.1 + uuid: 10.0.0 + validate-npm-package-license: 3.0.4 + validate-npm-package-name: 5.0.1 + wide-align: 1.1.5 + write-file-atomic: 5.0.1 + write-pkg: 4.0.0 + yargs: 17.7.2 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - '@swc-node/register' + - '@swc/core' + - '@types/node' + - babel-plugin-macros + - bluebird + - debug + - encoding + - supports-color + - typescript + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@napi-rs/wasm-runtime@0.2.4': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.9.0 + + '@npmcli/agent@2.2.2': + dependencies: + agent-base: 7.1.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 10.4.3 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + '@npmcli/arborist@7.5.4': + dependencies: + '@isaacs/string-locale-compare': 1.1.0 + '@npmcli/fs': 3.1.1 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/map-workspaces': 3.0.6 + '@npmcli/metavuln-calculator': 7.1.1 + '@npmcli/name-from-folder': 2.0.0 + '@npmcli/node-gyp': 3.0.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/query': 3.1.0 + '@npmcli/redact': 2.0.1 + '@npmcli/run-script': 8.1.0 + bin-links: 4.0.4 + cacache: 18.0.4 + common-ancestor-path: 1.0.1 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + json-stringify-nice: 1.1.4 + lru-cache: 10.4.3 + minimatch: 9.0.5 + nopt: 7.2.1 + npm-install-checks: 6.3.0 + npm-package-arg: 11.0.2 + npm-pick-manifest: 9.1.0 + npm-registry-fetch: 17.1.0 + pacote: 18.0.6 + parse-conflict-json: 3.0.1 + proc-log: 4.2.0 + proggy: 2.0.0 + promise-all-reject-late: 1.0.1 + promise-call-limit: 3.0.2 + read-package-json-fast: 3.0.2 + semver: 7.7.3 + ssri: 10.0.6 + treeverse: 3.0.0 + walk-up-path: 3.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + '@npmcli/fs@3.1.1': + dependencies: + semver: 7.7.3 + + '@npmcli/git@5.0.8': + dependencies: + '@npmcli/promise-spawn': 7.0.2 + ini: 4.1.3 + lru-cache: 10.4.3 + npm-pick-manifest: 9.1.0 + proc-log: 4.2.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.7.3 + which: 4.0.0 + transitivePeerDependencies: + - bluebird + + '@npmcli/installed-package-contents@2.1.0': + dependencies: + npm-bundled: 3.0.1 + npm-normalize-package-bin: 3.0.1 + + '@npmcli/map-workspaces@3.0.6': + dependencies: + '@npmcli/name-from-folder': 2.0.0 + glob: 10.5.0 + minimatch: 9.0.5 + read-package-json-fast: 3.0.2 + + '@npmcli/metavuln-calculator@7.1.1': + dependencies: + cacache: 18.0.4 + json-parse-even-better-errors: 3.0.2 + pacote: 18.0.6 + proc-log: 4.2.0 + semver: 7.7.3 + transitivePeerDependencies: + - bluebird + - supports-color + + '@npmcli/name-from-folder@2.0.0': {} + + '@npmcli/node-gyp@3.0.0': {} + + '@npmcli/package-json@5.2.0': + dependencies: + '@npmcli/git': 5.0.8 + glob: 10.5.0 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + normalize-package-data: 6.0.2 + proc-log: 4.2.0 + semver: 7.7.3 + transitivePeerDependencies: + - bluebird + + '@npmcli/promise-spawn@7.0.2': + dependencies: + which: 4.0.0 + + '@npmcli/query@3.1.0': + dependencies: + postcss-selector-parser: 6.1.2 + + '@npmcli/redact@2.0.1': {} + + '@npmcli/run-script@8.1.0': + dependencies: + '@npmcli/node-gyp': 3.0.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/promise-spawn': 7.0.2 + node-gyp: 10.3.1 + proc-log: 4.2.0 + which: 4.0.0 + transitivePeerDependencies: + - bluebird + - supports-color + + '@nx/devkit@20.8.3(nx@20.8.3)': + dependencies: + ejs: 3.1.10 + enquirer: 2.3.6 + ignore: 5.3.2 + minimatch: 9.0.3 + nx: 20.8.3 + semver: 7.7.3 + tmp: 0.2.5 + tslib: 2.8.1 + yargs-parser: 21.1.1 + + '@nx/nx-darwin-arm64@20.8.3': + optional: true + + '@nx/nx-darwin-x64@20.8.3': + optional: true + + '@nx/nx-freebsd-x64@20.8.3': + optional: true + + '@nx/nx-linux-arm-gnueabihf@20.8.3': + optional: true + + '@nx/nx-linux-arm64-gnu@20.8.3': + optional: true + + '@nx/nx-linux-arm64-musl@20.8.3': + optional: true + + '@nx/nx-linux-x64-gnu@20.8.3': + optional: true + + '@nx/nx-linux-x64-musl@20.8.3': + optional: true + + '@nx/nx-win32-arm64-msvc@20.8.3': + optional: true + + '@nx/nx-win32-x64-msvc@20.8.3': + optional: true + + '@octokit/auth-token@4.0.0': {} + + '@octokit/core@5.2.2': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.1 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + + '@octokit/endpoint@9.0.6': + dependencies: + '@octokit/types': 13.10.0 + universal-user-agent: 6.0.1 + + '@octokit/graphql@7.1.1': + dependencies: + '@octokit/request': 8.4.1 + '@octokit/types': 13.10.0 + universal-user-agent: 6.0.1 + + '@octokit/openapi-types@24.2.0': {} + + '@octokit/plugin-enterprise-rest@6.0.1': {} + + '@octokit/plugin-paginate-rest@11.4.4-cjs.2(@octokit/core@5.2.2)': + dependencies: + '@octokit/core': 5.2.2 + '@octokit/types': 13.10.0 + + '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.2)': + dependencies: + '@octokit/core': 5.2.2 + + '@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1(@octokit/core@5.2.2)': + dependencies: + '@octokit/core': 5.2.2 + '@octokit/types': 13.10.0 + + '@octokit/request-error@5.1.1': + dependencies: + '@octokit/types': 13.10.0 + deprecation: 2.3.1 + once: 1.4.0 + + '@octokit/request@8.4.1': + dependencies: + '@octokit/endpoint': 9.0.6 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 + universal-user-agent: 6.0.1 + + '@octokit/rest@20.1.2': + dependencies: + '@octokit/core': 5.2.2 + '@octokit/plugin-paginate-rest': 11.4.4-cjs.2(@octokit/core@5.2.2) + '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.2) + '@octokit/plugin-rest-endpoint-methods': 13.3.2-cjs.1(@octokit/core@5.2.2) + + '@octokit/types@13.10.0': + dependencies: + '@octokit/openapi-types': 24.2.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.2.9': {} + + '@sigstore/bundle@2.3.2': + dependencies: + '@sigstore/protobuf-specs': 0.3.3 + + '@sigstore/core@1.1.0': {} + + '@sigstore/protobuf-specs@0.3.3': {} + + '@sigstore/sign@2.3.2': + dependencies: + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 + make-fetch-happen: 13.0.1 + proc-log: 4.2.0 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@sigstore/tuf@2.3.4': + dependencies: + '@sigstore/protobuf-specs': 0.3.3 + tuf-js: 2.2.1 + transitivePeerDependencies: + - supports-color + + '@sigstore/verify@1.2.1': + dependencies: + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 + + '@sinclair/typebox@0.27.8': {} + + '@sinclair/typebox@0.34.47': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@13.0.5': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tufjs/canonical-json@2.0.0': {} + + '@tufjs/models@2.0.1': + dependencies: + '@tufjs/canonical-json': 2.0.0 + minimatch: 9.0.5 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@tybys/wasm-util@0.9.0': + dependencies: + tslib: 2.8.1 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.28.5 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.28.5 + + '@types/estree@1.0.8': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.2.0 + pretty-format: 30.2.0 + + '@types/json-schema@7.0.15': {} + + '@types/minimatch@3.0.5': {} + + '@types/minimist@1.2.5': {} + + '@types/node@20.19.27': + dependencies: + undici-types: 6.21.0 + + '@types/normalize-package-data@2.4.4': {} + + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/type-utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.52.0 + eslint: 9.39.2 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.52.0 + debug: 4.4.3 + eslint: 9.39.2 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.52.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3) + '@typescript-eslint/types': 8.52.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.52.0': + dependencies: + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/visitor-keys': 8.52.0 + + '@typescript-eslint/tsconfig-utils@8.52.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.52.0(eslint@9.39.2)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.2 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.52.0': {} + + '@typescript-eslint/typescript-estree@8.52.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.52.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3) + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/visitor-keys': 8.52.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.3 + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.52.0(eslint@9.39.2)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + eslint: 9.39.2 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.52.0': + dependencies: + '@typescript-eslint/types': 8.52.0 + eslint-visitor-keys: 4.2.1 + + '@ungap/structured-clone@1.3.0': {} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + '@yarnpkg/lockfile@1.1.0': {} + + '@yarnpkg/parsers@3.0.2': + dependencies: + js-yaml: 3.14.2 + tslib: 2.8.1 + + '@zkochan/js-yaml@0.0.7': + dependencies: + argparse: 2.0.1 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + abbrev@2.0.0: {} + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + add-stream@1.0.0: {} + + agent-base@7.1.4: {} + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-colors@4.1.3: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + aproba@2.0.0: {} + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-differ@3.0.0: {} + + array-ify@1.0.0: {} + + array-union@2.1.0: {} + + arrify@1.0.1: {} + + arrify@2.0.1: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-jest@30.2.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@jest/transform': 30.2.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 7.0.1 + babel-preset-jest: 30.2.0(@babel/core@7.28.5) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@7.0.1: + dependencies: + '@babel/helper-plugin-utils': 7.27.1 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 6.0.3 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@30.2.0: + dependencies: + '@types/babel__core': 7.20.5 + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.5) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) + + babel-preset-jest@30.2.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + babel-plugin-jest-hoist: 30.2.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.9.14: {} + + before-after-hook@2.2.3: {} + + bin-links@4.0.4: + dependencies: + cmd-shim: 6.0.3 + npm-normalize-package-bin: 3.0.1 + read-cmd-shim: 4.0.0 + write-file-atomic: 5.0.1 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.14 + caniuse-lite: 1.0.30001763 + electron-to-chromium: 1.5.267 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + byte-size@8.1.1: {} + + cacache@18.0.4: + dependencies: + '@npmcli/fs': 3.1.1 + fs-minipass: 3.0.3 + glob: 10.5.0 + lru-cache: 10.4.3 + minipass: 7.1.2 + minipass-collect: 2.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + ssri: 10.0.6 + tar: 6.2.1 + unique-filename: 3.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + camelcase-keys@6.2.2: + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001763: {} + + chalk@4.1.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + char-regex@1.0.2: {} + + chardet@2.1.1: {} + + chownr@2.0.0: {} + + ci-info@3.9.0: {} + + ci-info@4.3.1: {} + + cjs-module-lexer@2.2.0: {} + + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.6.1: {} + + cli-spinners@2.9.2: {} + + cli-width@3.0.0: {} + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-deep@4.0.1: + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + + clone@1.0.4: {} + + cmd-shim@6.0.3: {} + + co@4.6.0: {} + + collect-v8-coverage@1.0.3: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + columnify@1.6.0: + dependencies: + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + common-ancestor-path@1.0.1: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + concat-map@0.0.1: {} + + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + + console-control-strings@1.1.0: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-core@5.0.1: + dependencies: + add-stream: 1.0.0 + conventional-changelog-writer: 6.0.1 + conventional-commits-parser: 4.0.0 + dateformat: 3.0.3 + get-pkg-repo: 4.2.1 + git-raw-commits: 3.0.0 + git-remote-origin-url: 2.0.0 + git-semver-tags: 5.0.1 + normalize-package-data: 3.0.3 + read-pkg: 3.0.0 + read-pkg-up: 3.0.0 + + conventional-changelog-preset-loader@3.0.0: {} + + conventional-changelog-writer@6.0.1: + dependencies: + conventional-commits-filter: 3.0.0 + dateformat: 3.0.3 + handlebars: 4.7.8 + json-stringify-safe: 5.0.1 + meow: 8.1.2 + semver: 7.7.3 + split: 1.0.1 + + conventional-commits-filter@3.0.0: + dependencies: + lodash.ismatch: 4.4.0 + modify-values: 1.0.1 + + conventional-commits-parser@4.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 1.0.1 + meow: 8.1.2 + split2: 3.2.2 + + conventional-recommended-bump@7.0.1: + dependencies: + concat-stream: 2.0.0 + conventional-changelog-preset-loader: 3.0.0 + conventional-commits-filter: 3.0.0 + conventional-commits-parser: 4.0.0 + git-raw-commits: 3.0.0 + git-semver-tags: 5.0.1 + meow: 8.1.2 + + convert-source-map@2.0.0: {} + + core-util-is@1.0.3: {} + + cosmiconfig@9.0.0(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + + create-require@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + dargs@7.0.0: {} + + dateformat@3.0.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize-keys@1.1.1: + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + + decamelize@1.2.0: {} + + dedent@1.5.3: {} + + dedent@1.7.1: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-lazy-prop@2.0.0: {} + + delayed-stream@1.0.0: {} + + deprecation@2.3.1: {} + + detect-indent@5.0.0: {} + + detect-newline@3.1.0: {} + + diff-sequences@29.6.3: {} + + diff@4.0.2: {} + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.4.7 + + dotenv@16.4.7: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-to-chromium@1.5.267: {} + + emittery@0.13.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + enquirer@2.3.6: + dependencies: + ansi-colors: 4.1.3 + + env-paths@2.2.1: {} + + envinfo@7.13.0: {} + + err-code@2.0.3: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.8(eslint@9.39.2): + dependencies: + eslint: 9.39.2 + + eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.2): + dependencies: + eslint: 9.39.2 + + eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): + dependencies: + eslint: 9.39.2 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.2: + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + eventemitter3@4.0.7: {} + + execa@5.0.0: + dependencies: + cross-spawn: 7.0.6 + 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.7 + strip-final-newline: 2.0.0 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit-x@0.2.2: {} + + expect@30.2.0: + dependencies: + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 + + exponential-backoff@3.1.3: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@2.1.0: + dependencies: + locate-path: 2.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat@5.0.2: {} + + flatted@3.3.3: {} + + follow-redirects@1.15.11: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + front-matter@4.0.2: + dependencies: + js-yaml: 3.14.2 + + fs-constants@1.0.0: {} + + fs-extra@11.3.3: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs-minipass@3.0.3: + dependencies: + minipass: 7.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-package-type@0.1.0: {} + + get-pkg-repo@4.2.1: + dependencies: + '@hutson/parse-repository-url': 3.0.2 + hosted-git-info: 4.1.0 + through2: 2.0.5 + yargs: 16.2.0 + + get-port@5.1.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@6.0.0: {} + + get-stream@6.0.1: {} + + git-raw-commits@3.0.0: + dependencies: + dargs: 7.0.0 + meow: 8.1.2 + split2: 3.2.2 + + git-remote-origin-url@2.0.0: + dependencies: + gitconfiglocal: 1.0.0 + pify: 2.3.0 + + git-semver-tags@5.0.1: + dependencies: + meow: 8.1.2 + semver: 7.7.3 + + git-up@7.0.0: + dependencies: + is-ssh: 1.4.1 + parse-url: 8.1.0 + + git-url-parse@14.0.0: + dependencies: + git-up: 7.0.0 + + gitconfiglocal@1.0.0: + dependencies: + ini: 1.3.8 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.1 + minimatch: 10.1.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@9.3.5: + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.11.1 + + globals@14.0.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + hard-rejection@2.1.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@2.8.9: {} + + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + html-escaper@2.0.2: {} + + http-cache-semantics@4.2.0: {} + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore-walk@6.0.5: + dependencies: + minimatch: 9.0.5 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.1.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.3: {} + + init-package-json@6.0.3: + dependencies: + '@npmcli/package-json': 5.2.0 + npm-package-arg: 11.0.2 + promzard: 1.0.2 + read: 3.0.1 + semver: 7.7.3 + validate-npm-package-license: 3.0.4 + validate-npm-package-name: 5.0.1 + transitivePeerDependencies: + - bluebird + + inquirer@8.2.7(@types/node@20.19.27): + dependencies: + '@inquirer/external-editor': 1.0.3(@types/node@20.19.27) + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.2 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 6.2.0 + transitivePeerDependencies: + - '@types/node' + + ip-address@10.1.0: {} + + is-arrayish@0.2.1: {} + + is-ci@3.0.1: + dependencies: + ci-info: 3.9.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@1.0.0: {} + + is-lambda@1.0.1: {} + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-plain-obj@1.1.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-ssh@1.4.1: + dependencies: + protocols: 2.0.2 + + is-stream@2.0.0: {} + + is-stream@2.0.1: {} + + is-text-path@1.0.1: + dependencies: + text-extensions: 1.9.0 + + is-unicode-supported@0.1.0: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + + isexe@2.0.0: {} + + isexe@3.1.1: {} + + isobject@3.0.1: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.28.5 + '@babel/parser': 7.28.5 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.1.1: + dependencies: + '@isaacs/cliui': 8.0.2 + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 + + jest-changed-files@30.2.0: + dependencies: + execa: 5.1.1 + jest-util: 30.2.0 + p-limit: 3.1.0 + + jest-circus@30.2.0: + dependencies: + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.1 + is-generator-fn: 2.1.0 + jest-each: 30.2.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-runtime: 30.2.0 + jest-snapshot: 30.2.0 + jest-util: 30.2.0 + p-limit: 3.1.0 + pretty-format: 30.2.0 + pure-rand: 7.0.1 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)): + dependencies: + '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + jest-util: 30.2.0 + jest-validate: 30.2.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jest-config@30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)): + dependencies: + '@babel/core': 7.28.5 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.2.0 + '@jest/types': 30.2.0 + babel-jest: 30.2.0(@babel/core@7.28.5) + chalk: 4.1.2 + ci-info: 4.3.1 + deepmerge: 4.3.1 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-circus: 30.2.0 + jest-docblock: 30.2.0 + jest-environment-node: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-runner: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 30.2.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.19.27 + ts-node: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.0 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-diff@30.2.0: + dependencies: + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.2.0 + + jest-docblock@30.2.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 + chalk: 4.1.2 + jest-util: 30.2.0 + pretty-format: 30.2.0 + + jest-environment-node@30.2.0: + dependencies: + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + jest-mock: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 30.0.1 + jest-util: 30.2.0 + jest-worker: 30.2.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + pretty-format: 30.2.0 + + jest-matcher-utils@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + jest-diff: 30.2.0 + pretty-format: 30.2.0 + + jest-message-util@30.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 30.2.0 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 30.2.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + jest-util: 30.2.0 + + jest-pnp-resolver@1.2.3(jest-resolve@30.2.0): + optionalDependencies: + jest-resolve: 30.2.0 + + jest-regex-util@30.0.1: {} + + jest-resolve-dependencies@30.2.0: + dependencies: + jest-regex-util: 30.0.1 + jest-snapshot: 30.2.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@30.2.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.2.0 + jest-pnp-resolver: 1.2.3(jest-resolve@30.2.0) + jest-util: 30.2.0 + jest-validate: 30.2.0 + slash: 3.0.0 + unrs-resolver: 1.11.1 + + jest-runner@30.2.0: + dependencies: + '@jest/console': 30.2.0 + '@jest/environment': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + chalk: 4.1.2 + emittery: 0.13.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-docblock: 30.2.0 + jest-environment-node: 30.2.0 + jest-haste-map: 30.2.0 + jest-leak-detector: 30.2.0 + jest-message-util: 30.2.0 + jest-resolve: 30.2.0 + jest-runtime: 30.2.0 + jest-util: 30.2.0 + jest-watcher: 30.2.0 + jest-worker: 30.2.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@30.2.0: + dependencies: + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/globals': 30.2.0 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + chalk: 4.1.2 + cjs-module-lexer: 2.2.0 + collect-v8-coverage: 1.0.3 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.2.0 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-snapshot: 30.2.0 + jest-util: 30.2.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@30.2.0: + dependencies: + '@babel/core': 7.28.5 + '@babel/generator': 7.28.5 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/types': 7.28.5 + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + '@jest/snapshot-utils': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + chalk: 4.1.2 + expect: 30.2.0 + graceful-fs: 4.2.11 + jest-diff: 30.2.0 + jest-matcher-utils: 30.2.0 + jest-message-util: 30.2.0 + jest-util: 30.2.0 + pretty-format: 30.2.0 + semver: 7.7.3 + synckit: 0.11.11 + transitivePeerDependencies: + - supports-color + + jest-util@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + chalk: 4.1.2 + ci-info: 4.3.1 + graceful-fs: 4.2.11 + picomatch: 4.0.3 + + jest-validate@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.2.0 + + jest-watcher@30.2.0: + dependencies: + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 20.19.27 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 30.2.0 + string-length: 4.0.2 + + jest-worker@30.2.0: + dependencies: + '@types/node': 20.19.27 + '@ungap/structured-clone': 1.3.0 + jest-util: 30.2.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)): + dependencies: + '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + '@jest/types': 30.2.0 + import-local: 3.2.0 + jest-cli: 30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-better-errors@1.0.2: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@3.0.2: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json-stringify-nice@1.1.4: {} + + json-stringify-safe@5.0.1: {} + + json5@2.2.3: {} + + jsonc-parser@3.2.0: {} + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + just-diff-apply@5.5.0: {} + + just-diff@6.0.2: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + lerna@8.2.4(@types/node@20.19.27)(encoding@0.1.13): + dependencies: + '@lerna/create': 8.2.4(@types/node@20.19.27)(encoding@0.1.13)(typescript@5.9.3) + '@npmcli/arborist': 7.5.4 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 + '@nx/devkit': 20.8.3(nx@20.8.3) + '@octokit/plugin-enterprise-rest': 6.0.1 + '@octokit/rest': 20.1.2 + aproba: 2.0.0 + byte-size: 8.1.1 + chalk: 4.1.0 + clone-deep: 4.0.1 + cmd-shim: 6.0.3 + color-support: 1.1.3 + columnify: 1.6.0 + console-control-strings: 1.1.0 + conventional-changelog-angular: 7.0.0 + conventional-changelog-core: 5.0.1 + conventional-recommended-bump: 7.0.1 + cosmiconfig: 9.0.0(typescript@5.9.3) + dedent: 1.5.3 + envinfo: 7.13.0 + execa: 5.0.0 + fs-extra: 11.3.3 + get-port: 5.1.1 + get-stream: 6.0.0 + git-url-parse: 14.0.0 + glob-parent: 6.0.2 + graceful-fs: 4.2.11 + has-unicode: 2.0.1 + import-local: 3.1.0 + ini: 1.3.8 + init-package-json: 6.0.3 + inquirer: 8.2.7(@types/node@20.19.27) + is-ci: 3.0.1 + is-stream: 2.0.0 + jest-diff: 29.7.0 + js-yaml: 4.1.0 + libnpmaccess: 8.0.6 + libnpmpublish: 9.0.9 + load-json-file: 6.2.0 + make-dir: 4.0.0 + minimatch: 3.0.5 + multimatch: 5.0.0 + node-fetch: 2.6.7(encoding@0.1.13) + npm-package-arg: 11.0.2 + npm-packlist: 8.0.2 + npm-registry-fetch: 17.1.0 + nx: 20.8.3 + p-map: 4.0.0 + p-map-series: 2.1.0 + p-pipe: 3.1.0 + p-queue: 6.6.2 + p-reduce: 2.1.0 + p-waterfall: 2.1.1 + pacote: 18.0.6 + pify: 5.0.0 + read-cmd-shim: 4.0.0 + resolve-from: 5.0.0 + rimraf: 4.4.1 + semver: 7.7.3 + set-blocking: 2.0.0 + signal-exit: 3.0.7 + slash: 3.0.0 + ssri: 10.0.6 + string-width: 4.2.3 + tar: 6.2.1 + temp-dir: 1.0.0 + through: 2.3.8 + tinyglobby: 0.2.12 + typescript: 5.9.3 + upath: 2.0.1 + uuid: 10.0.0 + validate-npm-package-license: 3.0.4 + validate-npm-package-name: 5.0.1 + wide-align: 1.1.5 + write-file-atomic: 5.0.1 + write-pkg: 4.0.0 + yargs: 17.7.2 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - '@swc-node/register' + - '@swc/core' + - '@types/node' + - babel-plugin-macros + - bluebird + - debug + - encoding + - supports-color + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + libnpmaccess@8.0.6: + dependencies: + npm-package-arg: 11.0.2 + npm-registry-fetch: 17.1.0 + transitivePeerDependencies: + - supports-color + + libnpmpublish@9.0.9: + dependencies: + ci-info: 4.3.1 + normalize-package-data: 6.0.2 + npm-package-arg: 11.0.2 + npm-registry-fetch: 17.1.0 + proc-log: 4.2.0 + semver: 7.7.3 + sigstore: 2.3.1 + ssri: 10.0.6 + transitivePeerDependencies: + - supports-color + + lines-and-columns@1.2.4: {} + + lines-and-columns@2.0.3: {} + + load-json-file@4.0.0: + dependencies: + graceful-fs: 4.2.11 + parse-json: 4.0.0 + pify: 3.0.0 + strip-bom: 3.0.0 + + load-json-file@6.2.0: + dependencies: + graceful-fs: 4.2.11 + parse-json: 5.2.0 + strip-bom: 4.0.0 + type-fest: 0.6.0 + + locate-path@2.0.0: + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.ismatch@4.4.0: {} + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + lru-cache@10.4.3: {} + + lru-cache@11.2.4: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + makage@0.1.10: + dependencies: + glob: 11.1.0 + yaml: 2.8.2 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + + make-dir@4.0.0: + dependencies: + semver: 7.7.3 + + make-error@1.3.6: {} + + make-fetch-happen@13.0.1: + dependencies: + '@npmcli/agent': 2.2.2 + cacache: 18.0.4 + http-cache-semantics: 4.2.0 + is-lambda: 1.0.1 + minipass: 7.1.2 + minipass-fetch: 3.0.5 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + proc-log: 4.2.0 + promise-retry: 2.0.1 + ssri: 10.0.6 + transitivePeerDependencies: + - supports-color + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + map-obj@1.0.1: {} + + map-obj@4.3.0: {} + + math-intrinsics@1.1.0: {} + + meow@8.1.2: + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + + merge-stream@2.0.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@2.1.0: {} + + min-indent@1.0.1: {} + + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + + minimatch@3.0.5: + dependencies: + brace-expansion: 1.1.12 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + + minimatch@8.0.4: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist-options@4.1.0: + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + + minimist@1.2.8: {} + + minipass-collect@2.0.1: + dependencies: + minipass: 7.1.2 + + minipass-fetch@3.0.5: + dependencies: + minipass: 7.1.2 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@4.2.8: {} + + minipass@5.0.0: {} + + minipass@7.1.2: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@1.0.4: {} + + modify-values@1.0.1: {} + + ms@2.1.3: {} + + multimatch@5.0.0: + dependencies: + '@types/minimatch': 3.0.5 + array-differ: 3.0.0 + array-union: 2.1.0 + arrify: 2.0.1 + minimatch: 3.0.5 + + mute-stream@0.0.8: {} + + mute-stream@1.0.0: {} + + napi-postinstall@0.3.4: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + node-fetch@2.6.7(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-gyp@10.3.1: + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + glob: 10.5.0 + graceful-fs: 4.2.11 + make-fetch-happen: 13.0.1 + nopt: 7.2.1 + proc-log: 4.2.0 + semver: 7.7.3 + tar: 6.2.1 + which: 4.0.0 + transitivePeerDependencies: + - supports-color + + node-int64@0.4.0: {} + + node-machine-id@1.1.12: {} + + node-releases@2.0.27: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.11 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-package-data@3.0.3: + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.16.1 + semver: 7.7.3 + validate-npm-package-license: 3.0.4 + + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.3 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + npm-bundled@3.0.1: + dependencies: + npm-normalize-package-bin: 3.0.1 + + npm-install-checks@6.3.0: + dependencies: + semver: 7.7.3 + + npm-normalize-package-bin@3.0.1: {} + + npm-package-arg@11.0.2: + dependencies: + hosted-git-info: 7.0.2 + proc-log: 4.2.0 + semver: 7.7.3 + validate-npm-package-name: 5.0.1 + + npm-packlist@8.0.2: + dependencies: + ignore-walk: 6.0.5 + + npm-pick-manifest@9.1.0: + dependencies: + npm-install-checks: 6.3.0 + npm-normalize-package-bin: 3.0.1 + npm-package-arg: 11.0.2 + semver: 7.7.3 + + npm-registry-fetch@17.1.0: + dependencies: + '@npmcli/redact': 2.0.1 + jsonparse: 1.3.1 + make-fetch-happen: 13.0.1 + minipass: 7.1.2 + minipass-fetch: 3.0.5 + minizlib: 2.1.2 + npm-package-arg: 11.0.2 + proc-log: 4.2.0 + transitivePeerDependencies: + - supports-color + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nx@20.8.3: + dependencies: + '@napi-rs/wasm-runtime': 0.2.4 + '@yarnpkg/lockfile': 1.1.0 + '@yarnpkg/parsers': 3.0.2 + '@zkochan/js-yaml': 0.0.7 + axios: 1.13.2 + chalk: 4.1.0 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + cliui: 8.0.1 + dotenv: 16.4.7 + dotenv-expand: 11.0.7 + enquirer: 2.3.6 + figures: 3.2.0 + flat: 5.0.2 + front-matter: 4.0.2 + ignore: 5.3.2 + jest-diff: 29.7.0 + jsonc-parser: 3.2.0 + lines-and-columns: 2.0.3 + minimatch: 9.0.3 + node-machine-id: 1.1.12 + npm-run-path: 4.0.1 + open: 8.4.2 + ora: 5.3.0 + resolve.exports: 2.0.3 + semver: 7.7.3 + string-width: 4.2.3 + tar-stream: 2.2.0 + tmp: 0.2.5 + tsconfig-paths: 4.2.0 + tslib: 2.8.1 + yaml: 2.8.2 + yargs: 17.7.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@nx/nx-darwin-arm64': 20.8.3 + '@nx/nx-darwin-x64': 20.8.3 + '@nx/nx-freebsd-x64': 20.8.3 + '@nx/nx-linux-arm-gnueabihf': 20.8.3 + '@nx/nx-linux-arm64-gnu': 20.8.3 + '@nx/nx-linux-arm64-musl': 20.8.3 + '@nx/nx-linux-x64-gnu': 20.8.3 + '@nx/nx-linux-x64-musl': 20.8.3 + '@nx/nx-win32-arm64-msvc': 20.8.3 + '@nx/nx-win32-x64-msvc': 20.8.3 + transitivePeerDependencies: + - debug + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@5.3.0: + dependencies: + bl: 4.1.0 + chalk: 4.1.0 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + is-interactive: 1.0.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + p-finally@1.0.0: {} + + p-limit@1.3.0: + dependencies: + p-try: 1.0.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@2.0.0: + dependencies: + p-limit: 1.3.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map-series@2.1.0: {} + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-pipe@3.1.0: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-reduce@2.1.0: {} + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-try@1.0.0: {} + + p-try@2.2.0: {} + + p-waterfall@2.1.1: + dependencies: + p-reduce: 2.1.0 + + package-json-from-dist@1.0.1: {} + + pacote@18.0.6: + dependencies: + '@npmcli/git': 5.0.8 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/promise-spawn': 7.0.2 + '@npmcli/run-script': 8.1.0 + cacache: 18.0.4 + fs-minipass: 3.0.3 + minipass: 7.1.2 + npm-package-arg: 11.0.2 + npm-packlist: 8.0.2 + npm-pick-manifest: 9.1.0 + npm-registry-fetch: 17.1.0 + proc-log: 4.2.0 + promise-retry: 2.0.1 + sigstore: 2.3.1 + ssri: 10.0.6 + tar: 6.2.1 + transitivePeerDependencies: + - bluebird + - supports-color + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-conflict-json@3.0.1: + dependencies: + json-parse-even-better-errors: 3.0.2 + just-diff: 6.0.2 + just-diff-apply: 5.5.0 + + parse-json@4.0.0: + dependencies: + error-ex: 1.3.4 + json-parse-better-errors: 1.0.2 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-path@7.1.0: + dependencies: + protocols: 2.0.2 + + parse-url@8.1.0: + dependencies: + parse-path: 7.1.0 + + path-exists@3.0.0: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.4 + minipass: 7.1.2 + + path-type@3.0.0: + dependencies: + pify: 3.0.0 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pify@2.3.0: {} + + pify@3.0.0: {} + + pify@4.0.1: {} + + pify@5.0.0: {} + + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + prelude-ls@1.2.1: {} + + prettier@3.7.4: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + pretty-format@30.2.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + proc-log@4.2.0: {} + + process-nextick-args@2.0.1: {} + + proggy@2.0.0: {} + + promise-all-reject-late@1.0.1: {} + + promise-call-limit@3.0.2: {} + + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + promzard@1.0.2: + dependencies: + read: 3.0.1 + + protocols@2.0.2: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + pure-rand@7.0.1: {} + + quick-lru@4.0.1: {} + + react-is@18.3.1: {} + + read-cmd-shim@4.0.0: {} + + read-package-json-fast@3.0.2: + dependencies: + json-parse-even-better-errors: 3.0.2 + npm-normalize-package-bin: 3.0.1 + + read-pkg-up@3.0.0: + dependencies: + find-up: 2.1.0 + read-pkg: 3.0.0 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@3.0.0: + dependencies: + load-json-file: 4.0.0 + normalize-package-data: 2.5.0 + path-type: 3.0.0 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + read@3.0.1: + dependencies: + mute-stream: 1.0.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + require-directory@2.1.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve.exports@2.0.3: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + retry@0.12.0: {} + + rimraf@4.4.1: + dependencies: + glob: 9.3.5 + + run-async@2.4.1: {} + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.7.3: {} + + set-blocking@2.0.0: {} + + shallow-clone@3.0.1: + dependencies: + kind-of: 6.0.3 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sigstore@2.3.1: + dependencies: + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 + '@sigstore/sign': 2.3.2 + '@sigstore/tuf': 2.3.4 + '@sigstore/verify': 1.2.1 + transitivePeerDependencies: + - supports-color + + slash@3.0.0: {} + + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + + sort-keys@2.0.0: + dependencies: + is-plain-obj: 1.1.0 + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.22 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.22 + + spdx-license-ids@3.0.22: {} + + split2@3.2.2: + dependencies: + readable-stream: 3.6.2 + + split@1.0.1: + dependencies: + through: 2.3.8 + + sprintf-js@1.0.3: {} + + ssri@10.0.6: + dependencies: + minipass: 7.1.2 + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + synckit@0.11.11: + dependencies: + '@pkgr/core': 0.2.9 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + temp-dir@1.0.0: {} + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + text-extensions@1.9.0: {} + + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + + through@2.3.8: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tmp@0.2.5: {} + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tr46@0.0.3: {} + + treeverse@3.0.0: {} + + trim-newlines@3.0.1: {} + + ts-api-utils@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-jest@29.4.6(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)))(typescript@5.9.3): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + handlebars: 4.7.8 + jest: 30.2.0(@types/node@20.19.27)(ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3)) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.3 + type-fest: 4.41.0 + typescript: 5.9.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.28.5 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + babel-jest: 30.2.0(@babel/core@7.28.5) + jest-util: 30.2.0 + + ts-node@10.9.2(@types/node@20.19.27)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.19.27 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tuf-js@2.2.1: + dependencies: + '@tufjs/models': 2.0.1 + debug: 4.4.3 + make-fetch-happen: 13.0.1 + transitivePeerDependencies: + - supports-color + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.18.1: {} + + type-fest@0.21.3: {} + + type-fest@0.4.1: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-fest@4.41.0: {} + + typedarray@0.0.6: {} + + typescript@5.9.3: {} + + uglify-js@3.19.3: + optional: true + + undici-types@6.21.0: {} + + unique-filename@3.0.0: + dependencies: + unique-slug: 4.0.0 + + unique-slug@4.0.0: + dependencies: + imurmurhash: 0.1.4 + + universal-user-agent@6.0.1: {} + + universalify@2.0.1: {} + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + upath@2.0.1: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + uuid@10.0.0: {} + + v8-compile-cache-lib@3.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@5.0.1: {} + + walk-up-path@3.0.1: {} + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@4.0.0: + dependencies: + isexe: 3.1.1 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + word-wrap@1.2.5: {} + + wordwrap@1.0.0: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 + + wrappy@1.0.2: {} + + write-file-atomic@2.4.3: + dependencies: + graceful-fs: 4.2.11 + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + write-json-file@3.2.0: + dependencies: + detect-indent: 5.0.0 + graceful-fs: 4.2.11 + make-dir: 2.1.0 + pify: 4.0.1 + sort-keys: 2.0.0 + write-file-atomic: 2.4.3 + + write-pkg@4.0.0: + dependencies: + sort-keys: 2.0.0 + type-fest: 0.4.1 + write-json-file: 3.2.0 + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yaml@2.8.2: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} From d4307b2bacfdc1366df277ace66976afaf21bdff Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 17:29:53 +0000 Subject: [PATCH 03/12] fix: update CI workflow for new package names - Rename workflow from 'pgpm tests' to 'CI' - Update matrix to use bash-parser and docker-parser packages - Remove pgpm-specific steps (no longer needed for pnpm-only workspace) - Add lint step to CI pipeline --- .github/workflows/ci.yml | 64 ++++------------------------------------ 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1692719..95ab664 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: pgpm tests +name: CI on: pull_request: branches: @@ -11,55 +11,14 @@ on: jobs: test: runs-on: ubuntu-latest - continue-on-error: true strategy: fail-fast: false matrix: package: - - your-module-1 - - your-module-2 - - env: - PGHOST: localhost - PGPORT: 5432 - PGUSER: postgres - PGPASSWORD: password - PGPM_VERSION: 2.7.9 - - services: - pg_db: - image: pyramation/pgvector:13.3-alpine - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - - minio_cdn: - image: minio/minio:edge-cicd - env: - MINIO_ROOT_USER: minioadmin - MINIO_ROOT_PASSWORD: minioadmin - ports: - - 9000:9000 - - 9001:9001 - options: >- - --health-cmd "curl -f http://localhost:9000/minio/health/live || exit 1" - --health-interval 10s - --health-timeout 5s - --health-retries 5 + - bash-parser + - docker-parser steps: - - name: Configure Git (for tests) - run: | - git config --global user.name "CI Test User" - git config --global user.email "ci@example.com" - - name: Checkout uses: actions/checkout@v4 @@ -77,24 +36,11 @@ jobs: - name: Install run: pnpm install - - name: Cache pgpm CLI - id: cache-pgpm - uses: actions/cache@v4 - with: - path: ~/.npm - key: pgpm-${{ env.PGPM_VERSION }} - - - name: Install pgpm CLI globally - run: npm install -g pgpm@${{ env.PGPM_VERSION }} - - name: Build run: pnpm -r build - - name: Seed pg and app_user - run: | - pgpm admin-users bootstrap --yes - # optional, but added to avoid concurrent attempts to add user - pgpm admin-users add --test --yes + - name: Lint + run: pnpm lint - name: Test ${{ matrix.package }} run: cd ./packages/${{ matrix.package }} && pnpm test From bca2c10e176c4dfa0b6de4dbb0345217f77c58a3 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 18:07:49 +0000 Subject: [PATCH 04/12] feat: add policy-engine and nginx-parser packages Phase 1: policy-engine package - Core types: Decision, PolicyModule, PolicyContext, PolicyData, Obligation - PolicyHelpers: all, any, none, count, find, match (exact/iexact/prefix/suffix/glob/regex), get, defined, empty, includes - Evaluator: evaluatePolicy, evaluatePolicies with deny-overrides strategy - Validator: validateModule, validateContext, validateData - 85 tests passing Phase 2: nginx-parser package - Lexer: tokenizes nginx.conf files (structural tokens, quoted strings, variables, comments) - Parser: recursive descent parser for all nginx constructs (server, location, upstream, map, if, http, events, stream, types, limit_except) - Deparser: AST to nginx.conf string conversion with proper indentation - cleanTree utility for round-trip testing - 53 tests passing Also includes: - POLICY_ENGINE_PLAN.md with full implementation plan - nginx fixtures for testing --- POLICY_ENGINE_PLAN.md | 465 ++++++++++++++++++ __fixtures__/nginx/basic/simple.conf | 26 + __fixtures__/nginx/basic/with-map.conf | 23 + __fixtures__/nginx/basic/with-upstream.conf | 16 + __fixtures__/nginx/locations/modifiers.conf | 28 ++ packages/nginx-parser/README.md | 144 ++++++ .../nginx-parser/__tests__/deparser.test.ts | 187 +++++++ .../nginx-parser/__tests__/parser.test.ts | 332 +++++++++++++ .../nginx-parser/__tests__/roundtrip.test.ts | 178 +++++++ packages/nginx-parser/jest.config.js | 8 + packages/nginx-parser/package.json | 42 ++ packages/nginx-parser/src/clean.ts | 85 ++++ packages/nginx-parser/src/deparser.ts | 306 ++++++++++++ packages/nginx-parser/src/index.ts | 38 ++ packages/nginx-parser/src/lexer.ts | 318 ++++++++++++ packages/nginx-parser/src/parser.ts | 411 ++++++++++++++++ packages/nginx-parser/src/types.ts | 191 +++++++ packages/nginx-parser/test-utils/index.ts | 34 ++ packages/nginx-parser/tsconfig.esm.json | 7 + packages/nginx-parser/tsconfig.json | 9 + packages/policy-engine/README.md | 196 ++++++++ .../policy-engine/__tests__/evaluator.test.ts | 375 ++++++++++++++ .../policy-engine/__tests__/helpers.test.ts | 257 ++++++++++ .../policy-engine/__tests__/validator.test.ts | 306 ++++++++++++ packages/policy-engine/jest.config.js | 8 + packages/policy-engine/package.json | 42 ++ packages/policy-engine/src/evaluator.ts | 207 ++++++++ packages/policy-engine/src/helpers.ts | 209 ++++++++ packages/policy-engine/src/index.ts | 42 ++ packages/policy-engine/src/types.ts | 272 ++++++++++ packages/policy-engine/src/validator.ts | 250 ++++++++++ packages/policy-engine/tsconfig.esm.json | 7 + packages/policy-engine/tsconfig.json | 9 + pnpm-lock.yaml | 14 + 34 files changed, 5042 insertions(+) create mode 100644 POLICY_ENGINE_PLAN.md create mode 100644 __fixtures__/nginx/basic/simple.conf create mode 100644 __fixtures__/nginx/basic/with-map.conf create mode 100644 __fixtures__/nginx/basic/with-upstream.conf create mode 100644 __fixtures__/nginx/locations/modifiers.conf create mode 100644 packages/nginx-parser/README.md create mode 100644 packages/nginx-parser/__tests__/deparser.test.ts create mode 100644 packages/nginx-parser/__tests__/parser.test.ts create mode 100644 packages/nginx-parser/__tests__/roundtrip.test.ts create mode 100644 packages/nginx-parser/jest.config.js create mode 100644 packages/nginx-parser/package.json create mode 100644 packages/nginx-parser/src/clean.ts create mode 100644 packages/nginx-parser/src/deparser.ts create mode 100644 packages/nginx-parser/src/index.ts create mode 100644 packages/nginx-parser/src/lexer.ts create mode 100644 packages/nginx-parser/src/parser.ts create mode 100644 packages/nginx-parser/src/types.ts create mode 100644 packages/nginx-parser/test-utils/index.ts create mode 100644 packages/nginx-parser/tsconfig.esm.json create mode 100644 packages/nginx-parser/tsconfig.json create mode 100644 packages/policy-engine/README.md create mode 100644 packages/policy-engine/__tests__/evaluator.test.ts create mode 100644 packages/policy-engine/__tests__/helpers.test.ts create mode 100644 packages/policy-engine/__tests__/validator.test.ts create mode 100644 packages/policy-engine/jest.config.js create mode 100644 packages/policy-engine/package.json create mode 100644 packages/policy-engine/src/evaluator.ts create mode 100644 packages/policy-engine/src/helpers.ts create mode 100644 packages/policy-engine/src/index.ts create mode 100644 packages/policy-engine/src/types.ts create mode 100644 packages/policy-engine/src/validator.ts create mode 100644 packages/policy-engine/tsconfig.esm.json create mode 100644 packages/policy-engine/tsconfig.json diff --git a/POLICY_ENGINE_PLAN.md b/POLICY_ENGINE_PLAN.md new file mode 100644 index 0000000..318ef29 --- /dev/null +++ b/POLICY_ENGINE_PLAN.md @@ -0,0 +1,465 @@ +# Policy Engine & Nginx Compilation Plan + +## Overview + +A TypeScript-based policy engine where **TypeScript IS the policy language**, with compilation to Nginx configurations. Policies are pure functions that return Decisions, which can be compiled to if/switch control flow structures and then to target formats (Nginx, WASM, etc.). + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ Policy Authoring │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ PolicyModule (TypeScript) │ │ +│ │ - Pure function: (ctx, data, helpers) => Decision │ │ +│ │ - Constrained syntax (no side effects, deterministic) │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ Policy Compilation │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ Intermediate Representation (IR) │ │ +│ │ - Normalized if/else chains │ │ +│ │ - Switch statements for multi-branch decisions │ │ +│ │ - Condition trees (AND/OR/NOT) │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ┌──────────────┼──────────────┐ + ▼ ▼ ▼ + ┌──────────┐ ┌──────────┐ ┌──────────┐ + │ Nginx │ │ WASM │ │ Other │ + │ Config │ │ Bytecode │ │ Targets │ + └──────────┘ └──────────┘ └──────────┘ +``` + +## Packages + +### 1. `policy-engine` (Core) + +The foundation - types, helpers, and runtime evaluator. + +``` +packages/policy-engine/ +├── src/ +│ ├── types.ts # Core types (Decision, PolicyModule, etc.) +│ ├── helpers.ts # PolicyHelpers implementation (all, any, match, get) +│ ├── evaluator.ts # Runtime policy evaluation with sandboxing +│ ├── validator.ts # Static validation of policy modules +│ └── index.ts +├── __tests__/ +└── __fixtures__/ +``` + +**Core Types:** + +```typescript +// Effect: the outcome of a policy decision +type Effect = "allow" | "deny"; + +// Reason: explains why a decision was made +interface Reason { + code: string; // stable identifier for analytics + message: string; // human-readable + path?: string; // e.g., "request.route" + meta?: Record; +} + +// Obligation: side effects to apply (maps to Nginx directives) +interface Obligation { + kind: "setHeader" | "rateLimit" | "rewrite" | "log" | "mask" | "route"; + args: Record; +} + +// Decision: the result of policy evaluation +interface Decision { + effect: Effect; + reasons: Reason[]; + obligations?: Obligation[]; + trace?: Array<{ step: string; ok: boolean; meta?: unknown }>; +} + +// PolicyContext: request + identity + environment +interface PolicyContext { + request: { + id: string; + time: string; + ip?: string; + method?: string; + host?: string; + path?: string; + headers?: Record; + namespace?: string; + service?: string; + operation?: string; + destination?: { host: string; port?: number; protocol?: string }; + }; + identity: { + subject: string; + roles?: string[]; + groups?: string[]; + claims?: Record; + }; + env: { + tenantId?: string; + cluster?: string; + region?: string; + stage?: "dev" | "staging" | "prod"; + }; +} + +// PolicyData: static config/facts +interface PolicyData { + nsBindings?: Record; + egressAllow?: Record>; + rbac?: Record; + [key: string]: unknown; +} + +// PolicyHelpers: safe, deterministic operations +interface PolicyHelpers { + all(items: readonly T[], pred: (x: T) => boolean): boolean; + any(items: readonly T[], pred: (x: T) => boolean): boolean; + none(items: readonly T[], pred: (x: T) => boolean): boolean; + count(items: readonly T[], pred: (x: T) => boolean): number; + match: { + exact(a?: string, b?: string): boolean; + prefix(value: string | undefined, prefix: string): boolean; + glob(value: string | undefined, pattern: string): boolean; + regex(value: string | undefined, pattern: string): boolean; + }; + get(obj: unknown, path: string, fallback: T): T; +} + +// PolicyModule: a versioned, composable policy +interface PolicyModule { + id: string; + version: string; + description?: string; + expects?: { + data?: string[]; + claims?: string[]; + }; + evaluate: (ctx: PolicyContext, data: PolicyData, h: PolicyHelpers) => Decision; +} +``` + +### 2. `policy-ir` (Intermediate Representation) + +Normalized control flow structures for compilation. + +``` +packages/policy-ir/ +├── src/ +│ ├── types.ts # IR node types +│ ├── builder.ts # Fluent API for building IR +│ ├── optimizer.ts # Simplify/optimize IR trees +│ └── index.ts +├── __tests__/ +``` + +**IR Types (If/Switch based):** + +```typescript +// Condition types +type Condition = + | { type: "compare"; left: Expression; op: "==" | "!=" | ">" | "<" | ">=" | "<="; right: Expression } + | { type: "match"; value: Expression; pattern: string; matchType: "exact" | "prefix" | "glob" | "regex" } + | { type: "in"; value: Expression; list: Expression[] } + | { type: "exists"; path: string } + | { type: "and"; conditions: Condition[] } + | { type: "or"; conditions: Condition[] } + | { type: "not"; condition: Condition }; + +// Expression types +type Expression = + | { type: "literal"; value: string | number | boolean } + | { type: "path"; path: string } // e.g., "ctx.request.path" + | { type: "call"; fn: string; args: Expression[] }; + +// Statement types (if/switch) +type Statement = + | { type: "if"; condition: Condition; then: Statement[]; else?: Statement[] } + | { type: "switch"; value: Expression; cases: Array<{ match: Expression; body: Statement[] }>; default?: Statement[] } + | { type: "return"; decision: DecisionIR } + | { type: "assign"; variable: string; value: Expression }; + +// Decision in IR form +interface DecisionIR { + effect: "allow" | "deny"; + reasonCode: string; + reasonMessage: string; + obligations?: ObligationIR[]; +} + +interface ObligationIR { + kind: string; + args: Record; +} + +// Complete IR program +interface PolicyIR { + id: string; + version: string; + inputs: string[]; // required context paths + body: Statement[]; +} +``` + +### 3. `nginx-parser` (Parser/Deparser) + +Parse and generate Nginx configurations, following docker-parser patterns. + +``` +packages/nginx-parser/ +├── src/ +│ ├── types.ts # Nginx AST types +│ ├── lexer.ts # Tokenizer +│ ├── parser.ts # Parser +│ ├── deparser.ts # Generate config from AST +│ ├── clean.ts # cleanTree for testing +│ └── index.ts +├── __tests__/ +│ ├── parser.test.ts +│ ├── deparser.test.ts +│ └── roundtrip.test.ts +├── __fixtures__/ +│ └── nginx/ +│ ├── basic/ +│ ├── locations/ +│ └── upstreams/ +└── test-utils/ +``` + +**Nginx AST Types:** + +```typescript +interface NginxConfig { + type: "NginxConfig"; + directives: Directive[]; + blocks: Block[]; +} + +interface Directive { + type: "Directive"; + name: string; + args: string[]; + range?: Range; +} + +interface Block { + type: "Block"; + name: string; + args: string[]; + directives: Directive[]; + blocks: Block[]; + range?: Range; +} + +// Specific block types +interface HttpBlock extends Block { + name: "http"; +} + +interface ServerBlock extends Block { + name: "server"; +} + +interface LocationBlock extends Block { + name: "location"; + modifier?: "=" | "~" | "~*" | "^~"; + path: string; +} + +interface UpstreamBlock extends Block { + name: "upstream"; + upstreamName: string; +} + +interface IfBlock extends Block { + name: "if"; + condition: string; +} + +interface MapBlock extends Block { + name: "map"; + source: string; + variable: string; +} +``` + +### 4. `policy-to-nginx` (Compiler) + +Compile Policy IR to Nginx configuration. + +``` +packages/policy-to-nginx/ +├── src/ +│ ├── compiler.ts # Main compilation logic +│ ├── templates.ts # Nginx config templates +│ ├── obligations.ts # Obligation -> Nginx directive mapping +│ └── index.ts +├── __tests__/ +``` + +**Obligation to Nginx Mapping:** + +```typescript +// setHeader -> add_header / proxy_set_header +{ kind: "setHeader", args: { name: "X-Namespace", value: "$ns" } } +// => add_header X-Namespace $ns; + +// rateLimit -> limit_req_zone + limit_req +{ kind: "rateLimit", args: { zone: "api", rate: "10r/s", burst: 20 } } +// => limit_req zone=api burst=20 nodelay; + +// rewrite -> rewrite / return +{ kind: "rewrite", args: { from: "/old", to: "/new", type: "permanent" } } +// => rewrite ^/old$ /new permanent; + +// route -> proxy_pass / upstream selection +{ kind: "route", args: { upstream: "backend", path: "/api" } } +// => proxy_pass http://backend; + +// log -> access_log with custom format +{ kind: "log", args: { format: "policy", path: "/var/log/nginx/policy.log" } } +// => access_log /var/log/nginx/policy.log policy; +``` + +**Compilation Strategy:** + +Policy conditions compile to Nginx `if` blocks or `map` directives: + +```nginx +# From policy condition: ctx.request.path starts with "/api" +map $uri $is_api { + default 0; + ~^/api 1; +} + +# From policy condition: identity.claims.ns == request.namespace +# (requires external auth module to set $jwt_ns) +if ($jwt_ns != $namespace) { + return 403; +} + +# From obligation: setHeader +add_header X-Policy-Decision "allow"; + +# From obligation: rateLimit +limit_req zone=policy_limit burst=10 nodelay; +``` + +## Implementation Order + +### Phase 1: Core Types & Runtime +1. Create `policy-engine` package with core types +2. Implement PolicyHelpers (all, any, match, get) +3. Implement runtime evaluator with sandboxing +4. Add tests with example policies + +### Phase 2: Nginx Parser/Deparser +1. Create `nginx-parser` package structure +2. Implement lexer (tokenize nginx.conf) +3. Implement parser (tokens -> AST) +4. Implement deparser (AST -> nginx.conf) +5. Add fixtures and round-trip tests + +### Phase 3: Intermediate Representation +1. Create `policy-ir` package with IR types +2. Implement IR builder (fluent API) +3. Implement IR optimizer (simplify conditions) +4. Add tests + +### Phase 4: Policy to Nginx Compiler +1. Create `policy-to-nginx` package +2. Implement obligation -> directive mapping +3. Implement condition -> if/map compilation +4. Implement full policy -> nginx.conf compilation +5. Add integration tests + +### Phase 5: Heterogeneous Integration +1. Add policy-engine as dependency to docker-parser +2. Parse Dockerfile -> extract policy hints from labels/comments +3. Generate nginx.conf from Docker + policy definitions + +## Example: End-to-End Flow + +**Input: TypeScript Policy** +```typescript +const policy: PolicyModule = { + id: "api.ratelimit", + version: "1.0.0", + evaluate(ctx, data, h) { + if (h.match.prefix(ctx.request.path, "/api/public")) { + return { + effect: "allow", + reasons: [{ code: "public_api", message: "Public API access" }], + obligations: [{ kind: "rateLimit", args: { rate: "100r/s" } }] + }; + } + if (!ctx.identity.subject) { + return { + effect: "deny", + reasons: [{ code: "unauthenticated", message: "Auth required" }] + }; + } + return { + effect: "allow", + reasons: [{ code: "authenticated", message: "Authenticated access" }], + obligations: [ + { kind: "rateLimit", args: { rate: "1000r/s" } }, + { kind: "setHeader", args: { name: "X-User", value: ctx.identity.subject } } + ] + }; + } +}; +``` + +**Output: Nginx Config** +```nginx +# Generated from policy: api.ratelimit v1.0.0 + +limit_req_zone $binary_remote_addr zone=public_api:10m rate=100r/s; +limit_req_zone $binary_remote_addr zone=authenticated:10m rate=1000r/s; + +server { + listen 80; + + # Public API - rate limited, no auth required + location ^~ /api/public { + limit_req zone=public_api burst=50 nodelay; + proxy_pass http://backend; + } + + # Authenticated API + location /api { + # Auth check (assumes auth_request or JWT module) + auth_request /auth; + + # Deny if unauthenticated + if ($auth_user = "") { + return 403; + } + + limit_req zone=authenticated burst=100 nodelay; + add_header X-User $auth_user; + proxy_pass http://backend; + } +} +``` + +## Testing Strategy + +1. **Unit Tests**: Each package has isolated tests +2. **Round-Trip Tests**: Parse -> Deparse -> Parse for nginx-parser +3. **Integration Tests**: Policy -> IR -> Nginx -> Validate +4. **Fixture-Based**: Real-world nginx configs and policies + +## Open Questions + +1. **Runtime vs Compile-time**: Should some policies evaluate at runtime (via Lua/njs) while others compile to static config? +2. **Auth Integration**: How to handle JWT claims in Nginx (auth_request, njs, lua)? +3. **Dynamic Data**: How to handle PolicyData that changes (reload configs vs runtime lookup)? diff --git a/__fixtures__/nginx/basic/simple.conf b/__fixtures__/nginx/basic/simple.conf new file mode 100644 index 0000000..20de0bd --- /dev/null +++ b/__fixtures__/nginx/basic/simple.conf @@ -0,0 +1,26 @@ +worker_processes 4; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + } +} diff --git a/__fixtures__/nginx/basic/with-map.conf b/__fixtures__/nginx/basic/with-map.conf new file mode 100644 index 0000000..3929a7c --- /dev/null +++ b/__fixtures__/nginx/basic/with-map.conf @@ -0,0 +1,23 @@ +map $uri $new_uri { + default ""; + /old-page /new-page; + /legacy /modern; +} + +map $http_user_agent $is_mobile { + default 0; + ~*mobile 1; + ~*android 1; +} + +server { + listen 80; + + if ($new_uri) { + return 301 $new_uri; + } + + location / { + root /var/www/html; + } +} diff --git a/__fixtures__/nginx/basic/with-upstream.conf b/__fixtures__/nginx/basic/with-upstream.conf new file mode 100644 index 0000000..64a65f9 --- /dev/null +++ b/__fixtures__/nginx/basic/with-upstream.conf @@ -0,0 +1,16 @@ +upstream backend { + server 127.0.0.1:8080 weight=5; + server 127.0.0.1:8081 weight=3; + server 127.0.0.1:8082 backup; +} + +server { + listen 80; + server_name api.example.com; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} diff --git a/__fixtures__/nginx/locations/modifiers.conf b/__fixtures__/nginx/locations/modifiers.conf new file mode 100644 index 0000000..f32eb6c --- /dev/null +++ b/__fixtures__/nginx/locations/modifiers.conf @@ -0,0 +1,28 @@ +server { + listen 80; + + location = /exact { + return 200 "exact match"; + } + + location ^~ /prefix { + return 200 "prefix match"; + } + + location ~ \.php$ { + fastcgi_pass unix:/var/run/php-fpm.sock; + } + + location ~* \.(jpg|jpeg|png|gif)$ { + expires 30d; + } + + location @named { + internal; + proxy_pass http://backend; + } + + location / { + try_files $uri $uri/ @named; + } +} diff --git a/packages/nginx-parser/README.md b/packages/nginx-parser/README.md new file mode 100644 index 0000000..c57cab4 --- /dev/null +++ b/packages/nginx-parser/README.md @@ -0,0 +1,144 @@ +# nginx-parser + +TypeScript Nginx configuration parser and deparser. Parse nginx.conf files into AST and regenerate configuration from AST. + +## Installation + +```bash +npm install nginx-parser +``` + +## Usage + +### Parse Nginx Configuration + +```typescript +import { parse } from 'nginx-parser'; + +const config = ` +server { + listen 80; + server_name example.com; + + location / { + proxy_pass http://backend; + } +} +`; + +const ast = parse(config); +console.log(ast); +``` + +### Deparse AST to Configuration + +```typescript +import { parse, deparse } from 'nginx-parser'; + +const ast = parse(config); +const output = deparse(ast); +console.log(output); +``` + +### Round-Trip Testing + +```typescript +import { parse, deparse, cleanTree } from 'nginx-parser'; + +const ast1 = parse(config); +const output = deparse(ast1); +const ast2 = parse(output); + +// Compare ASTs without location info +expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); +``` + +## AST Types + +### NginxConfig (Root) + +```typescript +interface NginxConfig { + type: 'NginxConfig'; + body: Statement[]; +} +``` + +### Directive + +```typescript +interface Directive { + type: 'Directive'; + name: string; + args: string[]; +} +``` + +### Block Types + +- `ServerBlock` - Virtual server configuration +- `LocationBlock` - URI handling with optional modifiers (=, ~, ~*, ^~, @) +- `HttpBlock` - HTTP context +- `EventsBlock` - Events context +- `StreamBlock` - TCP/UDP proxying +- `UpstreamBlock` - Backend server groups +- `MapBlock` - Variable mapping +- `IfBlock` - Conditional logic +- `TypesBlock` - MIME type definitions +- `LimitExceptBlock` - HTTP method restrictions + +### Location Modifiers + +```typescript +interface LocationBlock { + type: 'LocationBlock'; + modifier?: '=' | '~' | '~*' | '^~' | '@'; + path: string; + body: Statement[]; +} +``` + +- `=` - Exact match +- `~` - Case-sensitive regex +- `~*` - Case-insensitive regex +- `^~` - Prefix match (no regex check) +- `@` - Named location + +## Deparse Options + +```typescript +interface DeparseOptions { + indent?: string; // Default: ' ' (4 spaces) + newline?: string; // Default: '\n' +} + +const output = deparse(ast, { indent: ' ' }); +``` + +## Utilities + +### cleanTree + +Remove location/range information from AST for comparison: + +```typescript +import { cleanTree } from 'nginx-parser'; + +const cleaned = cleanTree(ast); +``` + +### astEqual + +Compare two ASTs ignoring location info: + +```typescript +import { astEqual } from 'nginx-parser'; + +if (astEqual(ast1, ast2)) { + console.log('ASTs are equivalent'); +} +``` + +## License + +MIT diff --git a/packages/nginx-parser/__tests__/deparser.test.ts b/packages/nginx-parser/__tests__/deparser.test.ts new file mode 100644 index 0000000..0bbde95 --- /dev/null +++ b/packages/nginx-parser/__tests__/deparser.test.ts @@ -0,0 +1,187 @@ +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; + +describe('nginx deparser', () => { + describe('directives', () => { + it('deparses simple directive', () => { + const ast = parse('worker_processes 4;'); + const output = deparse(ast); + + expect(output).toBe('worker_processes 4;'); + }); + + it('deparses directive with multiple arguments', () => { + const ast = parse('error_log /var/log/nginx/error.log warn;'); + const output = deparse(ast); + + expect(output).toBe('error_log /var/log/nginx/error.log warn;'); + }); + + it('deparses multiple directives', () => { + const input = `worker_processes 4; +error_log /var/log/error.log;`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('worker_processes 4;'); + expect(output).toContain('error_log /var/log/error.log;'); + }); + }); + + describe('comments', () => { + it('deparses comments', () => { + const ast = parse('# This is a comment'); + const output = deparse(ast); + + expect(output).toBe('# This is a comment'); + }); + }); + + describe('server block', () => { + it('deparses server block', () => { + const input = `server { + listen 80; + server_name localhost; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('server {'); + expect(output).toContain('listen 80;'); + expect(output).toContain('server_name localhost;'); + expect(output).toContain('}'); + }); + }); + + describe('location block', () => { + it('deparses location block', () => { + const input = `location / { + root /var/www/html; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('location / {'); + expect(output).toContain('root /var/www/html;'); + }); + + it('deparses location with modifier', () => { + const input = `location = /exact { + return 200; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('location = /exact {'); + }); + + it('deparses location with regex modifier', () => { + const input = `location ~ \\.php$ { + fastcgi_pass unix:/var/run/php-fpm.sock; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('location ~ \\.php$ {'); + }); + }); + + describe('upstream block', () => { + it('deparses upstream block', () => { + const input = `upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('upstream backend {'); + expect(output).toContain('server 127.0.0.1:8080;'); + }); + }); + + describe('map block', () => { + it('deparses map block', () => { + const input = `map $uri $new_uri { + default ""; + /old /new; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('map $uri $new_uri {'); + expect(output).toContain('default ;'); + }); + }); + + describe('if block', () => { + it('deparses if block', () => { + const input = `if ($request_method = POST) { + return 405; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('if ('); + expect(output).toContain('$request_method = POST'); + expect(output).toContain('return 405;'); + }); + }); + + describe('http block', () => { + it('deparses http block', () => { + const input = `http { + include mime.types; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('http {'); + expect(output).toContain('include mime.types;'); + }); + }); + + describe('events block', () => { + it('deparses events block', () => { + const input = `events { + worker_connections 1024; +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('events {'); + expect(output).toContain('worker_connections 1024;'); + }); + }); + + describe('nested blocks', () => { + it('deparses nested structure with proper indentation', () => { + const input = `http { + server { + location / { + root /var/www/html; + } + } +}`; + const ast = parse(input); + const output = deparse(ast); + + expect(output).toContain('http {'); + expect(output).toContain('server {'); + expect(output).toContain('location / {'); + expect(output).toContain('root /var/www/html;'); + }); + }); + + describe('custom options', () => { + it('uses custom indent', () => { + const input = `server { + listen 80; +}`; + const ast = parse(input); + const output = deparse(ast, { indent: ' ' }); + + expect(output).toContain(' listen 80;'); + }); + }); +}); diff --git a/packages/nginx-parser/__tests__/parser.test.ts b/packages/nginx-parser/__tests__/parser.test.ts new file mode 100644 index 0000000..5f64257 --- /dev/null +++ b/packages/nginx-parser/__tests__/parser.test.ts @@ -0,0 +1,332 @@ +import { parse } from '../src/parser'; +import type { Directive, HttpBlock, IfBlock,LocationBlock, MapBlock, ServerBlock, UpstreamBlock } from '../src/types'; + +describe('nginx parser', () => { + describe('directives', () => { + it('parses simple directive', () => { + const input = 'worker_processes 4;'; + const ast = parse(input); + + expect(ast.type).toBe('NginxConfig'); + expect(ast.body).toHaveLength(1); + + const directive = ast.body[0] as Directive; + expect(directive.type).toBe('Directive'); + expect(directive.name).toBe('worker_processes'); + expect(directive.args).toEqual(['4']); + }); + + it('parses directive with multiple arguments', () => { + const input = 'error_log /var/log/nginx/error.log warn;'; + const ast = parse(input); + + const directive = ast.body[0] as Directive; + expect(directive.name).toBe('error_log'); + expect(directive.args).toEqual(['/var/log/nginx/error.log', 'warn']); + }); + + it('parses directive with no arguments', () => { + const input = 'daemon;'; + const ast = parse(input); + + const directive = ast.body[0] as Directive; + expect(directive.name).toBe('daemon'); + expect(directive.args).toEqual([]); + }); + + it('parses multiple directives', () => { + const input = ` + worker_processes 4; + error_log /var/log/error.log; + pid /var/run/nginx.pid; + `; + const ast = parse(input); + + expect(ast.body).toHaveLength(3); + }); + }); + + describe('comments', () => { + it('parses comments', () => { + const input = '# This is a comment'; + const ast = parse(input); + + expect(ast.body).toHaveLength(1); + expect(ast.body[0].type).toBe('Comment'); + }); + + it('parses comments with directives', () => { + const input = ` + # Comment + worker_processes 4; + `; + const ast = parse(input); + + expect(ast.body).toHaveLength(2); + expect(ast.body[0].type).toBe('Comment'); + expect(ast.body[1].type).toBe('Directive'); + }); + }); + + describe('server block', () => { + it('parses empty server block', () => { + const input = 'server { }'; + const ast = parse(input); + + expect(ast.body).toHaveLength(1); + const server = ast.body[0] as ServerBlock; + expect(server.type).toBe('ServerBlock'); + expect(server.body).toHaveLength(0); + }); + + it('parses server block with directives', () => { + const input = ` + server { + listen 80; + server_name localhost; + } + `; + const ast = parse(input); + + const server = ast.body[0] as ServerBlock; + expect(server.type).toBe('ServerBlock'); + expect(server.body).toHaveLength(2); + + const listen = server.body[0] as Directive; + expect(listen.name).toBe('listen'); + expect(listen.args).toEqual(['80']); + }); + }); + + describe('location block', () => { + it('parses location block', () => { + const input = ` + server { + location / { + root /var/www/html; + } + } + `; + const ast = parse(input); + + const server = ast.body[0] as ServerBlock; + const location = server.body[0] as LocationBlock; + expect(location.type).toBe('LocationBlock'); + expect(location.path).toBe('/'); + expect(location.modifier).toBeUndefined(); + }); + + it('parses location with exact modifier', () => { + const input = ` + location = /exact { + return 200; + } + `; + const ast = parse(input); + + const location = ast.body[0] as LocationBlock; + expect(location.modifier).toBe('='); + expect(location.path).toBe('/exact'); + }); + + it('parses location with regex modifier', () => { + const input = ` + location ~ \\.php$ { + fastcgi_pass unix:/var/run/php-fpm.sock; + } + `; + const ast = parse(input); + + const location = ast.body[0] as LocationBlock; + expect(location.modifier).toBe('~'); + expect(location.path).toBe('\\.php$'); + }); + + it('parses location with case-insensitive regex modifier', () => { + const input = ` + location ~* \\.(jpg|png)$ { + expires 30d; + } + `; + const ast = parse(input); + + const location = ast.body[0] as LocationBlock; + expect(location.modifier).toBe('~*'); + }); + + it('parses location with prefix modifier', () => { + const input = ` + location ^~ /images { + root /data; + } + `; + const ast = parse(input); + + const location = ast.body[0] as LocationBlock; + expect(location.modifier).toBe('^~'); + expect(location.path).toBe('/images'); + }); + + it('parses named location', () => { + const input = ` + location @fallback { + proxy_pass http://backend; + } + `; + const ast = parse(input); + + const location = ast.body[0] as LocationBlock; + expect(location.path).toBe('@fallback'); + }); + }); + + describe('http block', () => { + it('parses http block', () => { + const input = ` + http { + include mime.types; + server { + listen 80; + } + } + `; + const ast = parse(input); + + const http = ast.body[0] as HttpBlock; + expect(http.type).toBe('HttpBlock'); + expect(http.body).toHaveLength(2); + }); + }); + + describe('upstream block', () => { + it('parses upstream block', () => { + const input = ` + upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; + } + `; + const ast = parse(input); + + const upstream = ast.body[0] as UpstreamBlock; + expect(upstream.type).toBe('UpstreamBlock'); + expect(upstream.name).toBe('backend'); + expect(upstream.body).toHaveLength(2); + }); + + it('parses upstream with weights', () => { + const input = ` + upstream backend { + server 127.0.0.1:8080 weight=5; + server 127.0.0.1:8081 backup; + } + `; + const ast = parse(input); + + const upstream = ast.body[0] as UpstreamBlock; + const server1 = upstream.body[0] as Directive; + expect(server1.args).toContain('weight=5'); + }); + }); + + describe('map block', () => { + it('parses map block', () => { + const input = ` + map $uri $new_uri { + default ""; + /old /new; + } + `; + const ast = parse(input); + + const map = ast.body[0] as MapBlock; + expect(map.type).toBe('MapBlock'); + expect(map.source).toBe('$uri'); + expect(map.variable).toBe('$new_uri'); + expect(map.body).toHaveLength(2); + expect(map.body[0].match).toBe('default'); + expect(map.body[0].value).toBe(''); + }); + }); + + describe('if block', () => { + it('parses if block', () => { + const input = ` + if ($request_uri ~* "^/old") { + return 301 /new; + } + `; + const ast = parse(input); + + const ifBlock = ast.body[0] as IfBlock; + expect(ifBlock.type).toBe('IfBlock'); + expect(ifBlock.condition).toContain('$request_uri'); + }); + }); + + describe('events block', () => { + it('parses events block', () => { + const input = ` + events { + worker_connections 1024; + use epoll; + } + `; + const ast = parse(input); + + expect(ast.body[0].type).toBe('EventsBlock'); + }); + }); + + describe('nested blocks', () => { + it('parses deeply nested structure', () => { + const input = ` + http { + server { + location / { + if ($request_method = POST) { + return 405; + } + } + } + } + `; + const ast = parse(input); + + const http = ast.body[0] as HttpBlock; + const server = http.body[0] as ServerBlock; + const location = server.body[0] as LocationBlock; + const ifBlock = location.body[0] as IfBlock; + + expect(ifBlock.type).toBe('IfBlock'); + }); + }); + + describe('variables', () => { + it('parses variables in directives', () => { + const input = 'proxy_set_header Host $host;'; + const ast = parse(input); + + const directive = ast.body[0] as Directive; + expect(directive.args).toContain('$host'); + }); + }); + + describe('quoted strings', () => { + it('parses double-quoted strings', () => { + const input = 'return 200 "Hello World";'; + const ast = parse(input); + + const directive = ast.body[0] as Directive; + expect(directive.args).toContain('Hello World'); + }); + + it('parses single-quoted strings', () => { + const input = "add_header X-Custom 'value';"; + const ast = parse(input); + + const directive = ast.body[0] as Directive; + expect(directive.args).toContain('value'); + }); + }); +}); diff --git a/packages/nginx-parser/__tests__/roundtrip.test.ts b/packages/nginx-parser/__tests__/roundtrip.test.ts new file mode 100644 index 0000000..7a0e17a --- /dev/null +++ b/packages/nginx-parser/__tests__/roundtrip.test.ts @@ -0,0 +1,178 @@ +import { cleanTree } from '../src/clean'; +import { deparse } from '../src/deparser'; +import { parse } from '../src/parser'; +import {readFixture } from '../test-utils'; + +describe('nginx roundtrip', () => { + describe('parse -> deparse -> parse', () => { + it('roundtrips simple directive', () => { + const input = 'worker_processes 4;'; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips server block', () => { + const input = `server { + listen 80; + server_name localhost; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips location block', () => { + const input = `location / { + root /var/www/html; + index index.html; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips location with modifier', () => { + const input = `location = /exact { + return 200; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips upstream block', () => { + const input = `upstream backend { + server 127.0.0.1:8080; + server 127.0.0.1:8081; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips map block', () => { + const input = `map $uri $new_uri { + default ""; + /old /new; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips if block', () => { + const input = `if ($request_method = POST) { + return 405; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips nested structure', () => { + const input = `http { + server { + listen 80; + location / { + root /var/www/html; + } + } +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips events block', () => { + const input = `events { + worker_connections 1024; + use epoll; +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + + it('roundtrips complex configuration', () => { + const input = `worker_processes 4; +error_log /var/log/nginx/error.log warn; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + upstream backend { + server 127.0.0.1:8080; + } + + server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://backend; + } + + location = /health { + return 200; + } + } +}`; + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + }); + + describe('fixture roundtrips', () => { + const fixtures = [ + 'nginx/basic/simple.conf', + 'nginx/basic/with-upstream.conf', + 'nginx/basic/with-map.conf', + 'nginx/locations/modifiers.conf', + ]; + + for (const fixture of fixtures) { + it(`roundtrips ${fixture}`, () => { + let input: string; + try { + input = readFixture(fixture); + } catch { + // Skip if fixture doesn't exist + return; + } + + const ast1 = parse(input); + const output = deparse(ast1); + const ast2 = parse(output); + + expect(cleanTree(ast1)).toEqual(cleanTree(ast2)); + }); + } + }); +}); diff --git a/packages/nginx-parser/jest.config.js b/packages/nginx-parser/jest.config.js new file mode 100644 index 0000000..5642f3c --- /dev/null +++ b/packages/nginx-parser/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }] + }, + testMatch: ['**/__tests__/**/*.test.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] +}; diff --git a/packages/nginx-parser/package.json b/packages/nginx-parser/package.json new file mode 100644 index 0000000..5465379 --- /dev/null +++ b/packages/nginx-parser/package.json @@ -0,0 +1,42 @@ +{ + "name": "nginx-parser", + "version": "0.0.1", + "author": "Constructive ", + "description": "TypeScript Nginx configuration parser and deparser", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/dockerjs", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/dockerjs" + }, + "bugs": { + "url": "https://github.com/constructive-io/dockerjs/issues" + }, + "scripts": { + "copy": "makage assets", + "clean": "makage clean dist", + "prepublishOnly": "npm run build", + "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", + "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", + "lint": "cd ../.. && eslint packages/nginx-parser --fix", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "nginx", + "parser", + "deparser", + "configuration", + "typescript" + ], + "devDependencies": { + "makage": "^0.1.8" + } +} diff --git a/packages/nginx-parser/src/clean.ts b/packages/nginx-parser/src/clean.ts new file mode 100644 index 0000000..c3e5be7 --- /dev/null +++ b/packages/nginx-parser/src/clean.ts @@ -0,0 +1,85 @@ +import type { AstNode } from './types'; + +/** + * Remove range/location information from AST for comparison + */ +export function cleanTree(node: T): T { + if (Array.isArray(node)) { + return node.map((item) => cleanTree(item)) as unknown as T; + } + + if (node === null || typeof node !== 'object') { + return node; + } + + const cleaned: Record = {}; + + for (const [key, value] of Object.entries(node)) { + // Skip range/location properties + if (key === 'range' || key === 'location' || key === 'loc') { + continue; + } + + if (Array.isArray(value)) { + cleaned[key] = value.map((item) => { + if (item && typeof item === 'object') { + return cleanTree(item as AstNode); + } + return item; + }); + } else if (value && typeof value === 'object') { + cleaned[key] = cleanTree(value as AstNode); + } else { + cleaned[key] = value; + } + } + + return cleaned as T; +} + +/** + * Deep equality check for AST nodes (ignoring range) + */ +export function astEqual(a: AstNode, b: AstNode): boolean { + const cleanA = cleanTree(a); + const cleanB = cleanTree(b); + return JSON.stringify(cleanA) === JSON.stringify(cleanB); +} + +/** + * Pretty print AST for debugging + */ +export function printAst(node: AstNode, indent: number = 0): string { + const spaces = ' '.repeat(indent); + + if (Array.isArray(node)) { + if (node.length === 0) return '[]'; + const items = node.map((item) => printAst(item, indent + 1)); + return `[\n${items.map((i) => `${spaces} ${i}`).join(',\n')}\n${spaces}]`; + } + + if (node === null) return 'null'; + if (typeof node !== 'object') return JSON.stringify(node); + + const entries: string[] = []; + for (const [key, value] of Object.entries(node)) { + if (key === 'range') continue; + + if (Array.isArray(value)) { + if (value.length === 0) { + entries.push(`${key}: []`); + } else if (typeof value[0] === 'object') { + entries.push(`${key}: ${printAst(value as unknown as AstNode, indent + 1)}`); + } else { + entries.push(`${key}: ${JSON.stringify(value)}`); + } + } else if (value && typeof value === 'object') { + entries.push(`${key}: ${printAst(value as AstNode, indent + 1)}`); + } else { + entries.push(`${key}: ${JSON.stringify(value)}`); + } + } + + if (entries.length === 0) return '{}'; + return `{\n${entries.map((e) => `${spaces} ${e}`).join(',\n')}\n${spaces}}`; +} diff --git a/packages/nginx-parser/src/deparser.ts b/packages/nginx-parser/src/deparser.ts new file mode 100644 index 0000000..908fa20 --- /dev/null +++ b/packages/nginx-parser/src/deparser.ts @@ -0,0 +1,306 @@ +import type { + Block, + Comment, + Directive, + EventsBlock, + GeoBlock, + HttpBlock, + IfBlock, + LimitExceptBlock, + LocationBlock, + MapBlock, + MapEntry, + NginxConfig, + ServerBlock, + Statement, + StreamBlock, + TypesBlock, + UpstreamBlock, +} from './types'; + +/** + * Options for deparsing + */ +export interface DeparseOptions { + indent?: string; + newline?: string; +} + +const DEFAULT_OPTIONS: Required = { + indent: ' ', + newline: '\n', +}; + +/** + * Deparser for nginx configuration AST + */ +export class Deparser { + private options: Required; + private indentLevel: number = 0; + + constructor(options?: DeparseOptions) { + this.options = { ...DEFAULT_OPTIONS, ...options }; + } + + /** + * Deparse AST back to nginx configuration string + */ + deparse(ast: NginxConfig): string { + this.indentLevel = 0; + return this.deparseStatements(ast.body); + } + + private deparseStatements(statements: Statement[]): string { + const lines: string[] = []; + + for (const stmt of statements) { + const line = this.deparseStatement(stmt); + if (line !== null) { + lines.push(line); + } + } + + return lines.join(this.options.newline); + } + + private deparseStatement(stmt: Statement): string | null { + switch (stmt.type) { + case 'Comment': + return this.deparseComment(stmt); + case 'Directive': + return this.deparseDirective(stmt); + case 'Block': + return this.deparseBlock(stmt); + case 'IfBlock': + return this.deparseIfBlock(stmt); + case 'MapBlock': + return this.deparseMapBlock(stmt); + case 'GeoBlock': + return this.deparseGeoBlock(stmt); + case 'UpstreamBlock': + return this.deparseUpstreamBlock(stmt); + case 'ServerBlock': + return this.deparseServerBlock(stmt); + case 'LocationBlock': + return this.deparseLocationBlock(stmt); + case 'HttpBlock': + return this.deparseHttpBlock(stmt); + case 'EventsBlock': + return this.deparseEventsBlock(stmt); + case 'StreamBlock': + return this.deparseStreamBlock(stmt); + case 'TypesBlock': + return this.deparseTypesBlock(stmt); + case 'LimitExceptBlock': + return this.deparseLimitExceptBlock(stmt); + default: + return null; + } + } + + private deparseComment(comment: Comment): string { + return `${this.getIndent()}# ${comment.value}`; + } + + private deparseDirective(directive: Directive): string { + const args = directive.args.length > 0 ? ' ' + this.formatArgs(directive.args) : ''; + return `${this.getIndent()}${directive.name}${args};`; + } + + private deparseBlock(block: Block): string { + const args = block.args.length > 0 ? ' ' + this.formatArgs(block.args) : ''; + const header = `${this.getIndent()}${block.name}${args} {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseIfBlock(block: IfBlock): string { + // The condition already includes parentheses from parsing + const condition = block.condition.startsWith('(') ? block.condition : `(${block.condition})`; + const header = `${this.getIndent()}if ${condition} {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseMapBlock(block: MapBlock): string { + const header = `${this.getIndent()}map ${block.source} ${block.variable} {`; + const body = this.deparseMapEntries(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseMapEntries(entries: MapEntry[]): string { + this.indentLevel++; + const lines = entries.map((entry) => { + return `${this.getIndent()}${entry.match} ${entry.value};`; + }); + this.indentLevel--; + return lines.join(this.options.newline); + } + + private deparseGeoBlock(block: GeoBlock): string { + const addressPart = block.address ? `${block.address} ` : ''; + const header = `${this.getIndent()}geo ${addressPart}${block.variable} {`; + const body = this.deparseMapEntries(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseUpstreamBlock(block: UpstreamBlock): string { + const header = `${this.getIndent()}upstream ${block.name} {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseServerBlock(block: ServerBlock): string { + const header = `${this.getIndent()}server {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseLocationBlock(block: LocationBlock): string { + let locationPart = 'location'; + if (block.modifier && block.modifier !== '@') { + locationPart += ` ${block.modifier}`; + } + locationPart += ` ${block.path}`; + + const header = `${this.getIndent()}${locationPart} {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseHttpBlock(block: HttpBlock): string { + const header = `${this.getIndent()}http {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseEventsBlock(block: EventsBlock): string { + const header = `${this.getIndent()}events {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseStreamBlock(block: StreamBlock): string { + const header = `${this.getIndent()}stream {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseTypesBlock(block: TypesBlock): string { + const header = `${this.getIndent()}types {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseLimitExceptBlock(block: LimitExceptBlock): string { + const methods = block.methods.join(' '); + const header = `${this.getIndent()}limit_except ${methods} {`; + const body = this.deparseBlockBody(block.body); + const footer = `${this.getIndent()}}`; + + if (block.body.length === 0) { + return `${header}${this.options.newline}${footer}`; + } + + return `${header}${this.options.newline}${body}${this.options.newline}${footer}`; + } + + private deparseBlockBody(statements: Statement[]): string { + this.indentLevel++; + const result = this.deparseStatements(statements); + this.indentLevel--; + return result; + } + + private formatArgs(args: string[]): string { + return args + .map((arg) => { + // Quote strings that contain spaces or special characters + if (arg.includes(' ') || arg.includes('"') || arg.includes("'")) { + // Escape quotes and wrap in quotes + const escaped = arg.replace(/"/g, '\\"'); + return `"${escaped}"`; + } + return arg; + }) + .join(' '); + } + + private getIndent(): string { + return this.options.indent.repeat(this.indentLevel); + } +} + +/** + * Deparse nginx AST back to configuration string + */ +export function deparse(ast: NginxConfig, options?: DeparseOptions): string { + const deparser = new Deparser(options); + return deparser.deparse(ast); +} diff --git a/packages/nginx-parser/src/index.ts b/packages/nginx-parser/src/index.ts new file mode 100644 index 0000000..3232824 --- /dev/null +++ b/packages/nginx-parser/src/index.ts @@ -0,0 +1,38 @@ +// Types +export type { + AstNode, + BaseNode, + Block, + Comment, + Directive, + EventsBlock, + GeoBlock, + HttpBlock, + IfBlock, + LimitExceptBlock, + LocationBlock, + MapBlock, + MapEntry, + NginxConfig, + Position, + Range, + ServerBlock, + Statement, + StreamBlock, + TypesBlock, + UpstreamBlock, +} from './types'; + +// Lexer +export type { Token } from './lexer'; +export { Lexer, TokenType } from './lexer'; + +// Parser +export { parse,Parser } from './parser'; + +// Deparser +export type { DeparseOptions } from './deparser'; +export { deparse,Deparser } from './deparser'; + +// Utilities +export { astEqual, cleanTree, printAst } from './clean'; diff --git a/packages/nginx-parser/src/lexer.ts b/packages/nginx-parser/src/lexer.ts new file mode 100644 index 0000000..44f1b71 --- /dev/null +++ b/packages/nginx-parser/src/lexer.ts @@ -0,0 +1,318 @@ +import type { Position, Range } from './types'; + +/** + * Token types for nginx configuration + */ +export enum TokenType { + // Structural + LBRACE = 'LBRACE', // { + RBRACE = 'RBRACE', // } + SEMICOLON = 'SEMICOLON', // ; + + // Values + WORD = 'WORD', // unquoted word/identifier + QUOTED_STRING = 'QUOTED_STRING', // "..." or '...' + VARIABLE = 'VARIABLE', // $variable + + // Comments + COMMENT = 'COMMENT', // # comment + + // Special + NEWLINE = 'NEWLINE', + EOF = 'EOF', +} + +/** + * Token represents a single lexical unit + */ +export interface Token { + type: TokenType; + value: string; + range: Range; +} + +/** + * Lexer for nginx configuration files + */ +export class Lexer { + private input: string; + private pos: number = 0; + private line: number = 1; + private column: number = 1; + private tokens: Token[] = []; + + constructor(input: string) { + this.input = input; + } + + /** + * Tokenize the entire input + */ + tokenize(): Token[] { + while (!this.isAtEnd()) { + this.scanToken(); + } + + this.tokens.push({ + type: TokenType.EOF, + value: '', + range: this.makeRange(this.pos, this.pos), + }); + + return this.tokens; + } + + private scanToken(): void { + this.skipWhitespace(); + + if (this.isAtEnd()) { + return; + } + + const char = this.peek(); + + // Comments + if (char === '#') { + this.scanComment(); + return; + } + + // Structural tokens + if (char === '{') { + this.addToken(TokenType.LBRACE, '{'); + this.advance(); + return; + } + + if (char === '}') { + this.addToken(TokenType.RBRACE, '}'); + this.advance(); + return; + } + + if (char === ';') { + this.addToken(TokenType.SEMICOLON, ';'); + this.advance(); + return; + } + + // Quoted strings + if (char === '"' || char === "'") { + this.scanQuotedString(char); + return; + } + + // Variables or words + if (char === '$') { + this.scanVariable(); + return; + } + + // Regular words + if (this.isWordChar(char)) { + this.scanWord(); + return; + } + + // Skip unknown characters + this.advance(); + } + + private scanComment(): void { + const start = this.pos; + this.advance(); // skip # + + let value = ''; + while (!this.isAtEnd() && this.peek() !== '\n') { + value += this.advance(); + } + + this.tokens.push({ + type: TokenType.COMMENT, + value: value.trim(), + range: this.makeRange(start, this.pos), + }); + } + + private scanQuotedString(quote: string): void { + const start = this.pos; + this.advance(); // skip opening quote + + let value = ''; + while (!this.isAtEnd() && this.peek() !== quote) { + if (this.peek() === '\\' && this.peekNext() === quote) { + this.advance(); // skip backslash + value += this.advance(); // add escaped quote + } else if (this.peek() === '\\' && this.peekNext() === '\\') { + this.advance(); // skip first backslash + value += this.advance(); // add second backslash + } else if (this.peek() === '\n') { + value += this.advance(); + } else { + value += this.advance(); + } + } + + if (!this.isAtEnd()) { + this.advance(); // skip closing quote + } + + this.tokens.push({ + type: TokenType.QUOTED_STRING, + value, + range: this.makeRange(start, this.pos), + }); + } + + private scanVariable(): void { + const start = this.pos; + this.advance(); // skip $ + + let value = '$'; + + // Handle ${var} syntax + if (this.peek() === '{') { + value += this.advance(); // add { + while (!this.isAtEnd() && this.peek() !== '}') { + value += this.advance(); + } + if (!this.isAtEnd()) { + value += this.advance(); // add } + } + } else { + // Handle $var syntax + while (!this.isAtEnd() && this.isVariableChar(this.peek())) { + value += this.advance(); + } + } + + this.tokens.push({ + type: TokenType.VARIABLE, + value, + range: this.makeRange(start, this.pos), + }); + } + + private scanWord(): void { + const start = this.pos; + let value = ''; + + while (!this.isAtEnd() && this.isWordChar(this.peek())) { + value += this.advance(); + } + + this.tokens.push({ + type: TokenType.WORD, + value, + range: this.makeRange(start, this.pos), + }); + } + + private skipWhitespace(): void { + while (!this.isAtEnd()) { + const char = this.peek(); + if (char === ' ' || char === '\t' || char === '\r') { + this.advance(); + } else if (char === '\n') { + this.advance(); + } else { + break; + } + } + } + + private isWordChar(char: string): boolean { + // Nginx words can contain many characters + return ( + char !== ' ' && + char !== '\t' && + char !== '\n' && + char !== '\r' && + char !== '{' && + char !== '}' && + char !== ';' && + char !== '#' && + char !== '"' && + char !== "'" + ); + } + + private isVariableChar(char: string): boolean { + return /[a-zA-Z0-9_]/.test(char); + } + + private peek(): string { + if (this.isAtEnd()) return '\0'; + return this.input[this.pos]; + } + + private peekNext(): string { + if (this.pos + 1 >= this.input.length) return '\0'; + return this.input[this.pos + 1]; + } + + private advance(): string { + const char = this.input[this.pos]; + this.pos++; + + if (char === '\n') { + this.line++; + this.column = 1; + } else { + this.column++; + } + + return char; + } + + private isAtEnd(): boolean { + return this.pos >= this.input.length; + } + + private addToken(type: TokenType, value: string): void { + const start = this.pos; + this.tokens.push({ + type, + value, + range: this.makeRange(start, start + value.length), + }); + } + + private makeRange(start: number, end: number): Range { + // Calculate line/column for start position + let startLine = 1; + let startColumn = 1; + for (let i = 0; i < start && i < this.input.length; i++) { + if (this.input[i] === '\n') { + startLine++; + startColumn = 1; + } else { + startColumn++; + } + } + + // Calculate line/column for end position + let endLine = startLine; + let endColumn = startColumn; + for (let i = start; i < end && i < this.input.length; i++) { + if (this.input[i] === '\n') { + endLine++; + endColumn = 1; + } else { + endColumn++; + } + } + + return { + start: { line: startLine, column: startColumn }, + end: { line: endLine, column: endColumn }, + }; + } + + /** + * Get current position for error reporting + */ + getPosition(): Position { + return { line: this.line, column: this.column }; + } +} diff --git a/packages/nginx-parser/src/parser.ts b/packages/nginx-parser/src/parser.ts new file mode 100644 index 0000000..1aed44d --- /dev/null +++ b/packages/nginx-parser/src/parser.ts @@ -0,0 +1,411 @@ +import { Lexer, Token, TokenType } from './lexer'; +import type { + Block, + Comment, + Directive, + EventsBlock, + GeoBlock, + HttpBlock, + IfBlock, + LimitExceptBlock, + LocationBlock, + MapBlock, + MapEntry, + NginxConfig, + Range, + ServerBlock, + Statement, + StreamBlock, + TypesBlock, + UpstreamBlock, +} from './types'; + +/** + * Parser for nginx configuration files + */ +export class Parser { + private tokens: Token[] = []; + private current: number = 0; + + /** + * Parse nginx configuration string into AST + */ + parse(input: string): NginxConfig { + const lexer = new Lexer(input); + this.tokens = lexer.tokenize(); + this.current = 0; + + const body: Statement[] = []; + const startToken = this.peek(); + + while (!this.isAtEnd()) { + const stmt = this.parseStatement(); + if (stmt) { + body.push(stmt); + } + } + + return { + type: 'NginxConfig', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseStatement(): Statement | null { + // Skip comments but include them in AST + if (this.check(TokenType.COMMENT)) { + return this.parseComment(); + } + + // Skip stray semicolons + if (this.check(TokenType.SEMICOLON)) { + this.advance(); + return null; + } + + // Skip closing braces (handled by block parsing) + if (this.check(TokenType.RBRACE)) { + return null; + } + + // Parse directive or block + if (this.check(TokenType.WORD) || this.check(TokenType.VARIABLE)) { + return this.parseDirectiveOrBlock(); + } + + // Skip unknown tokens + this.advance(); + return null; + } + + private parseComment(): Comment { + const token = this.advance(); + return { + type: 'Comment', + value: token.value, + range: token.range, + }; + } + + private parseDirectiveOrBlock(): Statement { + const startToken = this.peek(); + const name = this.advance().value; + + // Collect arguments until we hit { or ; + const args: string[] = []; + while ( + !this.isAtEnd() && + !this.check(TokenType.LBRACE) && + !this.check(TokenType.SEMICOLON) && + !this.check(TokenType.COMMENT) + ) { + const token = this.advance(); + args.push(token.value); + } + + // Check if this is a block (has {) + if (this.check(TokenType.LBRACE)) { + return this.parseBlock(name, args, startToken); + } + + // It's a simple directive + if (this.check(TokenType.SEMICOLON)) { + this.advance(); // consume ; + } + + return { + type: 'Directive', + name, + args, + range: this.makeRange(startToken, this.previous()), + } as Directive; + } + + private parseBlock(name: string, args: string[], startToken: Token): Statement { + this.advance(); // consume { + + // Handle special block types + switch (name) { + case 'if': + return this.parseIfBlock(args, startToken); + case 'map': + return this.parseMapBlock(args, startToken); + case 'geo': + return this.parseGeoBlock(args, startToken); + case 'upstream': + return this.parseUpstreamBlock(args, startToken); + case 'server': + return this.parseServerBlock(startToken); + case 'location': + return this.parseLocationBlock(args, startToken); + case 'http': + return this.parseHttpBlock(startToken); + case 'events': + return this.parseEventsBlock(startToken); + case 'stream': + return this.parseStreamBlock(startToken); + case 'types': + return this.parseTypesBlock(startToken); + case 'limit_except': + return this.parseLimitExceptBlock(args, startToken); + default: + return this.parseGenericBlock(name, args, startToken); + } + } + + private parseIfBlock(args: string[], startToken: Token): IfBlock { + // Reconstruct the condition from args + const condition = args.join(' '); + const body = this.parseBlockBody(); + + return { + type: 'IfBlock', + condition, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseMapBlock(args: string[], startToken: Token): MapBlock { + const source = args[0] || ''; + const variable = args[1] || ''; + const body = this.parseMapEntries(); + + return { + type: 'MapBlock', + source, + variable, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseMapEntries(): MapEntry[] { + const entries: MapEntry[] = []; + + while (!this.isAtEnd() && !this.check(TokenType.RBRACE)) { + if (this.check(TokenType.COMMENT)) { + this.advance(); // skip comments in map blocks + continue; + } + + if (this.check(TokenType.WORD) || this.check(TokenType.QUOTED_STRING) || this.check(TokenType.VARIABLE)) { + const startToken = this.peek(); + const match = this.advance().value; + + let value = ''; + if (this.check(TokenType.WORD) || this.check(TokenType.QUOTED_STRING) || this.check(TokenType.VARIABLE)) { + value = this.advance().value; + } + + if (this.check(TokenType.SEMICOLON)) { + this.advance(); + } + + entries.push({ + type: 'MapEntry', + match, + value, + range: this.makeRange(startToken, this.previous()), + }); + } else { + this.advance(); // skip unknown tokens + } + } + + if (this.check(TokenType.RBRACE)) { + this.advance(); + } + + return entries; + } + + private parseGeoBlock(args: string[], startToken: Token): GeoBlock { + let address: string | undefined; + let variable: string; + + if (args.length >= 2) { + address = args[0]; + variable = args[1]; + } else { + variable = args[0] || ''; + } + + const body = this.parseMapEntries(); + + return { + type: 'GeoBlock', + variable, + address, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseUpstreamBlock(args: string[], startToken: Token): UpstreamBlock { + const name = args[0] || ''; + const body = this.parseBlockBody(); + + return { + type: 'UpstreamBlock', + name, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseServerBlock(startToken: Token): ServerBlock { + const body = this.parseBlockBody(); + + return { + type: 'ServerBlock', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseLocationBlock(args: string[], startToken: Token): LocationBlock { + let modifier: LocationBlock['modifier']; + let path: string; + + // Check for location modifiers + if (args.length >= 2 && ['=', '~', '~*', '^~', '@'].includes(args[0])) { + modifier = args[0] as LocationBlock['modifier']; + path = args.slice(1).join(' '); + } else if (args.length >= 1 && args[0].startsWith('@')) { + modifier = '@'; + path = args[0]; + } else { + path = args.join(' '); + } + + const body = this.parseBlockBody(); + + return { + type: 'LocationBlock', + modifier, + path, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseHttpBlock(startToken: Token): HttpBlock { + const body = this.parseBlockBody(); + + return { + type: 'HttpBlock', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseEventsBlock(startToken: Token): EventsBlock { + const body = this.parseBlockBody(); + + return { + type: 'EventsBlock', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseStreamBlock(startToken: Token): StreamBlock { + const body = this.parseBlockBody(); + + return { + type: 'StreamBlock', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseTypesBlock(startToken: Token): TypesBlock { + const body = this.parseBlockBody(); + + return { + type: 'TypesBlock', + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseLimitExceptBlock(args: string[], startToken: Token): LimitExceptBlock { + const methods = args; + const body = this.parseBlockBody(); + + return { + type: 'LimitExceptBlock', + methods, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseGenericBlock(name: string, args: string[], startToken: Token): Block { + const body = this.parseBlockBody(); + + return { + type: 'Block', + name, + args, + body, + range: this.makeRange(startToken, this.previous()), + }; + } + + private parseBlockBody(): Statement[] { + const body: Statement[] = []; + + while (!this.isAtEnd() && !this.check(TokenType.RBRACE)) { + const stmt = this.parseStatement(); + if (stmt) { + body.push(stmt); + } + } + + if (this.check(TokenType.RBRACE)) { + this.advance(); + } + + return body; + } + + private check(type: TokenType): boolean { + if (this.isAtEnd()) return false; + return this.peek().type === type; + } + + private advance(): Token { + if (!this.isAtEnd()) this.current++; + return this.previous(); + } + + private peek(): Token { + return this.tokens[this.current]; + } + + private previous(): Token { + return this.tokens[this.current - 1]; + } + + private isAtEnd(): boolean { + return this.peek().type === TokenType.EOF; + } + + private makeRange(start: Token, end: Token): Range { + return { + start: start.range.start, + end: end.range.end, + }; + } +} + +/** + * Parse nginx configuration string into AST + */ +export function parse(input: string): NginxConfig { + const parser = new Parser(); + return parser.parse(input); +} diff --git a/packages/nginx-parser/src/types.ts b/packages/nginx-parser/src/types.ts new file mode 100644 index 0000000..0204f13 --- /dev/null +++ b/packages/nginx-parser/src/types.ts @@ -0,0 +1,191 @@ +/** + * Range represents a position in the source text + */ +export interface Range { + start: Position; + end: Position; +} + +/** + * Position represents a line and column in the source text + */ +export interface Position { + line: number; + column: number; +} + +/** + * Base node type for all AST nodes + */ +export interface BaseNode { + type: string; + range?: Range; +} + +/** + * Comment node + */ +export interface Comment extends BaseNode { + type: 'Comment'; + value: string; +} + +/** + * Directive node - a simple nginx directive like "worker_processes 4;" + */ +export interface Directive extends BaseNode { + type: 'Directive'; + name: string; + args: string[]; +} + +/** + * Block node - a directive with a body like "server { ... }" + */ +export interface Block extends BaseNode { + type: 'Block'; + name: string; + args: string[]; + body: Statement[]; +} + +/** + * If block - special block for conditional logic + */ +export interface IfBlock extends BaseNode { + type: 'IfBlock'; + condition: string; + body: Statement[]; +} + +/** + * Map block - special block for variable mapping + */ +export interface MapBlock extends BaseNode { + type: 'MapBlock'; + source: string; + variable: string; + body: MapEntry[]; +} + +/** + * Map entry - a single mapping in a map block + */ +export interface MapEntry extends BaseNode { + type: 'MapEntry'; + match: string; + value: string; +} + +/** + * Geo block - special block for geo-based variable mapping + */ +export interface GeoBlock extends BaseNode { + type: 'GeoBlock'; + variable: string; + address?: string; + body: MapEntry[]; +} + +/** + * Upstream block - defines a group of servers + */ +export interface UpstreamBlock extends BaseNode { + type: 'UpstreamBlock'; + name: string; + body: Statement[]; +} + +/** + * Server block - defines a virtual server + */ +export interface ServerBlock extends BaseNode { + type: 'ServerBlock'; + body: Statement[]; +} + +/** + * Location block - defines request handling for a URI + */ +export interface LocationBlock extends BaseNode { + type: 'LocationBlock'; + modifier?: '=' | '~' | '~*' | '^~' | '@'; + path: string; + body: Statement[]; +} + +/** + * Http block - the main http context + */ +export interface HttpBlock extends BaseNode { + type: 'HttpBlock'; + body: Statement[]; +} + +/** + * Events block - the events context + */ +export interface EventsBlock extends BaseNode { + type: 'EventsBlock'; + body: Statement[]; +} + +/** + * Stream block - for TCP/UDP proxying + */ +export interface StreamBlock extends BaseNode { + type: 'StreamBlock'; + body: Statement[]; +} + +/** + * Types block - for MIME type definitions + */ +export interface TypesBlock extends BaseNode { + type: 'TypesBlock'; + body: Statement[]; +} + +/** + * Limit except block - for limiting HTTP methods + */ +export interface LimitExceptBlock extends BaseNode { + type: 'LimitExceptBlock'; + methods: string[]; + body: Statement[]; +} + +/** + * Statement is any valid nginx statement + */ +export type Statement = + | Directive + | Block + | IfBlock + | MapBlock + | GeoBlock + | UpstreamBlock + | ServerBlock + | LocationBlock + | HttpBlock + | EventsBlock + | StreamBlock + | TypesBlock + | LimitExceptBlock + | Comment; + +/** + * NginxConfig is the root AST node + */ +export interface NginxConfig extends BaseNode { + type: 'NginxConfig'; + body: Statement[]; +} + +/** + * Any AST node + */ +export type AstNode = + | NginxConfig + | Statement + | MapEntry; diff --git a/packages/nginx-parser/test-utils/index.ts b/packages/nginx-parser/test-utils/index.ts new file mode 100644 index 0000000..0ce31f6 --- /dev/null +++ b/packages/nginx-parser/test-utils/index.ts @@ -0,0 +1,34 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * Read a fixture file + */ +export function readFixture(fixturePath: string): string { + const fullPath = path.resolve(__dirname, '../../../__fixtures__', fixturePath); + return fs.readFileSync(fullPath, 'utf-8'); +} + +/** + * Get all fixture files in a directory + */ +export function getFixtures(dir: string): string[] { + const fullPath = path.resolve(__dirname, '../../../__fixtures__', dir); + if (!fs.existsSync(fullPath)) { + return []; + } + return fs.readdirSync(fullPath) + .filter((file) => file.endsWith('.conf') || file.endsWith('.nginx')) + .map((file) => path.join(dir, file)); +} + +/** + * Normalize whitespace for comparison + */ +export function normalizeWhitespace(str: string): string { + return str + .split('\n') + .map((line) => line.trimEnd()) + .filter((line) => line.length > 0) + .join('\n'); +} diff --git a/packages/nginx-parser/tsconfig.esm.json b/packages/nginx-parser/tsconfig.esm.json new file mode 100644 index 0000000..f106773 --- /dev/null +++ b/packages/nginx-parser/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "ES2020" + } +} diff --git a/packages/nginx-parser/tsconfig.json b/packages/nginx-parser/tsconfig.json new file mode 100644 index 0000000..c1ce63f --- /dev/null +++ b/packages/nginx-parser/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "__tests__"] +} diff --git a/packages/policy-engine/README.md b/packages/policy-engine/README.md new file mode 100644 index 0000000..9533d61 --- /dev/null +++ b/packages/policy-engine/README.md @@ -0,0 +1,196 @@ +# policy-engine + +TypeScript policy engine with deterministic evaluation. Define authorization policies as pure TypeScript functions that return allow/deny decisions with obligations. + +## Installation + +```bash +npm install policy-engine +``` + +## Usage + +### Define a Policy + +```typescript +import type { PolicyModule } from 'policy-engine'; + +const policy: PolicyModule = { + id: 'api.auth', + version: '1.0.0', + description: 'API authentication policy', + + expects: { + request: ['path'], + claims: ['sub'], + }, + + evaluate(ctx, data, h) { + // Public endpoints - allow without auth + if (h.match.prefix(ctx.request.path, '/api/public')) { + return { + effect: 'allow', + reasons: [{ code: 'public', message: 'Public endpoint' }], + }; + } + + // Require authentication for other endpoints + if (!ctx.identity.subject) { + return { + effect: 'deny', + reasons: [{ code: 'unauthenticated', message: 'Authentication required' }], + }; + } + + return { + effect: 'allow', + reasons: [{ code: 'authenticated', message: 'User authenticated' }], + obligations: [ + { kind: 'setHeader', args: { name: 'X-User-Id', value: ctx.identity.subject } }, + ], + }; + }, +}; + +export default policy; +``` + +### Evaluate a Policy + +```typescript +import { evaluatePolicy } from 'policy-engine'; +import policy from './my-policy'; + +const ctx = { + request: { + id: 'req-123', + time: new Date().toISOString(), + path: '/api/users', + method: 'GET', + }, + identity: { + subject: 'user-456', + roles: ['user'], + claims: { sub: 'user-456' }, + }, + env: { + stage: 'prod', + }, +}; + +const data = { + rbac: { + user: { allowOps: ['read'] }, + admin: { allowOps: ['read', 'write', 'delete'] }, + }, +}; + +const result = evaluatePolicy(policy, ctx, data); + +console.log(result.decision.effect); // 'allow' or 'deny' +console.log(result.decision.reasons); // explanation +console.log(result.decision.obligations); // side effects to apply +``` + +### Evaluate Multiple Policies + +```typescript +import { evaluatePolicies } from 'policy-engine'; + +const result = evaluatePolicies([authPolicy, rbacPolicy, rateLimitPolicy], ctx, data); + +// Uses "deny overrides" - any deny results in overall deny +// Obligations from all allowing policies are combined +``` + +## API + +### Types + +#### `Decision` +```typescript +interface Decision { + effect: 'allow' | 'deny'; + reasons: Reason[]; + obligations?: Obligation[]; + trace?: TraceStep[]; +} +``` + +#### `PolicyModule` +```typescript +interface PolicyModule { + id: string; + version: string; + description?: string; + expects?: PolicyExpects; + evaluate: (ctx: PolicyContext, data: PolicyData, h: PolicyHelpers) => Decision; +} +``` + +#### `Obligation` +```typescript +interface Obligation { + kind: 'setHeader' | 'rateLimit' | 'rewrite' | 'log' | 'mask' | 'route' | 'cache' | 'cors'; + args: Record; +} +``` + +### Helpers + +The `PolicyHelpers` object provides safe, deterministic operations: + +```typescript +interface PolicyHelpers { + // Quantifiers + all(items: T[], pred: (x: T) => boolean): boolean; + any(items: T[], pred: (x: T) => boolean): boolean; + none(items: T[], pred: (x: T) => boolean): boolean; + count(items: T[], pred: (x: T) => boolean): number; + find(items: T[], pred: (x: T) => boolean): T | undefined; + + // String matching + match: { + exact(a?: string, b?: string): boolean; + iexact(a?: string, b?: string): boolean; + prefix(value?: string, prefix: string): boolean; + suffix(value?: string, suffix: string): boolean; + glob(value?: string, pattern: string): boolean; + regex(value?: string, pattern: string): boolean; + }; + + // Safe access + get(obj: unknown, path: string, fallback: T): T; + defined(value: unknown): boolean; + empty(value: unknown[] | string | undefined | null): boolean; + includes(list: T[], value: T): boolean; +} +``` + +### Validation + +```typescript +import { validate, validateModule } from 'policy-engine'; + +// Validate module structure +const moduleResult = validateModule(policy); + +// Validate module + context + data +const fullResult = validate(policy, ctx, data); + +if (!fullResult.valid) { + console.error(fullResult.errors); +} +``` + +## Design Principles + +1. **TypeScript is the policy language** - No DSL to learn +2. **Pure functions** - No side effects, deterministic evaluation +3. **Safe helpers** - Never throw, always return sensible defaults +4. **Composable** - Combine multiple policies with deny-overrides +5. **Explainable** - Trace mode for debugging decisions + +## License + +MIT diff --git a/packages/policy-engine/__tests__/evaluator.test.ts b/packages/policy-engine/__tests__/evaluator.test.ts new file mode 100644 index 0000000..fb37fdd --- /dev/null +++ b/packages/policy-engine/__tests__/evaluator.test.ts @@ -0,0 +1,375 @@ +import { + allow, + allowWith, + deny, + evaluatePolicies, + evaluatePolicy, +} from '../src/evaluator'; +import type { PolicyContext, PolicyData,PolicyModule } from '../src/types'; + +describe('evaluatePolicy', () => { + const createContext = (overrides?: Partial): PolicyContext => ({ + request: { + id: 'req-123', + time: new Date().toISOString(), + method: 'GET', + path: '/api/users', + ...overrides?.request, + }, + identity: { + subject: 'user-456', + roles: ['user'], + groups: [], + claims: {}, + ...overrides?.identity, + }, + env: { + stage: 'dev', + ...overrides?.env, + }, + }); + + const createData = (overrides?: Partial): PolicyData => ({ + ...overrides, + }); + + it('evaluates a simple allow policy', () => { + const policy: PolicyModule = { + id: 'test.allow', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'allowed', message: 'Access granted' }], + }), + }; + + const result = evaluatePolicy(policy, createContext(), createData()); + + expect(result.decision.effect).toBe('allow'); + expect(result.decision.reasons[0].code).toBe('allowed'); + expect(result.moduleId).toBe('test.allow'); + expect(result.moduleVersion).toBe('1.0.0'); + expect(result.durationMs).toBeGreaterThanOrEqual(0); + }); + + it('evaluates a simple deny policy', () => { + const policy: PolicyModule = { + id: 'test.deny', + version: '1.0.0', + evaluate: () => ({ + effect: 'deny', + reasons: [{ code: 'denied', message: 'Access denied' }], + }), + }; + + const result = evaluatePolicy(policy, createContext(), createData()); + + expect(result.decision.effect).toBe('deny'); + expect(result.decision.reasons[0].code).toBe('denied'); + }); + + it('passes context and data to policy', () => { + const policy: PolicyModule = { + id: 'test.context', + version: '1.0.0', + evaluate: (ctx, data, h) => { + if (h.match.prefix(ctx.request.path, '/api')) { + return { + effect: 'allow', + reasons: [{ code: 'api_access', message: 'API access granted' }], + }; + } + return { + effect: 'deny', + reasons: [{ code: 'not_api', message: 'Not an API path' }], + }; + }, + }; + + const apiResult = evaluatePolicy( + policy, + createContext({ request: { id: '1', time: '', path: '/api/users' } }), + createData() + ); + expect(apiResult.decision.effect).toBe('allow'); + + const webResult = evaluatePolicy( + policy, + createContext({ request: { id: '1', time: '', path: '/web/home' } }), + createData() + ); + expect(webResult.decision.effect).toBe('deny'); + }); + + it('handles policy that uses helpers', () => { + const policy: PolicyModule = { + id: 'test.helpers', + version: '1.0.0', + evaluate: (ctx, data, h) => { + const roles = ctx.identity.roles ?? []; + if (h.any(roles, (r) => r === 'admin')) { + return { + effect: 'allow', + reasons: [{ code: 'admin', message: 'Admin access' }], + }; + } + return { + effect: 'deny', + reasons: [{ code: 'not_admin', message: 'Admin required' }], + }; + }, + }; + + const adminResult = evaluatePolicy( + policy, + createContext({ identity: { subject: 'admin', roles: ['admin'] } }), + createData() + ); + expect(adminResult.decision.effect).toBe('allow'); + + const userResult = evaluatePolicy( + policy, + createContext({ identity: { subject: 'user', roles: ['user'] } }), + createData() + ); + expect(userResult.decision.effect).toBe('deny'); + }); + + it('handles policy that throws', () => { + const policy: PolicyModule = { + id: 'test.throws', + version: '1.0.0', + evaluate: () => { + throw new Error('Policy error'); + }, + }; + + const result = evaluatePolicy(policy, createContext(), createData()); + + expect(result.decision.effect).toBe('deny'); + expect(result.decision.reasons[0].code).toBe('evaluation_error'); + expect(result.decision.reasons[0].message).toContain('Policy error'); + }); + + it('handles policy that returns invalid decision', () => { + const policy: PolicyModule = { + id: 'test.invalid', + version: '1.0.0', + evaluate: () => null as unknown as ReturnType, + }; + + const result = evaluatePolicy(policy, createContext(), createData()); + + expect(result.decision.effect).toBe('deny'); + expect(result.decision.reasons[0].code).toBe('invalid_decision'); + }); + + it('includes obligations in decision', () => { + const policy: PolicyModule = { + id: 'test.obligations', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'allowed', message: 'Access granted' }], + obligations: [ + { kind: 'setHeader', args: { name: 'X-User', value: 'test' } }, + { kind: 'rateLimit', args: { rate: '100r/s' } }, + ], + }), + }; + + const result = evaluatePolicy(policy, createContext(), createData()); + + expect(result.decision.obligations).toHaveLength(2); + expect(result.decision.obligations?.[0].kind).toBe('setHeader'); + expect(result.decision.obligations?.[1].kind).toBe('rateLimit'); + }); +}); + +describe('evaluatePolicies', () => { + const createContext = (): PolicyContext => ({ + request: { id: 'req-123', time: new Date().toISOString() }, + identity: { subject: 'user-456' }, + env: {}, + }); + + it('allows when all policies allow', () => { + const policies: PolicyModule[] = [ + { + id: 'policy1', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p1_ok', message: 'Policy 1 OK' }], + }), + }, + { + id: 'policy2', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p2_ok', message: 'Policy 2 OK' }], + }), + }, + ]; + + const result = evaluatePolicies(policies, createContext(), {}); + + expect(result.decision.effect).toBe('allow'); + expect(result.decision.reasons).toHaveLength(2); + }); + + it('denies when any policy denies (deny overrides)', () => { + const policies: PolicyModule[] = [ + { + id: 'policy1', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p1_ok', message: 'Policy 1 OK' }], + }), + }, + { + id: 'policy2', + version: '1.0.0', + evaluate: () => ({ + effect: 'deny', + reasons: [{ code: 'p2_deny', message: 'Policy 2 denied' }], + }), + }, + { + id: 'policy3', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p3_ok', message: 'Policy 3 OK' }], + }), + }, + ]; + + const result = evaluatePolicies(policies, createContext(), {}); + + expect(result.decision.effect).toBe('deny'); + expect(result.decision.reasons[0].code).toBe('p2_deny'); + }); + + it('short-circuits on first deny', () => { + let policy3Called = false; + + const policies: PolicyModule[] = [ + { + id: 'policy1', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p1_ok', message: 'Policy 1 OK' }], + }), + }, + { + id: 'policy2', + version: '1.0.0', + evaluate: () => ({ + effect: 'deny', + reasons: [{ code: 'p2_deny', message: 'Policy 2 denied' }], + }), + }, + { + id: 'policy3', + version: '1.0.0', + evaluate: () => { + policy3Called = true; + return { + effect: 'allow', + reasons: [{ code: 'p3_ok', message: 'Policy 3 OK' }], + }; + }, + }, + ]; + + evaluatePolicies(policies, createContext(), {}); + + expect(policy3Called).toBe(false); + }); + + it('combines obligations from all allowing policies', () => { + const policies: PolicyModule[] = [ + { + id: 'policy1', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p1_ok', message: 'Policy 1 OK' }], + obligations: [{ kind: 'setHeader', args: { name: 'X-P1', value: '1' } }], + }), + }, + { + id: 'policy2', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p2_ok', message: 'Policy 2 OK' }], + obligations: [{ kind: 'rateLimit', args: { rate: '100r/s' } }], + }), + }, + ]; + + const result = evaluatePolicies(policies, createContext(), {}); + + expect(result.decision.obligations).toHaveLength(2); + }); + + it('includes trace when explain is enabled', () => { + const policies: PolicyModule[] = [ + { + id: 'policy1', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p1_ok', message: 'Policy 1 OK' }], + }), + }, + { + id: 'policy2', + version: '2.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'p2_ok', message: 'Policy 2 OK' }], + }), + }, + ]; + + const result = evaluatePolicies(policies, createContext(), {}, { explain: true }); + + expect(result.decision.trace).toHaveLength(2); + expect(result.decision.trace?.[0].step).toBe('policy1@1.0.0'); + expect(result.decision.trace?.[1].step).toBe('policy2@2.0.0'); + }); +}); + +describe('decision helpers', () => { + it('allow creates allow decision', () => { + const decision = allow('ok', 'Access granted'); + + expect(decision.effect).toBe('allow'); + expect(decision.reasons[0].code).toBe('ok'); + expect(decision.reasons[0].message).toBe('Access granted'); + }); + + it('deny creates deny decision', () => { + const decision = deny('forbidden', 'Access denied'); + + expect(decision.effect).toBe('deny'); + expect(decision.reasons[0].code).toBe('forbidden'); + expect(decision.reasons[0].message).toBe('Access denied'); + }); + + it('allowWith creates allow decision with obligations', () => { + const decision = allowWith('ok', 'Access granted', [ + { kind: 'setHeader', args: { name: 'X-User', value: 'test' } }, + ]); + + expect(decision.effect).toBe('allow'); + expect(decision.obligations).toHaveLength(1); + expect(decision.obligations?.[0].kind).toBe('setHeader'); + }); +}); diff --git a/packages/policy-engine/__tests__/helpers.test.ts b/packages/policy-engine/__tests__/helpers.test.ts new file mode 100644 index 0000000..35abb37 --- /dev/null +++ b/packages/policy-engine/__tests__/helpers.test.ts @@ -0,0 +1,257 @@ +import { createHelpers } from '../src/helpers'; +import type { PolicyHelpers } from '../src/types'; + +describe('PolicyHelpers', () => { + let h: PolicyHelpers; + + beforeEach(() => { + h = createHelpers(); + }); + + describe('all', () => { + it('returns true for empty array', () => { + expect(h.all([], () => false)).toBe(true); + }); + + it('returns true when all items match', () => { + expect(h.all([1, 2, 3], (x) => x > 0)).toBe(true); + }); + + it('returns false when any item does not match', () => { + expect(h.all([1, 2, -1], (x) => x > 0)).toBe(false); + }); + + it('short-circuits on first false', () => { + let count = 0; + h.all([1, -1, 2], (x) => { + count++; + return x > 0; + }); + expect(count).toBe(2); + }); + }); + + describe('any', () => { + it('returns false for empty array', () => { + expect(h.any([], () => true)).toBe(false); + }); + + it('returns true when any item matches', () => { + expect(h.any([1, -2, 3], (x) => x < 0)).toBe(true); + }); + + it('returns false when no items match', () => { + expect(h.any([1, 2, 3], (x) => x < 0)).toBe(false); + }); + + it('short-circuits on first true', () => { + let count = 0; + h.any([1, 2, 3], (x) => { + count++; + return x === 2; + }); + expect(count).toBe(2); + }); + }); + + describe('none', () => { + it('returns true for empty array', () => { + expect(h.none([], () => true)).toBe(true); + }); + + it('returns true when no items match', () => { + expect(h.none([1, 2, 3], (x) => x < 0)).toBe(true); + }); + + it('returns false when any item matches', () => { + expect(h.none([1, -2, 3], (x) => x < 0)).toBe(false); + }); + }); + + describe('count', () => { + it('returns 0 for empty array', () => { + expect(h.count([], () => true)).toBe(0); + }); + + it('counts matching items', () => { + expect(h.count([1, -2, 3, -4], (x) => x < 0)).toBe(2); + }); + }); + + describe('find', () => { + it('returns undefined for empty array', () => { + expect(h.find([], () => true)).toBeUndefined(); + }); + + it('returns first matching item', () => { + expect(h.find([1, 2, 3], (x) => x > 1)).toBe(2); + }); + + it('returns undefined when no match', () => { + expect(h.find([1, 2, 3], (x) => x > 10)).toBeUndefined(); + }); + }); + + describe('match.exact', () => { + it('returns true for equal strings', () => { + expect(h.match.exact('foo', 'foo')).toBe(true); + }); + + it('returns false for different strings', () => { + expect(h.match.exact('foo', 'bar')).toBe(false); + }); + + it('returns false for undefined', () => { + expect(h.match.exact(undefined, 'foo')).toBe(false); + expect(h.match.exact('foo', undefined)).toBe(false); + }); + + it('is case-sensitive', () => { + expect(h.match.exact('Foo', 'foo')).toBe(false); + }); + }); + + describe('match.iexact', () => { + it('returns true for case-insensitive match', () => { + expect(h.match.iexact('Foo', 'foo')).toBe(true); + expect(h.match.iexact('FOO', 'foo')).toBe(true); + }); + + it('returns false for different strings', () => { + expect(h.match.iexact('foo', 'bar')).toBe(false); + }); + }); + + describe('match.prefix', () => { + it('returns true when value starts with prefix', () => { + expect(h.match.prefix('/api/users', '/api')).toBe(true); + }); + + it('returns false when value does not start with prefix', () => { + expect(h.match.prefix('/web/users', '/api')).toBe(false); + }); + + it('returns false for undefined', () => { + expect(h.match.prefix(undefined, '/api')).toBe(false); + }); + }); + + describe('match.suffix', () => { + it('returns true when value ends with suffix', () => { + expect(h.match.suffix('file.json', '.json')).toBe(true); + }); + + it('returns false when value does not end with suffix', () => { + expect(h.match.suffix('file.xml', '.json')).toBe(false); + }); + + it('returns false for undefined', () => { + expect(h.match.suffix(undefined, '.json')).toBe(false); + }); + }); + + describe('match.glob', () => { + it('matches wildcard patterns', () => { + expect(h.match.glob('api.example.com', '*.example.com')).toBe(true); + expect(h.match.glob('foo.example.com', '*.example.com')).toBe(true); + }); + + it('matches single character wildcard', () => { + expect(h.match.glob('file1.txt', 'file?.txt')).toBe(true); + expect(h.match.glob('file12.txt', 'file?.txt')).toBe(false); + }); + + it('returns false for non-matching patterns', () => { + expect(h.match.glob('other.com', '*.example.com')).toBe(false); + }); + + it('returns false for undefined', () => { + expect(h.match.glob(undefined, '*.example.com')).toBe(false); + }); + }); + + describe('match.regex', () => { + it('matches regex patterns', () => { + expect(h.match.regex('/api/v1/users', '^/api/v\\d+')).toBe(true); + }); + + it('returns false for non-matching patterns', () => { + expect(h.match.regex('/web/users', '^/api')).toBe(false); + }); + + it('returns false for invalid regex', () => { + expect(h.match.regex('test', '[invalid')).toBe(false); + }); + + it('returns false for undefined', () => { + expect(h.match.regex(undefined, '.*')).toBe(false); + }); + }); + + describe('get', () => { + it('gets nested property', () => { + const obj = { a: { b: { c: 'value' } } }; + expect(h.get(obj, 'a.b.c', 'default')).toBe('value'); + }); + + it('returns fallback for missing property', () => { + const obj = { a: { b: {} } }; + expect(h.get(obj, 'a.b.c', 'default')).toBe('default'); + }); + + it('returns fallback for null object', () => { + expect(h.get(null, 'a.b', 'default')).toBe('default'); + }); + + it('returns fallback for undefined object', () => { + expect(h.get(undefined, 'a.b', 'default')).toBe('default'); + }); + + it('handles array indices', () => { + const obj = { items: ['a', 'b', 'c'] }; + expect(h.get(obj, 'items.1', 'default')).toBe('b'); + }); + }); + + describe('defined', () => { + it('returns true for defined values', () => { + expect(h.defined('')).toBe(true); + expect(h.defined(0)).toBe(true); + expect(h.defined(false)).toBe(true); + expect(h.defined({})).toBe(true); + }); + + it('returns false for null and undefined', () => { + expect(h.defined(null)).toBe(false); + expect(h.defined(undefined)).toBe(false); + }); + }); + + describe('empty', () => { + it('returns true for empty values', () => { + expect(h.empty('')).toBe(true); + expect(h.empty([])).toBe(true); + expect(h.empty(null)).toBe(true); + expect(h.empty(undefined)).toBe(true); + }); + + it('returns false for non-empty values', () => { + expect(h.empty('hello')).toBe(false); + expect(h.empty([1, 2])).toBe(false); + }); + }); + + describe('includes', () => { + it('returns true when list contains value', () => { + expect(h.includes(['a', 'b', 'c'], 'b')).toBe(true); + }); + + it('returns false when list does not contain value', () => { + expect(h.includes(['a', 'b', 'c'], 'd')).toBe(false); + }); + + it('handles non-array input', () => { + expect(h.includes(null as unknown as string[], 'a')).toBe(false); + }); + }); +}); diff --git a/packages/policy-engine/__tests__/validator.test.ts b/packages/policy-engine/__tests__/validator.test.ts new file mode 100644 index 0000000..3684c5a --- /dev/null +++ b/packages/policy-engine/__tests__/validator.test.ts @@ -0,0 +1,306 @@ +import type { PolicyContext, PolicyData, PolicyModule, Reason } from '../src/types'; +import { + validate, + validateContext, + validateData, + validateModule, +} from '../src/validator'; + +describe('validateModule', () => { + it('validates a correct module', () => { + const module: PolicyModule = { + id: 'test.policy', + version: '1.0.0', + evaluate: () => ({ + effect: 'allow', + reasons: [{ code: 'ok', message: 'OK' }], + }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(true); + expect(result.errors).toHaveLength(0); + }); + + it('rejects non-object module', () => { + const result = validateModule(null); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('invalid_module'); + }); + + it('rejects module without id', () => { + const module = { + version: '1.0.0', + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(false); + expect(result.errors.some((e) => e.code === 'missing_id')).toBe(true); + }); + + it('rejects module with empty id', () => { + const module = { + id: '', + version: '1.0.0', + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(false); + expect(result.errors.some((e) => e.code === 'missing_id')).toBe(true); + }); + + it('rejects module without version', () => { + const module = { + id: 'test.policy', + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(false); + expect(result.errors.some((e) => e.code === 'missing_version')).toBe(true); + }); + + it('rejects module without evaluate function', () => { + const module = { + id: 'test.policy', + version: '1.0.0', + }; + + const result = validateModule(module); + + expect(result.valid).toBe(false); + expect(result.errors.some((e) => e.code === 'missing_evaluate')).toBe(true); + }); + + it('warns about invalid description type', () => { + const module = { + id: 'test.policy', + version: '1.0.0', + description: 123, + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(true); + expect(result.warnings.some((w) => w.code === 'invalid_description')).toBe(true); + }); + + it('warns about invalid expects type', () => { + const module = { + id: 'test.policy', + version: '1.0.0', + expects: 'invalid', + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(true); + expect(result.warnings.some((w) => w.code === 'invalid_expects')).toBe(true); + }); + + it('warns about invalid expects.data type', () => { + const module = { + id: 'test.policy', + version: '1.0.0', + expects: { data: 'not-an-array' }, + evaluate: () => ({ effect: 'allow' as const, reasons: [] as Reason[] }), + }; + + const result = validateModule(module); + + expect(result.valid).toBe(true); + expect(result.warnings.some((w) => w.code === 'invalid_expects_data')).toBe(true); + }); +}); + +describe('validateContext', () => { + const createModule = (expects?: PolicyModule['expects']): PolicyModule => ({ + id: 'test.policy', + version: '1.0.0', + expects, + evaluate: () => ({ effect: 'allow', reasons: [] as Reason[] }), + }); + + const createContext = (overrides?: Partial): PolicyContext => ({ + request: { + id: 'req-123', + time: new Date().toISOString(), + path: '/api/users', + ...overrides?.request, + }, + identity: { + subject: 'user-456', + claims: { ns: 'default', role: 'user' }, + ...overrides?.identity, + }, + env: { + stage: 'dev', + ...overrides?.env, + }, + }); + + it('passes when no expects defined', () => { + const result = validateContext(createModule(), createContext()); + + expect(result.valid).toBe(true); + }); + + it('passes when all expected request fields present', () => { + const module = createModule({ request: ['path', 'id'] }); + const result = validateContext(module, createContext()); + + expect(result.valid).toBe(true); + }); + + it('fails when expected request field missing', () => { + const module = createModule({ request: ['method'] }); + const ctx = createContext(); + delete ctx.request.method; + + const result = validateContext(module, ctx); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('missing_request_field'); + expect(result.errors[0].path).toBe('request.method'); + }); + + it('passes when all expected claims present', () => { + const module = createModule({ claims: ['ns', 'role'] }); + const result = validateContext(module, createContext()); + + expect(result.valid).toBe(true); + }); + + it('fails when expected claim missing', () => { + const module = createModule({ claims: ['admin_level'] }); + const result = validateContext(module, createContext()); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('missing_claim'); + expect(result.errors[0].path).toBe('identity.claims.admin_level'); + }); + + it('passes when all expected env fields present', () => { + const module = createModule({ env: ['stage'] }); + const result = validateContext(module, createContext()); + + expect(result.valid).toBe(true); + }); + + it('fails when expected env field missing', () => { + const module = createModule({ env: ['cluster'] }); + const result = validateContext(module, createContext()); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('missing_env_field'); + }); +}); + +describe('validateData', () => { + const createModule = (expects?: PolicyModule['expects']): PolicyModule => ({ + id: 'test.policy', + version: '1.0.0', + expects, + evaluate: () => ({ effect: 'allow', reasons: [] as Reason[] }), + }); + + it('passes when no expects defined', () => { + const result = validateData(createModule(), {}); + + expect(result.valid).toBe(true); + }); + + it('passes when all expected data fields present', () => { + const module = createModule({ data: ['rbac', 'nsBindings'] }); + const data: PolicyData = { + rbac: { admin: { allowOps: ['*'] } }, + nsBindings: { default: { groups: ['users'] } }, + }; + + const result = validateData(module, data); + + expect(result.valid).toBe(true); + }); + + it('fails when expected data field missing', () => { + const module = createModule({ data: ['egressAllow'] }); + const data: PolicyData = {}; + + const result = validateData(module, data); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('missing_data_field'); + expect(result.errors[0].path).toBe('data.egressAllow'); + }); +}); + +describe('validate', () => { + it('validates module, context, and data together', () => { + const module: PolicyModule = { + id: 'test.policy', + version: '1.0.0', + expects: { + request: ['path'], + claims: ['ns'], + data: ['rbac'], + }, + evaluate: () => ({ effect: 'allow', reasons: [] }), + }; + + const ctx: PolicyContext = { + request: { id: '1', time: '', path: '/api' }, + identity: { subject: 'user', claims: { ns: 'default' } }, + env: {}, + }; + + const data: PolicyData = { + rbac: { user: { allowOps: ['read'] } }, + }; + + const result = validate(module, ctx, data); + + expect(result.valid).toBe(true); + }); + + it('collects errors from all validations', () => { + const module: PolicyModule = { + id: 'test.policy', + version: '1.0.0', + expects: { + request: ['method'], + claims: ['admin'], + data: ['secrets'], + }, + evaluate: () => ({ effect: 'allow', reasons: [] }), + }; + + const ctx: PolicyContext = { + request: { id: '1', time: '' }, + identity: { subject: 'user', claims: {} }, + env: {}, + }; + + const data: PolicyData = {}; + + const result = validate(module, ctx, data); + + expect(result.valid).toBe(false); + expect(result.errors.length).toBeGreaterThanOrEqual(3); + }); + + it('fails early if module is invalid', () => { + const result = validate(null); + + expect(result.valid).toBe(false); + expect(result.errors[0].code).toBe('invalid_module'); + }); +}); diff --git a/packages/policy-engine/jest.config.js b/packages/policy-engine/jest.config.js new file mode 100644 index 0000000..5642f3c --- /dev/null +++ b/packages/policy-engine/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }] + }, + testMatch: ['**/__tests__/**/*.test.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] +}; diff --git a/packages/policy-engine/package.json b/packages/policy-engine/package.json new file mode 100644 index 0000000..4a94ef7 --- /dev/null +++ b/packages/policy-engine/package.json @@ -0,0 +1,42 @@ +{ + "name": "policy-engine", + "version": "0.0.1", + "author": "Constructive ", + "description": "TypeScript policy engine with deterministic evaluation", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/dockerjs", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/dockerjs" + }, + "bugs": { + "url": "https://github.com/constructive-io/dockerjs/issues" + }, + "scripts": { + "copy": "makage assets", + "clean": "makage clean dist", + "prepublishOnly": "npm run build", + "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", + "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", + "lint": "cd ../.. && eslint packages/policy-engine --fix", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "policy", + "engine", + "authorization", + "typescript", + "deterministic" + ], + "devDependencies": { + "makage": "^0.1.8" + } +} diff --git a/packages/policy-engine/src/evaluator.ts b/packages/policy-engine/src/evaluator.ts new file mode 100644 index 0000000..e1806c0 --- /dev/null +++ b/packages/policy-engine/src/evaluator.ts @@ -0,0 +1,207 @@ +import { createHelpers } from './helpers'; +import type { + Decision, + EvaluateOptions, + EvaluationResult, + PolicyContext, + PolicyData, + PolicyModule, +} from './types'; + +/** + * Default evaluation options + */ +const DEFAULT_OPTIONS: Required = { + explain: false, + maxTimeMs: 10, + moduleId: '', + freeze: true, +}; + +/** + * Deep freeze an object to prevent mutations + */ +function deepFreeze(obj: T): T { + if (obj === null || typeof obj !== 'object') { + return obj; + } + + Object.freeze(obj); + + for (const key of Object.keys(obj)) { + const value = (obj as Record)[key]; + if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) { + deepFreeze(value as object); + } + } + + return obj; +} + +/** + * Create a default deny decision for errors + */ +function createErrorDecision(code: string, message: string): Decision { + return { + effect: 'deny', + reasons: [{ code, message }], + }; +} + +/** + * Evaluate a policy module with the given context and data + */ +export function evaluatePolicy( + mod: PolicyModule, + ctx: PolicyContext, + data: PolicyData, + opts?: EvaluateOptions +): EvaluationResult { + const options = { ...DEFAULT_OPTIONS, ...opts }; + const startTime = Date.now(); + const helpers = createHelpers(); + + // Freeze context and data if requested + const frozenCtx = options.freeze ? deepFreeze({ ...ctx }) : ctx; + const frozenData = options.freeze ? deepFreeze({ ...data }) : data; + + let decision: Decision; + + try { + // Execute the policy evaluation + decision = mod.evaluate(frozenCtx, frozenData, helpers); + + // Validate the decision structure + if (!decision || typeof decision !== 'object') { + decision = createErrorDecision( + 'invalid_decision', + 'Policy returned invalid decision' + ); + } + + if (!decision.effect || !['allow', 'deny'].includes(decision.effect)) { + decision = createErrorDecision( + 'invalid_effect', + 'Policy returned invalid effect' + ); + } + + if (!Array.isArray(decision.reasons)) { + decision.reasons = []; + } + } catch (error) { + // Policy threw an exception - return deny + const message = error instanceof Error ? error.message : 'Unknown error'; + decision = createErrorDecision('evaluation_error', `Policy evaluation failed: ${message}`); + } + + const endTime = Date.now(); + const durationMs = endTime - startTime; + + return { + decision, + moduleId: options.moduleId || mod.id, + moduleVersion: mod.version, + evaluatedAt: new Date(startTime).toISOString(), + durationMs, + }; +} + +/** + * Evaluate multiple policies and combine results + * Uses "deny overrides" - any deny results in overall deny + */ +export function evaluatePolicies( + modules: PolicyModule[], + ctx: PolicyContext, + data: PolicyData, + opts?: EvaluateOptions +): EvaluationResult { + const startTime = Date.now(); + const results: EvaluationResult[] = []; + + for (const mod of modules) { + const result = evaluatePolicy(mod, ctx, data, opts); + results.push(result); + + // Short-circuit on deny (deny overrides) + if (result.decision.effect === 'deny') { + return { + decision: { + effect: 'deny', + reasons: result.decision.reasons, + obligations: result.decision.obligations, + trace: opts?.explain + ? results.map((r) => ({ + step: `${r.moduleId}@${r.moduleVersion}`, + ok: r.decision.effect === 'allow', + meta: { reasons: r.decision.reasons }, + })) + : undefined, + }, + moduleId: 'combined', + moduleVersion: '0.0.0', + evaluatedAt: new Date(startTime).toISOString(), + durationMs: Date.now() - startTime, + }; + } + } + + // All policies allowed - combine obligations + const allObligations = results.flatMap((r) => r.decision.obligations ?? []); + const allReasons = results.flatMap((r) => r.decision.reasons); + + return { + decision: { + effect: 'allow', + reasons: allReasons, + obligations: allObligations.length > 0 ? allObligations : undefined, + trace: opts?.explain + ? results.map((r) => ({ + step: `${r.moduleId}@${r.moduleVersion}`, + ok: r.decision.effect === 'allow', + meta: { reasons: r.decision.reasons }, + })) + : undefined, + }, + moduleId: 'combined', + moduleVersion: '0.0.0', + evaluatedAt: new Date(startTime).toISOString(), + durationMs: Date.now() - startTime, + }; +} + +/** + * Create a simple allow decision + */ +export function allow(code: string, message: string): Decision { + return { + effect: 'allow', + reasons: [{ code, message }], + }; +} + +/** + * Create a simple deny decision + */ +export function deny(code: string, message: string): Decision { + return { + effect: 'deny', + reasons: [{ code, message }], + }; +} + +/** + * Create an allow decision with obligations + */ +export function allowWith( + code: string, + message: string, + obligations: Decision['obligations'] +): Decision { + return { + effect: 'allow', + reasons: [{ code, message }], + obligations, + }; +} diff --git a/packages/policy-engine/src/helpers.ts b/packages/policy-engine/src/helpers.ts new file mode 100644 index 0000000..c6cc395 --- /dev/null +++ b/packages/policy-engine/src/helpers.ts @@ -0,0 +1,209 @@ +import type { MatchHelpers,PolicyHelpers } from './types'; + +/** + * Convert a simple glob pattern to a regex + * Supports * (any characters) and ? (single character) + */ +function globToRegex(pattern: string): RegExp { + const escaped = pattern + .replace(/[.+^${}()|[\]\\]/g, '\\$&') + .replace(/\*/g, '.*') + .replace(/\?/g, '.'); + return new RegExp(`^${escaped}$`); +} + +/** + * Safe regex execution with basic protection + */ +function safeRegexTest(pattern: string, value: string): boolean { + try { + const regex = new RegExp(pattern); + return regex.test(value); + } catch { + return false; + } +} + +/** + * Get a nested property from an object using dot notation + * Never throws - returns fallback if path doesn't exist + */ +function getPath(obj: unknown, path: string, fallback: T): T { + if (obj === null || obj === undefined) { + return fallback; + } + + const parts = path.split('.'); + let current: unknown = obj; + + for (const part of parts) { + if (current === null || current === undefined) { + return fallback; + } + if (typeof current !== 'object') { + return fallback; + } + current = (current as Record)[part]; + } + + if (current === undefined) { + return fallback; + } + + return current as T; +} + +/** + * Match helpers implementation + */ +const matchHelpers: MatchHelpers = { + exact(a?: string, b?: string): boolean { + if (a === undefined || b === undefined) { + return false; + } + return a === b; + }, + + prefix(value: string | undefined, prefix: string): boolean { + if (value === undefined) { + return false; + } + return value.startsWith(prefix); + }, + + suffix(value: string | undefined, suffix: string): boolean { + if (value === undefined) { + return false; + } + return value.endsWith(suffix); + }, + + glob(value: string | undefined, pattern: string): boolean { + if (value === undefined) { + return false; + } + try { + const regex = globToRegex(pattern); + return regex.test(value); + } catch { + return false; + } + }, + + regex(value: string | undefined, pattern: string): boolean { + if (value === undefined) { + return false; + } + return safeRegexTest(pattern, value); + }, + + iexact(a?: string, b?: string): boolean { + if (a === undefined || b === undefined) { + return false; + } + return a.toLowerCase() === b.toLowerCase(); + }, +}; + +/** + * Create a PolicyHelpers instance + */ +export function createHelpers(): PolicyHelpers { + return { + all(items: readonly T[], pred: (x: T) => boolean): boolean { + if (!Array.isArray(items) || items.length === 0) { + return true; + } + for (const item of items) { + if (!pred(item)) { + return false; + } + } + return true; + }, + + any(items: readonly T[], pred: (x: T) => boolean): boolean { + if (!Array.isArray(items)) { + return false; + } + for (const item of items) { + if (pred(item)) { + return true; + } + } + return false; + }, + + none(items: readonly T[], pred: (x: T) => boolean): boolean { + if (!Array.isArray(items) || items.length === 0) { + return true; + } + for (const item of items) { + if (pred(item)) { + return false; + } + } + return true; + }, + + count(items: readonly T[], pred: (x: T) => boolean): number { + if (!Array.isArray(items)) { + return 0; + } + let count = 0; + for (const item of items) { + if (pred(item)) { + count++; + } + } + return count; + }, + + find(items: readonly T[], pred: (x: T) => boolean): T | undefined { + if (!Array.isArray(items)) { + return undefined; + } + for (const item of items) { + if (pred(item)) { + return item; + } + } + return undefined; + }, + + match: matchHelpers, + + get(obj: unknown, path: string, fallback: T): T { + return getPath(obj, path, fallback); + }, + + defined(value: unknown): boolean { + return value !== null && value !== undefined; + }, + + empty(value: unknown[] | string | undefined | null): boolean { + if (value === undefined || value === null) { + return true; + } + if (typeof value === 'string') { + return value.length === 0; + } + if (Array.isArray(value)) { + return value.length === 0; + } + return true; + }, + + includes(list: readonly T[], value: T): boolean { + if (!Array.isArray(list)) { + return false; + } + return list.includes(value); + }, + }; +} + +/** + * Default helpers instance + */ +export const helpers = createHelpers(); diff --git a/packages/policy-engine/src/index.ts b/packages/policy-engine/src/index.ts new file mode 100644 index 0000000..7600343 --- /dev/null +++ b/packages/policy-engine/src/index.ts @@ -0,0 +1,42 @@ +// Core types +export type { + Decision, + Effect, + EnvironmentContext, + EvaluateOptions, + EvaluationResult, + IdentityContext, + MatchHelpers, + Obligation, + Policy, + PolicyContext, + PolicyData, + PolicyExpects, + PolicyHelpers, + PolicyModule, + Reason, + RequestContext, + TraceStep, + ValidationError, + ValidationResult, +} from './types'; + +// Helpers +export { createHelpers, helpers } from './helpers'; + +// Evaluator +export { + allow, + allowWith, + deny, + evaluatePolicies, + evaluatePolicy, +} from './evaluator'; + +// Validator +export { + validate, + validateContext, + validateData, + validateModule, +} from './validator'; diff --git a/packages/policy-engine/src/types.ts b/packages/policy-engine/src/types.ts new file mode 100644 index 0000000..ba087fc --- /dev/null +++ b/packages/policy-engine/src/types.ts @@ -0,0 +1,272 @@ +/** + * Effect represents the outcome of a policy decision + */ +export type Effect = 'allow' | 'deny'; + +/** + * Reason explains why a decision was made + */ +export interface Reason { + /** Stable identifier for analytics and programmatic handling */ + code: string; + /** Human-readable explanation */ + message: string; + /** Optional path to the relevant context field (e.g., "request.path") */ + path?: string; + /** Optional metadata for debugging */ + meta?: Record; +} + +/** + * Obligation represents a side effect to apply after the decision + * These map to Nginx directives when compiled + */ +export interface Obligation { + kind: + | 'setHeader' + | 'rateLimit' + | 'rewrite' + | 'log' + | 'mask' + | 'route' + | 'cache' + | 'cors'; + args: Record; +} + +/** + * TraceStep records a step in policy evaluation for debugging + */ +export interface TraceStep { + step: string; + ok: boolean; + meta?: unknown; +} + +/** + * Decision is the result of policy evaluation + */ +export interface Decision { + effect: Effect; + reasons: Reason[]; + obligations?: Obligation[]; + /** Optional trace for debugging (can be disabled in production) */ + trace?: TraceStep[]; +} + +/** + * RequestContext contains information about the incoming request + */ +export interface RequestContext { + /** Unique request identifier */ + id: string; + /** Request timestamp in ISO format */ + time: string; + /** Client IP address */ + ip?: string; + /** HTTP method (GET, POST, etc.) */ + method?: string; + /** Request host */ + host?: string; + /** Request path */ + path?: string; + /** Request headers */ + headers?: Record; + /** Query parameters */ + query?: Record; + /** Request body (parsed) */ + body?: unknown; + /** Kubernetes/mesh namespace */ + namespace?: string; + /** Service name */ + service?: string; + /** Operation being performed (e.g., "connect", "query", "deploy") */ + operation?: string; + /** Destination for egress policies */ + destination?: { + host: string; + port?: number; + protocol?: string; + }; +} + +/** + * IdentityContext contains information about the authenticated identity + */ +export interface IdentityContext { + /** User or service principal identifier */ + subject: string; + /** Assigned roles */ + roles?: string[]; + /** Group memberships */ + groups?: string[]; + /** JWT claims or other identity attributes */ + claims?: Record; +} + +/** + * EnvironmentContext contains deployment environment information + */ +export interface EnvironmentContext { + /** Tenant identifier for multi-tenant systems */ + tenantId?: string; + /** Cluster name */ + cluster?: string; + /** Region */ + region?: string; + /** Deployment stage */ + stage?: 'dev' | 'staging' | 'prod'; + /** Additional environment variables */ + vars?: Record; +} + +/** + * PolicyContext is the complete context passed to policy evaluation + */ +export interface PolicyContext { + request: RequestContext; + identity: IdentityContext; + env: EnvironmentContext; +} + +/** + * PolicyData contains static configuration and facts for policy evaluation + */ +export interface PolicyData { + /** Namespace to group bindings */ + nsBindings?: Record; + /** Egress allowlist per namespace */ + egressAllow?: Record>; + /** RBAC role definitions */ + rbac?: Record; + /** Rate limit configurations */ + rateLimits?: Record; + /** Allow arbitrary additional data */ + [key: string]: unknown; +} + +/** + * MatchHelpers provides safe string matching operations + */ +export interface MatchHelpers { + /** Exact string equality (case-sensitive) */ + exact(a?: string, b?: string): boolean; + /** Check if value starts with prefix */ + prefix(value: string | undefined, prefix: string): boolean; + /** Check if value ends with suffix */ + suffix(value: string | undefined, suffix: string): boolean; + /** Simple glob matching (supports * and ?) */ + glob(value: string | undefined, pattern: string): boolean; + /** Safe regex matching (with timeout protection) */ + regex(value: string | undefined, pattern: string): boolean; + /** Case-insensitive exact match */ + iexact(a?: string, b?: string): boolean; +} + +/** + * PolicyHelpers provides safe, deterministic operations for policy evaluation + */ +export interface PolicyHelpers { + /** Check if all items satisfy the predicate */ + all(items: readonly T[], pred: (x: T) => boolean): boolean; + /** Check if any item satisfies the predicate */ + any(items: readonly T[], pred: (x: T) => boolean): boolean; + /** Check if no items satisfy the predicate */ + none(items: readonly T[], pred: (x: T) => boolean): boolean; + /** Count items that satisfy the predicate */ + count(items: readonly T[], pred: (x: T) => boolean): number; + /** Find first item that satisfies the predicate */ + find(items: readonly T[], pred: (x: T) => boolean): T | undefined; + /** String matching helpers */ + match: MatchHelpers; + /** Safe property access that never throws */ + get(obj: unknown, path: string, fallback: T): T; + /** Check if a value is defined (not null or undefined) */ + defined(value: unknown): boolean; + /** Check if an array or string is empty */ + empty(value: unknown[] | string | undefined | null): boolean; + /** Check if a value is in a list */ + includes(list: readonly T[], value: T): boolean; +} + +/** + * Policy is the core evaluation function type + */ +export type Policy = ( + ctx: PolicyContext, + data: PolicyData, + h: PolicyHelpers +) => Decision; + +/** + * PolicyExpects declares the inputs a policy requires + */ +export interface PolicyExpects { + /** Required data fields */ + data?: string[]; + /** Required identity claims */ + claims?: string[]; + /** Required request fields */ + request?: string[]; + /** Required environment fields */ + env?: string[]; +} + +/** + * PolicyModule is a versioned, composable policy unit + */ +export interface PolicyModule { + /** Unique policy identifier (e.g., "constructive.k8s.namespace.bind") */ + id: string; + /** Semantic version */ + version: string; + /** Human-readable description */ + description?: string; + /** Declared input requirements for validation */ + expects?: PolicyExpects; + /** The policy evaluation function */ + evaluate: Policy; +} + +/** + * EvaluateOptions configures policy evaluation + */ +export interface EvaluateOptions { + /** Enable trace/explain mode for debugging */ + explain?: boolean; + /** Maximum execution time in milliseconds */ + maxTimeMs?: number; + /** Override module ID for logging */ + moduleId?: string; + /** Freeze context and data objects */ + freeze?: boolean; +} + +/** + * EvaluationResult wraps a Decision with metadata + */ +export interface EvaluationResult { + decision: Decision; + moduleId: string; + moduleVersion: string; + evaluatedAt: string; + durationMs: number; +} + +/** + * ValidationError represents a policy validation failure + */ +export interface ValidationError { + code: string; + message: string; + path?: string; +} + +/** + * ValidationResult is the result of policy module validation + */ +export interface ValidationResult { + valid: boolean; + errors: ValidationError[]; + warnings: ValidationError[]; +} diff --git a/packages/policy-engine/src/validator.ts b/packages/policy-engine/src/validator.ts new file mode 100644 index 0000000..4041015 --- /dev/null +++ b/packages/policy-engine/src/validator.ts @@ -0,0 +1,250 @@ +import type { + EnvironmentContext, + PolicyContext, + PolicyData, + PolicyModule, + RequestContext, + ValidationError, + ValidationResult, +} from './types'; + +/** + * Get a field value from an object by key + */ +function getField(obj: RequestContext | EnvironmentContext, field: string): unknown { + return (obj as unknown as Record)[field]; +} + +/** + * Validate that a policy module has the required structure + */ +export function validateModule(mod: unknown): ValidationResult { + const errors: ValidationError[] = []; + const warnings: ValidationError[] = []; + + if (!mod || typeof mod !== 'object') { + errors.push({ + code: 'invalid_module', + message: 'Policy module must be an object', + }); + return { valid: false, errors, warnings }; + } + + const module = mod as Record; + + // Check required fields + if (typeof module.id !== 'string' || module.id.length === 0) { + errors.push({ + code: 'missing_id', + message: 'Policy module must have a non-empty id string', + path: 'id', + }); + } + + if (typeof module.version !== 'string' || module.version.length === 0) { + errors.push({ + code: 'missing_version', + message: 'Policy module must have a non-empty version string', + path: 'version', + }); + } + + if (typeof module.evaluate !== 'function') { + errors.push({ + code: 'missing_evaluate', + message: 'Policy module must have an evaluate function', + path: 'evaluate', + }); + } + + // Check optional fields + if (module.description !== undefined && typeof module.description !== 'string') { + warnings.push({ + code: 'invalid_description', + message: 'Policy module description should be a string', + path: 'description', + }); + } + + if (module.expects !== undefined) { + if (typeof module.expects !== 'object') { + warnings.push({ + code: 'invalid_expects', + message: 'Policy module expects should be an object', + path: 'expects', + }); + } else { + const expects = module.expects as Record; + + if (expects.data !== undefined && !Array.isArray(expects.data)) { + warnings.push({ + code: 'invalid_expects_data', + message: 'Policy module expects.data should be an array', + path: 'expects.data', + }); + } + + if (expects.claims !== undefined && !Array.isArray(expects.claims)) { + warnings.push({ + code: 'invalid_expects_claims', + message: 'Policy module expects.claims should be an array', + path: 'expects.claims', + }); + } + + if (expects.request !== undefined && !Array.isArray(expects.request)) { + warnings.push({ + code: 'invalid_expects_request', + message: 'Policy module expects.request should be an array', + path: 'expects.request', + }); + } + + if (expects.env !== undefined && !Array.isArray(expects.env)) { + warnings.push({ + code: 'invalid_expects_env', + message: 'Policy module expects.env should be an array', + path: 'expects.env', + }); + } + } + } + + return { + valid: errors.length === 0, + errors, + warnings, + }; +} + +/** + * Validate that context satisfies a policy module's expectations + */ +export function validateContext( + mod: PolicyModule, + ctx: PolicyContext +): ValidationResult { + const errors: ValidationError[] = []; + const warnings: ValidationError[] = []; + + if (!mod.expects) { + return { valid: true, errors, warnings }; + } + + // Check required request fields + if (mod.expects.request) { + for (const field of mod.expects.request) { + const value = getField(ctx.request, field); + if (value === undefined || value === null) { + errors.push({ + code: 'missing_request_field', + message: `Required request field '${field}' is missing`, + path: `request.${field}`, + }); + } + } + } + + // Check required claims + if (mod.expects.claims) { + for (const claim of mod.expects.claims) { + const value = ctx.identity.claims?.[claim]; + if (value === undefined || value === null) { + errors.push({ + code: 'missing_claim', + message: `Required claim '${claim}' is missing`, + path: `identity.claims.${claim}`, + }); + } + } + } + + // Check required env fields + if (mod.expects.env) { + for (const field of mod.expects.env) { + const value = getField(ctx.env, field); + if (value === undefined || value === null) { + errors.push({ + code: 'missing_env_field', + message: `Required environment field '${field}' is missing`, + path: `env.${field}`, + }); + } + } + } + + return { + valid: errors.length === 0, + errors, + warnings, + }; +} + +/** + * Validate that data satisfies a policy module's expectations + */ +export function validateData( + mod: PolicyModule, + data: PolicyData +): ValidationResult { + const errors: ValidationError[] = []; + const warnings: ValidationError[] = []; + + if (!mod.expects?.data) { + return { valid: true, errors, warnings }; + } + + for (const field of mod.expects.data) { + const value = data[field]; + if (value === undefined) { + errors.push({ + code: 'missing_data_field', + message: `Required data field '${field}' is missing`, + path: `data.${field}`, + }); + } + } + + return { + valid: errors.length === 0, + errors, + warnings, + }; +} + +/** + * Validate a policy module and its inputs + */ +export function validate( + mod: unknown, + ctx?: PolicyContext, + data?: PolicyData +): ValidationResult { + const moduleResult = validateModule(mod); + + if (!moduleResult.valid) { + return moduleResult; + } + + const validMod = mod as PolicyModule; + const errors: ValidationError[] = [...moduleResult.errors]; + const warnings: ValidationError[] = [...moduleResult.warnings]; + + if (ctx) { + const ctxResult = validateContext(validMod, ctx); + errors.push(...ctxResult.errors); + warnings.push(...ctxResult.warnings); + } + + if (data) { + const dataResult = validateData(validMod, data); + errors.push(...dataResult.errors); + warnings.push(...dataResult.warnings); + } + + return { + valid: errors.length === 0, + errors, + warnings, + }; +} diff --git a/packages/policy-engine/tsconfig.esm.json b/packages/policy-engine/tsconfig.esm.json new file mode 100644 index 0000000..f106773 --- /dev/null +++ b/packages/policy-engine/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "ES2020" + } +} diff --git a/packages/policy-engine/tsconfig.json b/packages/policy-engine/tsconfig.json new file mode 100644 index 0000000..c1ce63f --- /dev/null +++ b/packages/policy-engine/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "__tests__"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eab3fda..fe3a502 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,6 +75,20 @@ importers: version: 0.1.10 publishDirectory: dist + packages/nginx-parser: + devDependencies: + makage: + specifier: ^0.1.8 + version: 0.1.10 + publishDirectory: dist + + packages/policy-engine: + devDependencies: + makage: + specifier: ^0.1.8 + version: 0.1.10 + publishDirectory: dist + packages: '@babel/code-frame@7.27.1': From 8faedbe195e0f0448e3183de1496be497ca8fb6c Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 19:04:03 +0000 Subject: [PATCH 05/12] feat: add safegres plan and update licenses to All Rights Reserved - Add SAFEGRES_PLAN.md with comprehensive unified security system design - Update all packages to All Rights Reserved, Interweb, Inc. license - Set all packages to publishConfig restricted to prevent accidental publishing - Create LICENSE file with proprietary license text The safegres plan combines: - PolicyEngine types (Decision, PolicyModule, Obligation) - RLS AST node types from constructive-db (DirectOwner, Membership, etc.) - Unified condition system for postgres, ingress, and egress layers --- LICENSE | 27 +- SAFEGRES_PLAN.md | 723 ++++++++++++++++++++++++++++ package.json | 2 +- packages/bash-parser/package.json | 4 +- packages/docker-parser/package.json | 4 +- packages/nginx-parser/package.json | 4 +- packages/policy-engine/package.json | 4 +- 7 files changed, 741 insertions(+), 27 deletions(-) create mode 100644 SAFEGRES_PLAN.md diff --git a/LICENSE b/LICENSE index 153d3dd..19e5a48 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,12 @@ -The MIT License (MIT) +All Rights Reserved -Copyright (c) 2026 Dan Lynch +Copyright (c) 2024-2026 Interweb, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +This software and associated documentation files (the "Software") are the +proprietary and confidential property of Interweb, Inc. No part of the +Software may be reproduced, distributed, transmitted, displayed, published, +or broadcast in any form or by any means, including photocopying, recording, +or other electronic or mechanical methods, without the prior written +permission of Interweb, Inc. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +For licensing inquiries, please contact: developers@constructive.io diff --git a/SAFEGRES_PLAN.md b/SAFEGRES_PLAN.md new file mode 100644 index 0000000..d25fd57 --- /dev/null +++ b/SAFEGRES_PLAN.md @@ -0,0 +1,723 @@ +# Safegres: Unified Security System Plan + +This document outlines the plan for **safegres** - a unified security system that extends TypeScript-based policy evaluation from postgres (RLS) to ingress and egress layers. + +## Overview + +Safegres unifies three security domains under a single policy model: + +1. **Postgres (RLS)**: Row-Level Security policies controlling database access +2. **Ingress**: HTTP request filtering, rate limiting, routing +3. **Egress**: Outbound connection control, destination allowlists + +The system combines the existing PolicyEngine types with RLS AST node types from constructive-db into a unified schema that can compile to multiple targets (PostgreSQL RLS, Nginx, Envoy, etc.). + +## Design Principles + +1. **Single Source of Truth**: Define access rules once, compile to multiple targets +2. **Intent-Based**: Rules describe business intent, not implementation details +3. **Composable**: Conditions can be combined with AND/OR/NOT logic +4. **Type-Safe**: Full TypeScript type definitions for all constructs +5. **Deterministic**: Pure functions with no side effects during evaluation +6. **Auditable**: Clear mapping from business rules to technical implementation + +## Architecture + +``` + ┌─────────────────────────────────────┐ + │ SafegresPolicy │ + │ (Unified Policy Definition) │ + └─────────────────┬───────────────────┘ + │ + ┌───────────────────────┼───────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ + │ PostgreSQL │ │ Nginx │ │ Envoy │ + │ Compiler │ │ Compiler │ │ Compiler │ + └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ + │ │ │ + ▼ ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ + │ CREATE POLICY │ │ nginx.conf │ │ xDS Config │ + │ SQL Statements │ │ Directives │ │ (Future) │ + └─────────────────┘ └─────────────────┘ └─────────────────┘ +``` + +## Unified Type System + +### Core Types + +These types are shared across all security layers: + +```typescript +// Effect represents the outcome of a policy decision +type Effect = 'allow' | 'deny'; + +// Reason explains why a decision was made +interface Reason { + code: string; // Stable identifier for analytics + message: string; // Human-readable explanation + path?: string; // Context field path (e.g., "request.path") + meta?: Record; +} + +// Decision is the result of policy evaluation +interface Decision { + effect: Effect; + reasons: Reason[]; + obligations?: Obligation[]; + trace?: TraceStep[]; +} +``` + +### Condition Node Types + +Conditions are the core building blocks for expressing access control logic. They are designed to work across all three layers (postgres, ingress, egress). + +#### Identity Conditions (Who can access) + +```typescript +// Direct user ID comparison +// Postgres: owner_id = current_user_id() +// Ingress: subject = ctx.identity.subject +interface DirectOwner { + entity_field: string; +} + +// Multiple ownership fields (OR logic) +// Postgres: sender_id = current_user_id() OR receiver_id = current_user_id() +interface DirectOwnerAny { + entity_fields: string[]; +} + +// Role/group membership check +// Postgres: EXISTS (SELECT 1 FROM sprt WHERE actor_id = current_user_id() AND ...) +// Ingress: ctx.identity.roles.includes(role) +interface Membership { + membership_type: 'App Member' | 'Organization Member' | 'Group Member' | number; + permission?: string; + is_admin?: boolean; + is_owner?: boolean; +} + +// Scoped membership with entity binding +// Postgres: entity_id IN (SELECT entity_id FROM sprt WHERE actor_id = current_user_id()) +interface MembershipByField { + entity_field: string; + membership_type: 'App Member' | 'Organization Member' | 'Group Member' | number; + permission?: string; + is_admin?: boolean; + is_owner?: boolean; +} + +// JOIN-based membership through related tables +interface MembershipByJoin { + entity_field: string; + obj_table_id?: string; + obj_table?: string; + obj_schema?: string; + obj_field_id?: string; + obj_field?: string; + membership_type: 'App Member' | 'Organization Member' | 'Group Member' | number; + permission?: string; +} + +// Hierarchical visibility using closure table +// Postgres: EXISTS (SELECT 1 FROM hierarchy_sprt WHERE ...) +interface OrgHierarchy { + direction: 'up' | 'down'; + entity_field?: string; // Default: 'entity_id' + anchor_field: string; + max_depth?: number; +} +``` + +#### Temporal Conditions (When access is valid) + +```typescript +// Time-window based access control +// Postgres: publish_at <= now() AND (expires_at IS NULL OR expires_at > now()) +interface Temporal { + valid_from_field?: string; + valid_until_field?: string; + valid_from_inclusive?: boolean; // Default: true + valid_until_inclusive?: boolean; // Default: false +} + +// Published content visibility +interface Publishable { + is_published_field: string; +} +``` + +#### Resource Conditions (What can be accessed) + +```typescript +// URL path matching (ingress) +interface PathMatch { + pattern: string; // Glob or regex + method?: string; // HTTP method filter +} + +// Host/domain matching (ingress/egress) +interface HostMatch { + pattern: string; // Glob pattern (e.g., "*.example.com") +} + +// Egress destination rules +interface DestinationMatch { + host: string; + ports?: number[]; + protocol?: string; +} +``` + +#### Composition Conditions + +```typescript +// Boolean expression composition +interface BoolExpr { + boolop: 'AND_EXPR' | 'OR_EXPR' | 'NOT_EXPR'; + args: SafegresCondition[]; +} + +// Shorthand for OR composition +type AnyOf = SafegresCondition[]; + +// Shorthand for AND composition +type AllOf = SafegresCondition[]; + +// Negation +type Not = SafegresCondition; + +// Constant conditions +interface True {} +interface False {} +``` + +### Unified Condition Type + +```typescript +type SafegresCondition = + // Identity conditions + | { DirectOwner: DirectOwner } + | { DirectOwnerAny: DirectOwnerAny } + | { Membership: Membership } + | { MembershipByField: MembershipByField } + | { MembershipByJoin: MembershipByJoin } + | { OrgHierarchy: OrgHierarchy } + // Temporal conditions + | { Temporal: Temporal } + | { Publishable: Publishable } + // Resource conditions (ingress/egress) + | { PathMatch: PathMatch } + | { HostMatch: HostMatch } + | { DestinationMatch: DestinationMatch } + // Composition + | { BoolExpr: BoolExpr } + | { AnyOf: SafegresCondition[] } + | { AllOf: SafegresCondition[] } + | { Not: SafegresCondition } + // Constants + | { True: {} } + | { False: {} }; +``` + +### Obligation Types + +Obligations are side effects applied after a decision. They are layer-specific: + +```typescript +type SafegresObligation = + // Shared obligations + | { kind: 'log'; args: { level: string; message: string; fields?: Record } } + | { kind: 'mask'; args: { fields: string[]; strategy: 'redact' | 'hash' | 'partial' } } + // Postgres-specific + | { kind: 'rowFilter'; args: { expression: string } } + | { kind: 'columnMask'; args: { column: string; mask: string } } + | { kind: 'audit'; args: { action: string; table: string } } + // Ingress-specific + | { kind: 'setHeader'; args: { name: string; value: string } } + | { kind: 'rateLimit'; args: { zone: string; rate: string; burst?: number } } + | { kind: 'rewrite'; args: { pattern: string; replacement: string } } + | { kind: 'route'; args: { upstream: string; weight?: number } } + | { kind: 'cache'; args: { ttl: number; key?: string } } + | { kind: 'cors'; args: { origins: string[]; methods?: string[]; headers?: string[] } } + // Egress-specific + | { kind: 'allowDestination'; args: { host: string; ports?: number[] } } + | { kind: 'denyDestination'; args: { host: string; reason?: string } }; +``` + +### Policy and Rule Types + +```typescript +// Target specifies where a policy applies +interface SafegresTarget { + layer: 'postgres' | 'ingress' | 'egress'; + // Postgres targets + schema?: string; + table?: string; + // Ingress/egress targets + host?: string; + path?: string; + destination?: string; +} + +// Rule defines a single access pattern +interface SafegresRule { + name: string; + description?: string; + // Who: actors this rule applies to + actors: string[]; // Role names (e.g., 'authenticated', 'anonymous', 'admin') + // What: actions/privileges + actions: string[]; // Postgres: select/insert/update/delete, HTTP: get/post/put/delete + // When: condition that must be true + condition: SafegresCondition; + // Effect: allow or deny + effect: Effect; + // Side effects + obligations?: SafegresObligation[]; + // Options + permissive?: boolean; // Default: true + disabled?: boolean; +} + +// Policy is a versioned, composable policy unit +interface SafegresPolicy { + id: string; + version: string; + description?: string; + // Where this policy applies + target: SafegresTarget; + // Access rules + rules: SafegresRule[]; + // Metadata + tags?: string[]; +} +``` + +### Context Types + +```typescript +// Unified context for policy evaluation +interface SafegresContext { + // Request information + request: { + id: string; + time: string; + ip?: string; + method?: string; + host?: string; + path?: string; + headers?: Record; + query?: Record; + body?: unknown; + // Kubernetes/mesh + namespace?: string; + service?: string; + operation?: string; + // Egress + destination?: { host: string; port?: number; protocol?: string }; + }; + // Identity information + identity: { + subject: string; + roles?: string[]; + groups?: string[]; + claims?: Record; + // Postgres-specific (from JWT claims) + user_id?: string; + database_id?: string; + }; + // Environment + env: { + tenantId?: string; + cluster?: string; + region?: string; + stage?: 'dev' | 'staging' | 'prod'; + vars?: Record; + }; +} +``` + +## Package Structure + +``` +packages/ +├── safegres/ # Core unified types and runtime +│ ├── src/ +│ │ ├── types/ +│ │ │ ├── core.ts # Effect, Decision, Reason +│ │ │ ├── conditions.ts # All condition node types +│ │ │ ├── obligations.ts # All obligation types +│ │ │ ├── policy.ts # SafegresPolicy, SafegresRule +│ │ │ ├── context.ts # SafegresContext +│ │ │ └── index.ts +│ │ ├── helpers/ +│ │ │ ├── match.ts # String matching (exact, prefix, glob, regex) +│ │ │ ├── quantifiers.ts # all, any, none, count, find +│ │ │ ├── access.ts # get, defined, empty, includes +│ │ │ └── index.ts +│ │ ├── evaluator/ +│ │ │ ├── evaluate.ts # Runtime policy evaluation +│ │ │ ├── validator.ts # Policy validation +│ │ │ └── index.ts +│ │ └── index.ts +│ ├── package.json +│ └── README.md +│ +├── safegres-postgres/ # PostgreSQL RLS compiler +│ ├── src/ +│ │ ├── compiler.ts # SafegresPolicy -> SQL +│ │ ├── ast.ts # AST generation helpers +│ │ ├── deparser.ts # AST -> SQL string +│ │ └── index.ts +│ ├── package.json +│ └── README.md +│ +├── safegres-nginx/ # Nginx compiler (uses nginx-parser) +│ ├── src/ +│ │ ├── compiler.ts # SafegresPolicy -> Nginx AST +│ │ └── index.ts +│ ├── package.json +│ └── README.md +│ +├── policy-engine/ # (existing) Runtime evaluation +├── nginx-parser/ # (existing) Nginx parser/deparser +├── docker-parser/ # (existing) Dockerfile parser +└── bash-parser/ # (existing) Bash parser +``` + +## Implementation Phases + +### Phase 1: Repository Setup and Core Types + +1. Rename repository from `dockerjs` to `safegres` +2. Update all package licenses to "All Rights Reserved, Interweb, Inc." +3. Set all packages to `publishConfig: { access: "restricted" }` +4. Create `safegres` package with unified types +5. Export all condition node types +6. Export all obligation types +7. Export policy and rule types + +### Phase 2: Helpers and Evaluation + +1. Port helpers from policy-engine to safegres +2. Extend helpers with RLS-specific operations: + - `membershipCheck`: Check SPRT membership + - `hierarchyCheck`: Check org hierarchy visibility + - `temporalCheck`: Check time-window constraints +3. Implement condition evaluator for runtime evaluation +4. Implement policy validator + +### Phase 3: PostgreSQL Compiler + +1. Create `safegres-postgres` package +2. Implement condition-to-AST transformation: + - `DirectOwner` -> `col = current_user_id()` + - `Membership` -> `EXISTS (SELECT 1 FROM sprt ...)` + - `MembershipByField` -> `field IN (SELECT entity_id FROM sprt ...)` + - `OrgHierarchy` -> `EXISTS (SELECT 1 FROM hierarchy_sprt ...)` + - `Temporal` -> `field <= now() AND ...` + - `BoolExpr` -> `AND/OR/NOT` composition +3. Implement AST deparser (SQL generation) +4. Generate CREATE POLICY statements + +### Phase 4: Nginx Compiler + +1. Create `safegres-nginx` package +2. Implement condition-to-Nginx transformation: + - `PathMatch` -> `location` blocks + - `HostMatch` -> `server_name` directives + - `Membership` -> `if` blocks with variable checks +3. Implement obligation-to-Nginx transformation: + - `setHeader` -> `add_header`, `proxy_set_header` + - `rateLimit` -> `limit_req_zone`, `limit_req` + - `rewrite` -> `rewrite`, `return` + - `route` -> `proxy_pass`, upstream selection + - `cache` -> `proxy_cache` directives + - `cors` -> CORS headers + +### Phase 5: Integration and Testing + +1. Create comprehensive test fixtures +2. Test round-trip: Policy -> Postgres SQL -> verify +3. Test round-trip: Policy -> Nginx config -> verify +4. Integration tests with constructive-db patterns +5. Performance benchmarks + +## Example: Unified Policy Definition + +```typescript +const postsAccessPolicy: SafegresPolicy = { + id: 'constructive.posts.access', + version: '1.0.0', + description: 'Access rules for the posts table', + target: { + layer: 'postgres', + schema: 'public', + table: 'posts' + }, + rules: [ + // Owners have full access + { + name: 'owner_full_access', + actors: ['authenticated'], + actions: ['select', 'insert', 'update', 'delete'], + condition: { DirectOwner: { entity_field: 'owner_id' } }, + effect: 'allow' + }, + // Org members can read + { + name: 'org_members_read', + actors: ['authenticated'], + actions: ['select'], + condition: { + MembershipByField: { + entity_field: 'entity_id', + membership_type: 'Organization Member', + permission: 'read_posts' + } + }, + effect: 'allow' + }, + // Admins can edit any post in their org + { + name: 'org_admins_edit', + actors: ['authenticated'], + actions: ['update', 'delete'], + condition: { + MembershipByField: { + entity_field: 'entity_id', + membership_type: 'Organization Member', + is_admin: true + } + }, + effect: 'allow' + }, + // Published posts are public + { + name: 'published_public', + actors: ['anonymous', 'authenticated'], + actions: ['select'], + condition: { Publishable: { is_published_field: 'is_published' } }, + effect: 'allow' + } + ] +}; +``` + +### Compiled to PostgreSQL RLS + +```sql +-- owner_full_access +CREATE POLICY posts_access_owner_full_access_sel ON public.posts + FOR SELECT TO authenticated + USING (owner_id = jwt_public.current_user_id()); + +CREATE POLICY posts_access_owner_full_access_ins ON public.posts + FOR INSERT TO authenticated + WITH CHECK (owner_id = jwt_public.current_user_id()); + +CREATE POLICY posts_access_owner_full_access_upd ON public.posts + FOR UPDATE TO authenticated + USING (owner_id = jwt_public.current_user_id()); + +CREATE POLICY posts_access_owner_full_access_del ON public.posts + FOR DELETE TO authenticated + USING (owner_id = jwt_public.current_user_id()); + +-- org_members_read +CREATE POLICY posts_access_org_members_read_sel ON public.posts + FOR SELECT TO authenticated + USING (entity_id IN ( + SELECT org_sprt.entity_id + FROM private.org_sprt + WHERE org_sprt.actor_id = jwt_public.current_user_id() + AND (org_sprt.permissions & B'00000001') = B'00000001' + )); + +-- org_admins_edit +CREATE POLICY posts_access_org_admins_edit_upd ON public.posts + FOR UPDATE TO authenticated + USING (entity_id IN ( + SELECT org_sprt.entity_id + FROM private.org_sprt + WHERE org_sprt.actor_id = jwt_public.current_user_id() + AND org_sprt.is_admin = true + )); + +CREATE POLICY posts_access_org_admins_edit_del ON public.posts + FOR DELETE TO authenticated + USING (entity_id IN ( + SELECT org_sprt.entity_id + FROM private.org_sprt + WHERE org_sprt.actor_id = jwt_public.current_user_id() + AND org_sprt.is_admin = true + )); + +-- published_public +CREATE POLICY posts_access_published_public_sel ON public.posts + FOR SELECT TO anonymous, authenticated + USING (is_published = true); +``` + +## Example: Ingress Policy + +```typescript +const apiIngressPolicy: SafegresPolicy = { + id: 'constructive.api.ingress', + version: '1.0.0', + description: 'API ingress rules', + target: { + layer: 'ingress', + host: 'api.example.com' + }, + rules: [ + // Rate limit all requests + { + name: 'global_rate_limit', + actors: ['*'], + actions: ['*'], + condition: { True: {} }, + effect: 'allow', + obligations: [ + { kind: 'rateLimit', args: { zone: 'api', rate: '100r/s', burst: 50 } } + ] + }, + // Admin endpoints require admin role + { + name: 'admin_only', + actors: ['admin'], + actions: ['*'], + condition: { PathMatch: { pattern: '/admin/*' } }, + effect: 'allow' + }, + // Public health check + { + name: 'health_check', + actors: ['*'], + actions: ['get'], + condition: { PathMatch: { pattern: '/health' } }, + effect: 'allow' + } + ] +}; +``` + +### Compiled to Nginx + +```nginx +limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s; + +server { + server_name api.example.com; + + # Global rate limit + limit_req zone=api burst=50 nodelay; + + # Admin endpoints + location /admin/ { + if ($jwt_claim_role != "admin") { + return 403; + } + proxy_pass http://backend; + } + + # Health check (public) + location = /health { + return 200 "OK"; + } + + # Default backend + location / { + proxy_pass http://backend; + } +} +``` + +## Example: Egress Policy + +```typescript +const egressPolicy: SafegresPolicy = { + id: 'constructive.egress.allowlist', + version: '1.0.0', + description: 'Egress allowlist for production namespace', + target: { + layer: 'egress', + destination: '*' + }, + rules: [ + // Allow S3 access + { + name: 'allow_s3', + actors: ['*'], + actions: ['connect'], + condition: { HostMatch: { pattern: '*.s3.amazonaws.com' } }, + effect: 'allow' + }, + // Allow database connections + { + name: 'allow_database', + actors: ['*'], + actions: ['connect'], + condition: { + DestinationMatch: { + host: 'db.internal', + ports: [5432] + } + }, + effect: 'allow' + }, + // Deny all other egress + { + name: 'deny_default', + actors: ['*'], + actions: ['*'], + condition: { True: {} }, + effect: 'deny', + obligations: [ + { kind: 'log', args: { level: 'warn', message: 'Blocked egress attempt' } } + ] + } + ] +}; +``` + +## Migration from Existing Systems + +### From policy-engine + +The existing `policy-engine` package will be preserved for backward compatibility. New code should use `safegres` directly. The migration path: + +1. Import types from `safegres` instead of `policy-engine` +2. Convert `PolicyModule.evaluate` to `SafegresPolicy.rules` +3. Use condition nodes instead of imperative code + +### From constructive-db RLS + +The existing RLS system in constructive-db uses JSONB policy definitions. These map directly to safegres conditions: + +| constructive-db | safegres | +|-----------------|----------| +| `direct_owner` template | `DirectOwner` condition | +| `direct_owner_any` template | `DirectOwnerAny` condition | +| `membership` template | `Membership` condition | +| `membership_by_field` template | `MembershipByField` condition | +| `membership_by_join` template | `MembershipByJoin` condition | +| `ast` template with `OrgHierarchy` | `OrgHierarchy` condition | +| `ast` template with `Temporal` | `Temporal` condition | +| `BoolExpr` with `AND_EXPR` | `AllOf` or `BoolExpr` | +| `BoolExpr` with `OR_EXPR` | `AnyOf` or `BoolExpr` | + +## Related Documents + +- [POLICY_ENGINE_PLAN.md](./POLICY_ENGINE_PLAN.md) - Original policy engine design +- [constructive-db RLS_POLICY_TYPES.md](../constructive-db/docs/RLS_POLICY_TYPES.md) - RLS policy benchmarks +- [constructive-db SPRT_TABLES.md](../constructive-db/docs/spec/04-sprt-shadow-tables.md) - SPRT architecture +- [constructive-db Rule Sets](../constructive-db/docs/spec/08-rule-sets.md) - Rule sets specification + +## License + +All Rights Reserved, Interweb, Inc. diff --git a/package.json b/package.json index 0e63b80..d7b4bdd 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/constructive-io/dockerjs" }, - "license": "MIT", + "license": "SEE LICENSE IN LICENSE", "publishConfig": { "access": "restricted" }, diff --git a/packages/bash-parser/package.json b/packages/bash-parser/package.json index 3aeb9d0..83c0315 100644 --- a/packages/bash-parser/package.json +++ b/packages/bash-parser/package.json @@ -7,9 +7,9 @@ "module": "esm/index.js", "types": "index.d.ts", "homepage": "https://github.com/constructive-io/dockerjs", - "license": "MIT", + "license": "SEE LICENSE IN LICENSE", "publishConfig": { - "access": "public", + "access": "restricted", "directory": "dist" }, "repository": { diff --git a/packages/docker-parser/package.json b/packages/docker-parser/package.json index 18f519b..2f0dd74 100644 --- a/packages/docker-parser/package.json +++ b/packages/docker-parser/package.json @@ -7,9 +7,9 @@ "module": "esm/index.js", "types": "index.d.ts", "homepage": "https://github.com/constructive-io/dockerjs", - "license": "MIT", + "license": "SEE LICENSE IN LICENSE", "publishConfig": { - "access": "public", + "access": "restricted", "directory": "dist" }, "repository": { diff --git a/packages/nginx-parser/package.json b/packages/nginx-parser/package.json index 5465379..ca99356 100644 --- a/packages/nginx-parser/package.json +++ b/packages/nginx-parser/package.json @@ -7,9 +7,9 @@ "module": "esm/index.js", "types": "index.d.ts", "homepage": "https://github.com/constructive-io/dockerjs", - "license": "MIT", + "license": "SEE LICENSE IN LICENSE", "publishConfig": { - "access": "public", + "access": "restricted", "directory": "dist" }, "repository": { diff --git a/packages/policy-engine/package.json b/packages/policy-engine/package.json index 4a94ef7..95932c7 100644 --- a/packages/policy-engine/package.json +++ b/packages/policy-engine/package.json @@ -7,9 +7,9 @@ "module": "esm/index.js", "types": "index.d.ts", "homepage": "https://github.com/constructive-io/dockerjs", - "license": "MIT", + "license": "SEE LICENSE IN LICENSE", "publishConfig": { - "access": "public", + "access": "restricted", "directory": "dist" }, "repository": { From 4e8cf9347c9e7d2a1c3ce1c04aae8a1f733ba8f2 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 19:18:14 +0000 Subject: [PATCH 06/12] feat: add safegres package with unified security types Implements Phase 1 of the safegres plan - core unified types and helpers: Types: - Condition types: DirectOwner, DirectOwnerAny, Membership, MembershipByField, MembershipByJoin, OrgHierarchy, Temporal, Publishable, PathMatch, HostMatch, DestinationMatch, FieldEquals, FieldIn, BoolExpr, AllOf, AnyOf, Not, True, False - Obligation types: log, mask (shared), rowFilter, columnMask, audit (postgres), setHeader, rateLimit, rewrite, route, cache, cors (ingress), allowDestination, denyDestination, proxyThrough (egress) - Policy types: SafegresPolicy, SafegresRule, SafegresTarget, SecurityLayer - Context types: SafegresContext, SafegresRequest, SafegresIdentity, SafegresData Helpers: - Match: exact, iexact, prefix, suffix, contains, glob, regex - Quantifiers: all, any, none, count, find, filter, map, first, last - Access: get, defined, empty, includes, truthy, falsy, equals, coalesce - Condition builders: directOwner, membership, membershipByField, orgHierarchy, temporal, publishable, pathMatch, hostMatch, allOf, anyOf, not, always, never Tests: 125 passing tests covering all types, helpers, and policy validation --- packages/safegres/README.md | 132 ++++++ .../safegres/__tests__/conditions.test.ts | 321 +++++++++++++ packages/safegres/__tests__/helpers.test.ts | 383 ++++++++++++++++ .../safegres/__tests__/obligations.test.ts | 248 ++++++++++ packages/safegres/__tests__/policy.test.ts | 320 +++++++++++++ packages/safegres/jest.config.js | 8 + packages/safegres/package.json | 46 ++ packages/safegres/src/helpers/access.ts | 113 +++++ packages/safegres/src/helpers/conditions.ts | 303 +++++++++++++ packages/safegres/src/helpers/index.ts | 121 +++++ packages/safegres/src/helpers/match.ts | 101 +++++ packages/safegres/src/helpers/quantifiers.ts | 115 +++++ packages/safegres/src/index.ts | 14 + packages/safegres/src/types/conditions.ts | 422 ++++++++++++++++++ packages/safegres/src/types/context.ts | 171 +++++++ packages/safegres/src/types/core.ts | 38 ++ packages/safegres/src/types/index.ts | 147 ++++++ packages/safegres/src/types/obligations.ts | 377 ++++++++++++++++ packages/safegres/src/types/policy.ts | 351 +++++++++++++++ packages/safegres/tsconfig.esm.json | 7 + packages/safegres/tsconfig.json | 9 + 21 files changed, 3747 insertions(+) create mode 100644 packages/safegres/README.md create mode 100644 packages/safegres/__tests__/conditions.test.ts create mode 100644 packages/safegres/__tests__/helpers.test.ts create mode 100644 packages/safegres/__tests__/obligations.test.ts create mode 100644 packages/safegres/__tests__/policy.test.ts create mode 100644 packages/safegres/jest.config.js create mode 100644 packages/safegres/package.json create mode 100644 packages/safegres/src/helpers/access.ts create mode 100644 packages/safegres/src/helpers/conditions.ts create mode 100644 packages/safegres/src/helpers/index.ts create mode 100644 packages/safegres/src/helpers/match.ts create mode 100644 packages/safegres/src/helpers/quantifiers.ts create mode 100644 packages/safegres/src/index.ts create mode 100644 packages/safegres/src/types/conditions.ts create mode 100644 packages/safegres/src/types/context.ts create mode 100644 packages/safegres/src/types/core.ts create mode 100644 packages/safegres/src/types/index.ts create mode 100644 packages/safegres/src/types/obligations.ts create mode 100644 packages/safegres/src/types/policy.ts create mode 100644 packages/safegres/tsconfig.esm.json create mode 100644 packages/safegres/tsconfig.json diff --git a/packages/safegres/README.md b/packages/safegres/README.md new file mode 100644 index 0000000..121b6c6 --- /dev/null +++ b/packages/safegres/README.md @@ -0,0 +1,132 @@ +# safegres + +Unified security system for postgres, ingress, and egress policies. + +## Overview + +Safegres provides a unified type system and helpers for defining security policies that can be compiled to multiple targets: + +- **PostgreSQL RLS**: Row-Level Security policies +- **Nginx**: HTTP request filtering, rate limiting, routing +- **Egress**: Outbound connection control + +## Installation + +```bash +pnpm add safegres +``` + +## Usage + +### Defining Conditions + +```typescript +import { + directOwner, + membership, + membershipByField, + publishable, + allOf, + anyOf, +} from 'safegres'; + +// Owner can access their own records +const ownerCondition = directOwner('owner_id'); + +// Organization members can read +const orgMemberCondition = membershipByField( + 'entity_id', + 'Organization Member', + { permission: 'read' } +); + +// Published content is public +const publishedCondition = publishable('is_published'); + +// Combine conditions +const readCondition = anyOf( + ownerCondition, + orgMemberCondition, + publishedCondition +); +``` + +### Defining Policies + +```typescript +import { + createPolicy, + createRule, + postgresTarget, + directOwner, + membershipByField, + publishable, +} from 'safegres'; + +const postsPolicy = createPolicy( + 'constructive.posts.access', + '1.0.0', + postgresTarget('public', 'posts'), + [ + createRule( + 'owner_full_access', + ['authenticated'], + ['select', 'insert', 'update', 'delete'], + directOwner('owner_id'), + 'allow' + ), + createRule( + 'org_members_read', + ['authenticated'], + ['select'], + membershipByField('entity_id', 'Organization Member', { permission: 'read_posts' }), + 'allow' + ), + createRule( + 'published_public', + ['anonymous', 'authenticated'], + ['select'], + publishable('is_published'), + 'allow' + ), + ] +); +``` + +### Using Helpers + +```typescript +import { helpers, get, any, match } from 'safegres'; + +// Safe property access +const userId = get(ctx, 'identity.user_id', ''); + +// Quantifiers +const hasAdminRole = any(ctx.identity.roles ?? [], (r) => r === 'admin'); + +// String matching +const isApiPath = match.prefix(ctx.request.path, '/api/'); +const isAllowedHost = match.glob(ctx.request.host, '*.example.com'); +``` + +## Types + +### Condition Types + +- **Identity**: `DirectOwner`, `DirectOwnerAny`, `Membership`, `MembershipByField`, `MembershipByJoin`, `OrgHierarchy` +- **Temporal**: `Temporal`, `Publishable` +- **Resource**: `PathMatch`, `HostMatch`, `DestinationMatch`, `NamespaceMatch`, `ServiceMatch` +- **Comparison**: `FieldEquals`, `FieldEqualsField`, `FieldIn`, `FieldNotNull`, `FieldIsNull` +- **Composition**: `AllOf`, `AnyOf`, `Not`, `BoolExpr` +- **Constants**: `True`, `False` + +### Obligation Types + +- **Shared**: `log`, `mask` +- **Postgres**: `rowFilter`, `columnMask`, `audit` +- **Ingress**: `setHeader`, `rateLimit`, `rewrite`, `route`, `cache`, `cors`, `returnStatus`, `requireAuth` +- **Egress**: `allowDestination`, `denyDestination`, `proxyThrough` + +## License + +All Rights Reserved - Interweb, Inc. diff --git a/packages/safegres/__tests__/conditions.test.ts b/packages/safegres/__tests__/conditions.test.ts new file mode 100644 index 0000000..1d3a557 --- /dev/null +++ b/packages/safegres/__tests__/conditions.test.ts @@ -0,0 +1,321 @@ +import { + // Type guards + isDirectOwner, + isDirectOwnerAny, + isMembership, + isMembershipByField, + isMembershipByJoin, + isOrgHierarchy, + isTemporal, + isPublishable, + isPathMatch, + isHostMatch, + isDestinationMatch, + isFieldEquals, + isFieldIn, + isBoolExpr, + isAnyOf, + isAllOf, + isNot, + isTrue, + isFalse, + getConditionType, + getConditionValue, + // Builders + directOwner, + directOwnerAny, + membership, + membershipByField, + membershipByJoin, + orgHierarchy, + temporal, + publishable, + pathMatch, + hostMatch, + destinationMatch, + fieldEquals, + fieldIn, + allOf, + anyOf, + not, + always, + never, +} from '../src'; + +describe('Condition Type Guards', () => { + describe('Identity Conditions', () => { + it('should identify DirectOwner conditions', () => { + const condition = directOwner('owner_id'); + expect(isDirectOwner(condition)).toBe(true); + expect(isMembership(condition)).toBe(false); + }); + + it('should identify DirectOwnerAny conditions', () => { + const condition = directOwnerAny(['sender_id', 'receiver_id']); + expect(isDirectOwnerAny(condition)).toBe(true); + expect(isDirectOwner(condition)).toBe(false); + }); + + it('should identify Membership conditions', () => { + const condition = membership('Organization Member', { permission: 'read' }); + expect(isMembership(condition)).toBe(true); + expect(isMembershipByField(condition)).toBe(false); + }); + + it('should identify MembershipByField conditions', () => { + const condition = membershipByField('entity_id', 'Organization Member'); + expect(isMembershipByField(condition)).toBe(true); + expect(isMembership(condition)).toBe(false); + }); + + it('should identify MembershipByJoin conditions', () => { + const condition = membershipByJoin('entity_id', 'Organization Member', { + obj_table: 'organizations', + obj_field: 'id', + }); + expect(isMembershipByJoin(condition)).toBe(true); + expect(isMembershipByField(condition)).toBe(false); + }); + + it('should identify OrgHierarchy conditions', () => { + const condition = orgHierarchy('down', 'org_id', { max_depth: 3 }); + expect(isOrgHierarchy(condition)).toBe(true); + expect(isMembership(condition)).toBe(false); + }); + }); + + describe('Temporal Conditions', () => { + it('should identify Temporal conditions', () => { + const condition = temporal({ + valid_from_field: 'publish_at', + valid_until_field: 'expires_at', + }); + expect(isTemporal(condition)).toBe(true); + expect(isPublishable(condition)).toBe(false); + }); + + it('should identify Publishable conditions', () => { + const condition = publishable('is_published'); + expect(isPublishable(condition)).toBe(true); + expect(isTemporal(condition)).toBe(false); + }); + }); + + describe('Resource Conditions', () => { + it('should identify PathMatch conditions', () => { + const condition = pathMatch('/api/*', 'GET'); + expect(isPathMatch(condition)).toBe(true); + expect(isHostMatch(condition)).toBe(false); + }); + + it('should identify HostMatch conditions', () => { + const condition = hostMatch('*.example.com'); + expect(isHostMatch(condition)).toBe(true); + expect(isPathMatch(condition)).toBe(false); + }); + + it('should identify DestinationMatch conditions', () => { + const condition = destinationMatch('api.example.com', { ports: [443] }); + expect(isDestinationMatch(condition)).toBe(true); + expect(isHostMatch(condition)).toBe(false); + }); + }); + + describe('Comparison Conditions', () => { + it('should identify FieldEquals conditions', () => { + const condition = fieldEquals('status', 'active'); + expect(isFieldEquals(condition)).toBe(true); + expect(isFieldIn(condition)).toBe(false); + }); + + it('should identify FieldIn conditions', () => { + const condition = fieldIn('status', ['active', 'pending']); + expect(isFieldIn(condition)).toBe(true); + expect(isFieldEquals(condition)).toBe(false); + }); + }); + + describe('Composition Conditions', () => { + it('should identify AllOf conditions', () => { + const condition = allOf( + directOwner('owner_id'), + publishable('is_published') + ); + expect(isAllOf(condition)).toBe(true); + expect(isAnyOf(condition)).toBe(false); + }); + + it('should identify AnyOf conditions', () => { + const condition = anyOf( + directOwner('owner_id'), + publishable('is_published') + ); + expect(isAnyOf(condition)).toBe(true); + expect(isAllOf(condition)).toBe(false); + }); + + it('should identify Not conditions', () => { + const condition = not(publishable('is_published')); + expect(isNot(condition)).toBe(true); + expect(isAnyOf(condition)).toBe(false); + }); + + it('should return single condition for single-element allOf', () => { + const inner = directOwner('owner_id'); + const condition = allOf(inner); + expect(isDirectOwner(condition)).toBe(true); + }); + + it('should return single condition for single-element anyOf', () => { + const inner = directOwner('owner_id'); + const condition = anyOf(inner); + expect(isDirectOwner(condition)).toBe(true); + }); + }); + + describe('Constant Conditions', () => { + it('should identify True conditions', () => { + const condition = always(); + expect(isTrue(condition)).toBe(true); + expect(isFalse(condition)).toBe(false); + }); + + it('should identify False conditions', () => { + const condition = never(); + expect(isFalse(condition)).toBe(true); + expect(isTrue(condition)).toBe(false); + }); + + it('should return True for empty allOf', () => { + const condition = allOf(); + expect(isTrue(condition)).toBe(true); + }); + + it('should return False for empty anyOf', () => { + const condition = anyOf(); + expect(isFalse(condition)).toBe(true); + }); + }); +}); + +describe('Condition Utilities', () => { + it('should get condition type', () => { + expect(getConditionType(directOwner('owner_id'))).toBe('DirectOwner'); + expect(getConditionType(membership('Organization Member'))).toBe('Membership'); + expect(getConditionType(always())).toBe('True'); + }); + + it('should get condition value', () => { + const condition = directOwner('owner_id'); + const value = getConditionValue<{ entity_field: string }>(condition); + expect(value.entity_field).toBe('owner_id'); + }); +}); + +describe('Condition Builders', () => { + describe('directOwner', () => { + it('should create DirectOwner condition', () => { + const condition = directOwner('owner_id'); + expect(condition).toEqual({ DirectOwner: { entity_field: 'owner_id' } }); + }); + }); + + describe('membership', () => { + it('should create Membership condition with options', () => { + const condition = membership('Organization Member', { + permission: 'read', + is_admin: true, + }); + expect(condition).toEqual({ + Membership: { + membership_type: 'Organization Member', + permission: 'read', + is_admin: true, + }, + }); + }); + + it('should create Membership condition with numeric type', () => { + const condition = membership(42); + expect(condition).toEqual({ + Membership: { membership_type: 42 }, + }); + }); + }); + + describe('membershipByField', () => { + it('should create MembershipByField condition', () => { + const condition = membershipByField('entity_id', 'Organization Member', { + permission: 'write', + }); + expect(condition).toEqual({ + MembershipByField: { + entity_field: 'entity_id', + membership_type: 'Organization Member', + permission: 'write', + }, + }); + }); + }); + + describe('orgHierarchy', () => { + it('should create OrgHierarchy condition', () => { + const condition = orgHierarchy('down', 'org_id', { + entity_field: 'entity_id', + max_depth: 5, + }); + expect(condition).toEqual({ + OrgHierarchy: { + direction: 'down', + anchor_field: 'org_id', + entity_field: 'entity_id', + max_depth: 5, + }, + }); + }); + }); + + describe('temporal', () => { + it('should create Temporal condition', () => { + const condition = temporal({ + valid_from_field: 'start_date', + valid_until_field: 'end_date', + valid_from_inclusive: true, + valid_until_inclusive: false, + }); + expect(condition).toEqual({ + Temporal: { + valid_from_field: 'start_date', + valid_until_field: 'end_date', + valid_from_inclusive: true, + valid_until_inclusive: false, + }, + }); + }); + }); + + describe('pathMatch', () => { + it('should create PathMatch condition', () => { + const condition = pathMatch('/api/v1/*', 'POST'); + expect(condition).toEqual({ + PathMatch: { pattern: '/api/v1/*', method: 'POST' }, + }); + }); + }); + + describe('destinationMatch', () => { + it('should create DestinationMatch condition', () => { + const condition = destinationMatch('api.example.com', { + ports: [80, 443], + protocol: 'https', + }); + expect(condition).toEqual({ + DestinationMatch: { + host: 'api.example.com', + ports: [80, 443], + protocol: 'https', + }, + }); + }); + }); +}); diff --git a/packages/safegres/__tests__/helpers.test.ts b/packages/safegres/__tests__/helpers.test.ts new file mode 100644 index 0000000..6d7a3d7 --- /dev/null +++ b/packages/safegres/__tests__/helpers.test.ts @@ -0,0 +1,383 @@ +import { + // Match helpers + match, + exact, + iexact, + prefix, + suffix, + contains, + glob, + regex, + // Quantifier helpers + all, + any, + none, + count, + find, + filter, + first, + last, + // Access helpers + get, + defined, + empty, + includes, + truthy, + falsy, + equals, + coalesce, + // Combined helpers + helpers, + createHelpers, +} from '../src'; + +describe('Match Helpers', () => { + describe('exact', () => { + it('should match exact strings', () => { + expect(exact('hello', 'hello')).toBe(true); + expect(exact('hello', 'world')).toBe(false); + }); + + it('should return false for undefined', () => { + expect(exact(undefined, 'hello')).toBe(false); + expect(exact('hello', undefined)).toBe(false); + }); + }); + + describe('iexact', () => { + it('should match case-insensitively', () => { + expect(iexact('Hello', 'hello')).toBe(true); + expect(iexact('HELLO', 'hello')).toBe(true); + expect(iexact('hello', 'world')).toBe(false); + }); + }); + + describe('prefix', () => { + it('should match prefixes', () => { + expect(prefix('/api/users', '/api')).toBe(true); + expect(prefix('/api/users', '/users')).toBe(false); + }); + + it('should return false for undefined', () => { + expect(prefix(undefined, '/api')).toBe(false); + }); + }); + + describe('suffix', () => { + it('should match suffixes', () => { + expect(suffix('file.txt', '.txt')).toBe(true); + expect(suffix('file.txt', '.json')).toBe(false); + }); + }); + + describe('contains', () => { + it('should match substrings', () => { + expect(contains('hello world', 'world')).toBe(true); + expect(contains('hello world', 'foo')).toBe(false); + }); + }); + + describe('glob', () => { + it('should match glob patterns with *', () => { + expect(glob('api.example.com', '*.example.com')).toBe(true); + expect(glob('api.other.com', '*.example.com')).toBe(false); + }); + + it('should match glob patterns with ?', () => { + expect(glob('file1.txt', 'file?.txt')).toBe(true); + expect(glob('file12.txt', 'file?.txt')).toBe(false); + }); + + it('should match exact patterns', () => { + expect(glob('hello', 'hello')).toBe(true); + expect(glob('hello', 'world')).toBe(false); + }); + + it('should return false for undefined', () => { + expect(glob(undefined, '*.txt')).toBe(false); + }); + }); + + describe('regex', () => { + it('should match regex patterns', () => { + expect(regex('hello123', '^hello\\d+$')).toBe(true); + expect(regex('hello', '^hello\\d+$')).toBe(false); + }); + + it('should support flags', () => { + expect(regex('HELLO', 'hello', 'i')).toBe(true); + }); + + it('should return false for invalid patterns', () => { + expect(regex('hello', '[')).toBe(false); + }); + }); + + describe('match object', () => { + it('should provide all match functions', () => { + expect(match.exact('a', 'a')).toBe(true); + expect(match.prefix('/api', '/api')).toBe(true); + expect(match.glob('test.txt', '*.txt')).toBe(true); + }); + }); +}); + +describe('Quantifier Helpers', () => { + const numbers = [1, 2, 3, 4, 5]; + const isEven = (n: number) => n % 2 === 0; + const isPositive = (n: number) => n > 0; + const isNegative = (n: number) => n < 0; + + describe('all', () => { + it('should return true if all items match', () => { + expect(all(numbers, isPositive)).toBe(true); + }); + + it('should return false if any item does not match', () => { + expect(all(numbers, isEven)).toBe(false); + }); + + it('should return true for empty array', () => { + expect(all([], isPositive)).toBe(true); + }); + + it('should return true for null/undefined', () => { + expect(all(null, isPositive)).toBe(true); + expect(all(undefined, isPositive)).toBe(true); + }); + }); + + describe('any', () => { + it('should return true if any item matches', () => { + expect(any(numbers, isEven)).toBe(true); + }); + + it('should return false if no items match', () => { + expect(any(numbers, isNegative)).toBe(false); + }); + + it('should return false for empty array', () => { + expect(any([], isPositive)).toBe(false); + }); + }); + + describe('none', () => { + it('should return true if no items match', () => { + expect(none(numbers, isNegative)).toBe(true); + }); + + it('should return false if any item matches', () => { + expect(none(numbers, isEven)).toBe(false); + }); + + it('should return true for empty array', () => { + expect(none([], isPositive)).toBe(true); + }); + }); + + describe('count', () => { + it('should count matching items', () => { + expect(count(numbers, isEven)).toBe(2); + expect(count(numbers, isPositive)).toBe(5); + expect(count(numbers, isNegative)).toBe(0); + }); + + it('should return 0 for empty array', () => { + expect(count([], isPositive)).toBe(0); + }); + }); + + describe('find', () => { + it('should find first matching item', () => { + expect(find(numbers, isEven)).toBe(2); + }); + + it('should return undefined if no match', () => { + expect(find(numbers, isNegative)).toBeUndefined(); + }); + + it('should return undefined for empty array', () => { + expect(find([], isPositive)).toBeUndefined(); + }); + }); + + describe('filter', () => { + it('should filter matching items', () => { + expect(filter(numbers, isEven)).toEqual([2, 4]); + }); + + it('should return empty array if no match', () => { + expect(filter(numbers, isNegative)).toEqual([]); + }); + }); + + describe('first', () => { + it('should return first item', () => { + expect(first(numbers)).toBe(1); + }); + + it('should return undefined for empty array', () => { + expect(first([])).toBeUndefined(); + }); + }); + + describe('last', () => { + it('should return last item', () => { + expect(last(numbers)).toBe(5); + }); + + it('should return undefined for empty array', () => { + expect(last([])).toBeUndefined(); + }); + }); +}); + +describe('Access Helpers', () => { + const obj = { + user: { + name: 'Alice', + roles: ['admin', 'user'], + profile: { + email: 'alice@example.com', + }, + }, + }; + + describe('get', () => { + it('should get nested properties', () => { + expect(get(obj, 'user.name', '')).toBe('Alice'); + expect(get(obj, 'user.profile.email', '')).toBe('alice@example.com'); + }); + + it('should return fallback for missing properties', () => { + expect(get(obj, 'user.age', 0)).toBe(0); + expect(get(obj, 'user.profile.phone', 'N/A')).toBe('N/A'); + }); + + it('should return fallback for null/undefined', () => { + expect(get(null, 'user.name', 'default')).toBe('default'); + expect(get(undefined, 'user.name', 'default')).toBe('default'); + }); + }); + + describe('defined', () => { + it('should return true for defined values', () => { + expect(defined('hello')).toBe(true); + expect(defined(0)).toBe(true); + expect(defined(false)).toBe(true); + expect(defined('')).toBe(true); + }); + + it('should return false for null/undefined', () => { + expect(defined(null)).toBe(false); + expect(defined(undefined)).toBe(false); + }); + }); + + describe('empty', () => { + it('should return true for empty arrays/strings', () => { + expect(empty([])).toBe(true); + expect(empty('')).toBe(true); + }); + + it('should return false for non-empty arrays/strings', () => { + expect(empty([1, 2, 3])).toBe(false); + expect(empty('hello')).toBe(false); + }); + + it('should return true for null/undefined', () => { + expect(empty(null)).toBe(true); + expect(empty(undefined)).toBe(true); + }); + }); + + describe('includes', () => { + it('should check if value is in list', () => { + expect(includes(['a', 'b', 'c'], 'b')).toBe(true); + expect(includes(['a', 'b', 'c'], 'd')).toBe(false); + }); + + it('should return false for null/undefined list', () => { + expect(includes(null, 'a')).toBe(false); + expect(includes(undefined, 'a')).toBe(false); + }); + }); + + describe('truthy', () => { + it('should return true for truthy values', () => { + expect(truthy('hello')).toBe(true); + expect(truthy(1)).toBe(true); + expect(truthy(true)).toBe(true); + }); + + it('should return false for falsy values', () => { + expect(truthy('')).toBe(false); + expect(truthy(0)).toBe(false); + expect(truthy(false)).toBe(false); + expect(truthy(null)).toBe(false); + }); + }); + + describe('falsy', () => { + it('should return true for falsy values', () => { + expect(falsy('')).toBe(true); + expect(falsy(0)).toBe(true); + expect(falsy(null)).toBe(true); + }); + + it('should return false for truthy values', () => { + expect(falsy('hello')).toBe(false); + expect(falsy(1)).toBe(false); + }); + }); + + describe('equals', () => { + it('should compare primitives', () => { + expect(equals('a', 'a')).toBe(true); + expect(equals(1, 1)).toBe(true); + expect(equals('a', 'b')).toBe(false); + }); + + it('should compare objects deeply', () => { + expect(equals({ a: 1 }, { a: 1 })).toBe(true); + expect(equals({ a: 1 }, { a: 2 })).toBe(false); + expect(equals({ a: { b: 1 } }, { a: { b: 1 } })).toBe(true); + }); + + it('should handle null/undefined', () => { + expect(equals(null, null)).toBe(true); + expect(equals(undefined, undefined)).toBe(true); + expect(equals(null, undefined)).toBe(false); + }); + }); + + describe('coalesce', () => { + it('should return first defined value', () => { + expect(coalesce(undefined, null, 'hello')).toBe('hello'); + expect(coalesce('first', 'second')).toBe('first'); + }); + + it('should return undefined if all values are null/undefined', () => { + expect(coalesce(undefined, null)).toBeUndefined(); + }); + }); +}); + +describe('Combined Helpers', () => { + it('should create helpers with all functions', () => { + const h = createHelpers(); + expect(h.match).toBeDefined(); + expect(h.quantifiers).toBeDefined(); + expect(h.access).toBeDefined(); + expect(h.conditions).toBeDefined(); + }); + + it('should provide shorthand access to common helpers', () => { + expect(helpers.all([1, 2, 3], (n) => n > 0)).toBe(true); + expect(helpers.any([1, 2, 3], (n) => n > 2)).toBe(true); + expect(helpers.get({ a: 1 }, 'a', 0)).toBe(1); + expect(helpers.defined('hello')).toBe(true); + expect(helpers.empty([])).toBe(true); + expect(helpers.includes([1, 2, 3], 2)).toBe(true); + }); +}); diff --git a/packages/safegres/__tests__/obligations.test.ts b/packages/safegres/__tests__/obligations.test.ts new file mode 100644 index 0000000..55d2a54 --- /dev/null +++ b/packages/safegres/__tests__/obligations.test.ts @@ -0,0 +1,248 @@ +import { + isLogObligation, + isMaskObligation, + isRowFilterObligation, + isColumnMaskObligation, + isAuditObligation, + isSetHeaderObligation, + isRateLimitObligation, + isRewriteObligation, + isRouteObligation, + isCacheObligation, + isCorsObligation, + isReturnStatusObligation, + isRequireAuthObligation, + isAllowDestinationObligation, + isDenyDestinationObligation, + isProxyThroughObligation, + isPostgresObligation, + isIngressObligation, + isEgressObligation, + isSharedObligation, + type SafegresObligation, +} from '../src'; + +describe('Obligation Type Guards', () => { + describe('Shared Obligations', () => { + it('should identify log obligations', () => { + const obligation: SafegresObligation = { + kind: 'log', + args: { level: 'info', message: 'Access granted' }, + }; + expect(isLogObligation(obligation)).toBe(true); + expect(isSharedObligation(obligation)).toBe(true); + expect(isPostgresObligation(obligation)).toBe(false); + }); + + it('should identify mask obligations', () => { + const obligation: SafegresObligation = { + kind: 'mask', + args: { fields: ['ssn', 'email'], strategy: 'redact' }, + }; + expect(isMaskObligation(obligation)).toBe(true); + expect(isSharedObligation(obligation)).toBe(true); + }); + }); + + describe('Postgres Obligations', () => { + it('should identify rowFilter obligations', () => { + const obligation: SafegresObligation = { + kind: 'rowFilter', + args: { expression: 'status = \'active\'' }, + }; + expect(isRowFilterObligation(obligation)).toBe(true); + expect(isPostgresObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(false); + }); + + it('should identify columnMask obligations', () => { + const obligation: SafegresObligation = { + kind: 'columnMask', + args: { column: 'email', mask: '\'***@***.***\'' }, + }; + expect(isColumnMaskObligation(obligation)).toBe(true); + expect(isPostgresObligation(obligation)).toBe(true); + }); + + it('should identify audit obligations', () => { + const obligation: SafegresObligation = { + kind: 'audit', + args: { action: 'read', table: 'users' }, + }; + expect(isAuditObligation(obligation)).toBe(true); + expect(isPostgresObligation(obligation)).toBe(true); + }); + }); + + describe('Ingress Obligations', () => { + it('should identify setHeader obligations', () => { + const obligation: SafegresObligation = { + kind: 'setHeader', + args: { name: 'X-Request-ID', value: '$request_id' }, + }; + expect(isSetHeaderObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + expect(isPostgresObligation(obligation)).toBe(false); + }); + + it('should identify rateLimit obligations', () => { + const obligation: SafegresObligation = { + kind: 'rateLimit', + args: { zone: 'api', rate: '10r/s', burst: 20 }, + }; + expect(isRateLimitObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify rewrite obligations', () => { + const obligation: SafegresObligation = { + kind: 'rewrite', + args: { pattern: '^/old/(.*)', replacement: '/new/$1' }, + }; + expect(isRewriteObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify route obligations', () => { + const obligation: SafegresObligation = { + kind: 'route', + args: { upstream: 'backend', weight: 100 }, + }; + expect(isRouteObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify cache obligations', () => { + const obligation: SafegresObligation = { + kind: 'cache', + args: { ttl: 3600, key: '$uri' }, + }; + expect(isCacheObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify cors obligations', () => { + const obligation: SafegresObligation = { + kind: 'cors', + args: { + origins: ['https://example.com'], + methods: ['GET', 'POST'], + credentials: true, + }, + }; + expect(isCorsObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify returnStatus obligations', () => { + const obligation: SafegresObligation = { + kind: 'returnStatus', + args: { status: 403, body: 'Forbidden' }, + }; + expect(isReturnStatusObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + + it('should identify requireAuth obligations', () => { + const obligation: SafegresObligation = { + kind: 'requireAuth', + args: { realm: 'API', type: 'bearer' }, + }; + expect(isRequireAuthObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(true); + }); + }); + + describe('Egress Obligations', () => { + it('should identify allowDestination obligations', () => { + const obligation: SafegresObligation = { + kind: 'allowDestination', + args: { host: 'api.example.com', ports: [443] }, + }; + expect(isAllowDestinationObligation(obligation)).toBe(true); + expect(isEgressObligation(obligation)).toBe(true); + expect(isIngressObligation(obligation)).toBe(false); + }); + + it('should identify denyDestination obligations', () => { + const obligation: SafegresObligation = { + kind: 'denyDestination', + args: { host: 'malicious.com', reason: 'Blocked domain' }, + }; + expect(isDenyDestinationObligation(obligation)).toBe(true); + expect(isEgressObligation(obligation)).toBe(true); + }); + + it('should identify proxyThrough obligations', () => { + const obligation: SafegresObligation = { + kind: 'proxyThrough', + args: { proxy: 'http://proxy.internal:8080' }, + }; + expect(isProxyThroughObligation(obligation)).toBe(true); + expect(isEgressObligation(obligation)).toBe(true); + }); + }); +}); + +describe('Obligation Layer Classification', () => { + it('should correctly classify all postgres obligations', () => { + const postgresObligations: SafegresObligation[] = [ + { kind: 'rowFilter', args: { expression: 'true' } }, + { kind: 'columnMask', args: { column: 'col', mask: 'mask' } }, + { kind: 'audit', args: { action: 'read', table: 'users' } }, + ]; + + postgresObligations.forEach((o) => { + expect(isPostgresObligation(o)).toBe(true); + expect(isIngressObligation(o)).toBe(false); + expect(isEgressObligation(o)).toBe(false); + }); + }); + + it('should correctly classify all ingress obligations', () => { + const ingressObligations: SafegresObligation[] = [ + { kind: 'setHeader', args: { name: 'X-Test', value: 'test' } }, + { kind: 'rateLimit', args: { zone: 'test', rate: '1r/s' } }, + { kind: 'rewrite', args: { pattern: '/a', replacement: '/b' } }, + { kind: 'route', args: { upstream: 'backend' } }, + { kind: 'cache', args: { ttl: 60 } }, + { kind: 'cors', args: { origins: ['*'] } }, + { kind: 'returnStatus', args: { status: 200 } }, + { kind: 'requireAuth', args: {} }, + ]; + + ingressObligations.forEach((o) => { + expect(isIngressObligation(o)).toBe(true); + expect(isPostgresObligation(o)).toBe(false); + expect(isEgressObligation(o)).toBe(false); + }); + }); + + it('should correctly classify all egress obligations', () => { + const egressObligations: SafegresObligation[] = [ + { kind: 'allowDestination', args: { host: 'example.com' } }, + { kind: 'denyDestination', args: { host: 'blocked.com' } }, + { kind: 'proxyThrough', args: { proxy: 'http://proxy:8080' } }, + ]; + + egressObligations.forEach((o) => { + expect(isEgressObligation(o)).toBe(true); + expect(isPostgresObligation(o)).toBe(false); + expect(isIngressObligation(o)).toBe(false); + }); + }); + + it('should correctly classify shared obligations', () => { + const sharedObligations: SafegresObligation[] = [ + { kind: 'log', args: { level: 'info', message: 'test' } }, + { kind: 'mask', args: { fields: ['email'], strategy: 'redact' } }, + ]; + + sharedObligations.forEach((o) => { + expect(isSharedObligation(o)).toBe(true); + expect(isPostgresObligation(o)).toBe(false); + expect(isIngressObligation(o)).toBe(false); + expect(isEgressObligation(o)).toBe(false); + }); + }); +}); diff --git a/packages/safegres/__tests__/policy.test.ts b/packages/safegres/__tests__/policy.test.ts new file mode 100644 index 0000000..b8dc7fe --- /dev/null +++ b/packages/safegres/__tests__/policy.test.ts @@ -0,0 +1,320 @@ +import { + createPolicy, + createRule, + postgresTarget, + ingressTarget, + egressTarget, + validatePolicy, + directOwner, + membershipByField, + publishable, + anyOf, + always, + type SafegresPolicy, + type SafegresRule, +} from '../src'; + +describe('Policy Types', () => { + describe('createPolicy', () => { + it('should create a policy with required fields', () => { + const policy = createPolicy( + 'test.policy', + '1.0.0', + postgresTarget('public', 'users'), + [] + ); + + expect(policy.id).toBe('test.policy'); + expect(policy.version).toBe('1.0.0'); + expect(policy.target.layer).toBe('postgres'); + expect(policy.target.schema).toBe('public'); + expect(policy.target.table).toBe('users'); + expect(policy.rules).toEqual([]); + }); + + it('should create a policy with optional fields', () => { + const policy = createPolicy( + 'test.policy', + '1.0.0', + postgresTarget('public', 'users'), + [], + { + description: 'Test policy', + tags: ['test', 'users'], + disabled: false, + } + ); + + expect(policy.description).toBe('Test policy'); + expect(policy.tags).toEqual(['test', 'users']); + expect(policy.disabled).toBe(false); + }); + }); + + describe('createRule', () => { + it('should create a rule with required fields', () => { + const rule = createRule( + 'owner_access', + ['authenticated'], + ['select', 'update'], + directOwner('owner_id'), + 'allow' + ); + + expect(rule.name).toBe('owner_access'); + expect(rule.actors).toEqual(['authenticated']); + expect(rule.actions).toEqual(['select', 'update']); + expect(rule.effect).toBe('allow'); + }); + + it('should create a rule with optional fields', () => { + const rule = createRule( + 'owner_access', + ['authenticated'], + ['select'], + directOwner('owner_id'), + 'allow', + { + description: 'Owner can access their records', + permissive: true, + priority: 10, + } + ); + + expect(rule.description).toBe('Owner can access their records'); + expect(rule.permissive).toBe(true); + expect(rule.priority).toBe(10); + }); + }); + + describe('Target Builders', () => { + it('should create postgres target', () => { + const target = postgresTarget('public', 'posts', 'SELECT'); + expect(target).toEqual({ + layer: 'postgres', + schema: 'public', + table: 'posts', + operation: 'SELECT', + }); + }); + + it('should create ingress target', () => { + const target = ingressTarget('api.example.com', '/api/*', 'default'); + expect(target).toEqual({ + layer: 'ingress', + host: 'api.example.com', + path: '/api/*', + namespace: 'default', + }); + }); + + it('should create egress target', () => { + const target = egressTarget('*.s3.amazonaws.com', 'production'); + expect(target).toEqual({ + layer: 'egress', + destination: '*.s3.amazonaws.com', + namespace: 'production', + }); + }); + }); +}); + +describe('Policy Validation', () => { + it('should validate a valid policy', () => { + const policy = createPolicy( + 'test.policy', + '1.0.0', + postgresTarget('public', 'users'), + [ + createRule( + 'owner_access', + ['authenticated'], + ['select'], + directOwner('owner_id'), + 'allow' + ), + ] + ); + + const result = validatePolicy(policy); + expect(result.valid).toBe(true); + expect(result.errors).toHaveLength(0); + }); + + it('should report missing id', () => { + const policy: SafegresPolicy = { + id: '', + version: '1.0.0', + target: postgresTarget('public', 'users'), + rules: [], + }; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_ID' }) + ); + }); + + it('should report missing version', () => { + const policy: SafegresPolicy = { + id: 'test.policy', + version: '', + target: postgresTarget('public', 'users'), + rules: [], + }; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_VERSION' }) + ); + }); + + it('should report missing target', () => { + const policy = { + id: 'test.policy', + version: '1.0.0', + rules: [], + } as SafegresPolicy; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_TARGET' }) + ); + }); + + it('should warn about empty rules', () => { + const policy = createPolicy( + 'test.policy', + '1.0.0', + postgresTarget('public', 'users'), + [] + ); + + const result = validatePolicy(policy); + expect(result.valid).toBe(true); + expect(result.warnings).toContainEqual( + expect.objectContaining({ code: 'NO_RULES' }) + ); + }); + + it('should report missing rule name', () => { + const policy: SafegresPolicy = { + id: 'test.policy', + version: '1.0.0', + target: postgresTarget('public', 'users'), + rules: [ + { + name: '', + actors: ['authenticated'], + actions: ['select'], + condition: always(), + effect: 'allow', + }, + ], + }; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_RULE_NAME' }) + ); + }); + + it('should report missing actors', () => { + const policy: SafegresPolicy = { + id: 'test.policy', + version: '1.0.0', + target: postgresTarget('public', 'users'), + rules: [ + { + name: 'test_rule', + actors: [], + actions: ['select'], + condition: always(), + effect: 'allow', + }, + ], + }; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_ACTORS' }) + ); + }); + + it('should report missing actions', () => { + const policy: SafegresPolicy = { + id: 'test.policy', + version: '1.0.0', + target: postgresTarget('public', 'users'), + rules: [ + { + name: 'test_rule', + actors: ['authenticated'], + actions: [], + condition: always(), + effect: 'allow', + }, + ], + }; + + const result = validatePolicy(policy); + expect(result.valid).toBe(false); + expect(result.errors).toContainEqual( + expect.objectContaining({ code: 'MISSING_ACTIONS' }) + ); + }); +}); + +describe('Complete Policy Example', () => { + it('should create a complete posts access policy', () => { + const postsPolicy = createPolicy( + 'constructive.posts.access', + '1.0.0', + postgresTarget('public', 'posts'), + [ + createRule( + 'owner_full_access', + ['authenticated'], + ['select', 'insert', 'update', 'delete'], + directOwner('owner_id'), + 'allow', + { description: 'Owners have full access to their posts' } + ), + createRule( + 'org_members_read', + ['authenticated'], + ['select'], + membershipByField('entity_id', 'Organization Member', { + permission: 'read_posts', + }), + 'allow', + { description: 'Org members can read posts' } + ), + createRule( + 'published_public', + ['anonymous', 'authenticated'], + ['select'], + publishable('is_published'), + 'allow', + { description: 'Published posts are public' } + ), + ], + { + description: 'Access rules for the posts table', + tags: ['posts', 'content'], + } + ); + + const result = validatePolicy(postsPolicy); + expect(result.valid).toBe(true); + expect(postsPolicy.rules).toHaveLength(3); + expect(postsPolicy.rules[0].name).toBe('owner_full_access'); + expect(postsPolicy.rules[1].name).toBe('org_members_read'); + expect(postsPolicy.rules[2].name).toBe('published_public'); + }); +}); diff --git a/packages/safegres/jest.config.js b/packages/safegres/jest.config.js new file mode 100644 index 0000000..5642f3c --- /dev/null +++ b/packages/safegres/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }] + }, + testMatch: ['**/__tests__/**/*.test.ts'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] +}; diff --git a/packages/safegres/package.json b/packages/safegres/package.json new file mode 100644 index 0000000..f742381 --- /dev/null +++ b/packages/safegres/package.json @@ -0,0 +1,46 @@ +{ + "name": "safegres", + "version": "0.0.1", + "author": "Constructive ", + "description": "Unified security system for postgres, ingress, and egress policies", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/dockerjs", + "license": "SEE LICENSE IN LICENSE", + "publishConfig": { + "access": "restricted", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/dockerjs" + }, + "bugs": { + "url": "https://github.com/constructive-io/dockerjs/issues" + }, + "scripts": { + "copy": "makage assets", + "clean": "makage clean dist", + "prepublishOnly": "npm run build", + "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", + "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", + "lint": "cd ../.. && eslint packages/safegres --fix", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "security", + "policy", + "rls", + "row-level-security", + "postgres", + "nginx", + "ingress", + "egress", + "authorization" + ], + "devDependencies": { + "makage": "^0.1.8" + } +} diff --git a/packages/safegres/src/helpers/access.ts b/packages/safegres/src/helpers/access.ts new file mode 100644 index 0000000..353af8f --- /dev/null +++ b/packages/safegres/src/helpers/access.ts @@ -0,0 +1,113 @@ +/** + * Access Helpers for Safegres + * + * Safe property access and value checking helpers for policy evaluation. + */ + +/** + * Safe property access that never throws + * Supports dot notation paths like "request.headers.authorization" + */ +export function get(obj: unknown, path: string, fallback: T): T { + if (obj === null || obj === undefined) return fallback; + + const parts = path.split('.'); + let current: unknown = obj; + + for (const part of parts) { + if (current === null || current === undefined) return fallback; + if (typeof current !== 'object') return fallback; + current = (current as Record)[part]; + } + + return current === undefined ? fallback : (current as T); +} + +/** + * Check if a value is defined (not null or undefined) + */ +export function defined(value: unknown): boolean { + return value !== null && value !== undefined; +} + +/** + * Check if an array or string is empty + */ +export function empty( + value: unknown[] | string | undefined | null +): boolean { + if (value === null || value === undefined) return true; + return value.length === 0; +} + +/** + * Check if a value is in a list + */ +export function includes(list: readonly T[] | undefined | null, value: T): boolean { + if (!list) return false; + return list.includes(value); +} + +/** + * Check if a value is truthy + */ +export function truthy(value: unknown): boolean { + return Boolean(value); +} + +/** + * Check if a value is falsy + */ +export function falsy(value: unknown): boolean { + return !value; +} + +/** + * Check if two values are equal (deep equality for objects) + */ +export function equals(a: unknown, b: unknown): boolean { + if (a === b) return true; + if (a === null || b === null) return false; + if (a === undefined || b === undefined) return false; + if (typeof a !== typeof b) return false; + + if (typeof a === 'object' && typeof b === 'object') { + const aKeys = Object.keys(a as object); + const bKeys = Object.keys(b as object); + if (aKeys.length !== bKeys.length) return false; + return aKeys.every((key) => + equals( + (a as Record)[key], + (b as Record)[key] + ) + ); + } + + return false; +} + +/** + * Coalesce to first defined value + */ +export function coalesce(...values: (T | undefined | null)[]): T | undefined { + for (const value of values) { + if (value !== null && value !== undefined) return value; + } + return undefined; +} + +/** + * Access helpers object for convenient access + */ +export const access = { + get, + defined, + empty, + includes, + truthy, + falsy, + equals, + coalesce, +}; + +export type AccessHelpers = typeof access; diff --git a/packages/safegres/src/helpers/conditions.ts b/packages/safegres/src/helpers/conditions.ts new file mode 100644 index 0000000..5281194 --- /dev/null +++ b/packages/safegres/src/helpers/conditions.ts @@ -0,0 +1,303 @@ +/** + * Condition Builder Helpers for Safegres + * + * Convenient functions for creating condition nodes. + */ + +import type { + SafegresCondition, + DirectOwner, + DirectOwnerAny, + Membership, + MembershipByField, + MembershipByJoin, + OrgHierarchy, + Temporal, + Publishable, + PathMatch, + HostMatch, + DestinationMatch, + NamespaceMatch, + ServiceMatch, + FieldEquals, + FieldEqualsField, + FieldIn, + FieldNotNull, + FieldIsNull, + BoolExpr, + MembershipType, +} from '../types/conditions'; + +// ============================================================================ +// Identity Condition Builders +// ============================================================================ + +/** + * Create a DirectOwner condition + */ +export function directOwner(entity_field: string): SafegresCondition { + return { DirectOwner: { entity_field } }; +} + +/** + * Create a DirectOwnerAny condition + */ +export function directOwnerAny(entity_fields: string[]): SafegresCondition { + return { DirectOwnerAny: { entity_fields } }; +} + +/** + * Create a Membership condition + */ +export function membership( + membership_type: MembershipType, + options?: Partial> +): SafegresCondition { + return { Membership: { membership_type, ...options } }; +} + +/** + * Create a MembershipByField condition + */ +export function membershipByField( + entity_field: string, + membership_type: MembershipType, + options?: Partial> +): SafegresCondition { + return { MembershipByField: { entity_field, membership_type, ...options } }; +} + +/** + * Create a MembershipByJoin condition + */ +export function membershipByJoin( + entity_field: string, + membership_type: MembershipType, + options?: Partial> +): SafegresCondition { + return { MembershipByJoin: { entity_field, membership_type, ...options } }; +} + +/** + * Create an OrgHierarchy condition + */ +export function orgHierarchy( + direction: 'up' | 'down', + anchor_field: string, + options?: Partial> +): SafegresCondition { + return { OrgHierarchy: { direction, anchor_field, ...options } }; +} + +// ============================================================================ +// Temporal Condition Builders +// ============================================================================ + +/** + * Create a Temporal condition + */ +export function temporal(options: Temporal): SafegresCondition { + return { Temporal: options }; +} + +/** + * Create a Publishable condition + */ +export function publishable(is_published_field: string): SafegresCondition { + return { Publishable: { is_published_field } }; +} + +// ============================================================================ +// Resource Condition Builders +// ============================================================================ + +/** + * Create a PathMatch condition + */ +export function pathMatch( + pattern: string, + method?: string +): SafegresCondition { + return { PathMatch: { pattern, method } }; +} + +/** + * Create a HostMatch condition + */ +export function hostMatch(pattern: string): SafegresCondition { + return { HostMatch: { pattern } }; +} + +/** + * Create a DestinationMatch condition + */ +export function destinationMatch( + host: string, + options?: Partial> +): SafegresCondition { + return { DestinationMatch: { host, ...options } }; +} + +/** + * Create a NamespaceMatch condition + */ +export function namespaceMatch( + pattern: string, + exact?: boolean +): SafegresCondition { + return { NamespaceMatch: { pattern, exact } }; +} + +/** + * Create a ServiceMatch condition + */ +export function serviceMatch( + name: string, + namespace?: string +): SafegresCondition { + return { ServiceMatch: { name, namespace } }; +} + +// ============================================================================ +// Comparison Condition Builders +// ============================================================================ + +/** + * Create a FieldEquals condition + */ +export function fieldEquals( + field: string, + value: string | number | boolean +): SafegresCondition { + return { FieldEquals: { field, value } }; +} + +/** + * Create a FieldEqualsField condition + */ +export function fieldEqualsField( + field: string, + other_field: string +): SafegresCondition { + return { FieldEqualsField: { field, other_field } }; +} + +/** + * Create a FieldIn condition + */ +export function fieldIn( + field: string, + values: (string | number)[] +): SafegresCondition { + return { FieldIn: { field, values } }; +} + +/** + * Create a FieldNotNull condition + */ +export function fieldNotNull(field: string): SafegresCondition { + return { FieldNotNull: { field } }; +} + +/** + * Create a FieldIsNull condition + */ +export function fieldIsNull(field: string): SafegresCondition { + return { FieldIsNull: { field } }; +} + +// ============================================================================ +// Composition Condition Builders +// ============================================================================ + +/** + * Create an AND composition of conditions + */ +export function allOf(...conditions: SafegresCondition[]): SafegresCondition { + if (conditions.length === 0) return { True: {} }; + if (conditions.length === 1) return conditions[0]; + return { AllOf: conditions }; +} + +/** + * Create an OR composition of conditions + */ +export function anyOf(...conditions: SafegresCondition[]): SafegresCondition { + if (conditions.length === 0) return { False: {} }; + if (conditions.length === 1) return conditions[0]; + return { AnyOf: conditions }; +} + +/** + * Create a NOT condition + */ +export function not(condition: SafegresCondition): SafegresCondition { + return { Not: condition }; +} + +/** + * Create a BoolExpr condition + */ +export function boolExpr( + boolop: 'AND_EXPR' | 'OR_EXPR' | 'NOT_EXPR', + args: SafegresCondition[] +): SafegresCondition { + return { BoolExpr: { boolop, args } }; +} + +// ============================================================================ +// Constant Condition Builders +// ============================================================================ + +/** + * Create a True condition (always allows) + */ +export function always(): SafegresCondition { + return { True: {} }; +} + +/** + * Create a False condition (always denies) + */ +export function never(): SafegresCondition { + return { False: {} }; +} + +// ============================================================================ +// Condition Builders Object +// ============================================================================ + +export const conditions = { + // Identity + directOwner, + directOwnerAny, + membership, + membershipByField, + membershipByJoin, + orgHierarchy, + // Temporal + temporal, + publishable, + // Resource + pathMatch, + hostMatch, + destinationMatch, + namespaceMatch, + serviceMatch, + // Comparison + fieldEquals, + fieldEqualsField, + fieldIn, + fieldNotNull, + fieldIsNull, + // Composition + allOf, + anyOf, + not, + boolExpr, + // Constants + always, + never, +}; + +export type ConditionBuilders = typeof conditions; diff --git a/packages/safegres/src/helpers/index.ts b/packages/safegres/src/helpers/index.ts new file mode 100644 index 0000000..26c818d --- /dev/null +++ b/packages/safegres/src/helpers/index.ts @@ -0,0 +1,121 @@ +/** + * Safegres Helpers + * + * Safe, deterministic helper functions for policy evaluation. + */ + +// Match helpers +export { match, exact, iexact, prefix, suffix, contains, glob, regex } from './match'; +export type { MatchHelpers } from './match'; + +// Quantifier helpers +export { + quantifiers, + all, + any, + none, + count, + find, + filter, + map, + first, + last, +} from './quantifiers'; +export type { QuantifierHelpers } from './quantifiers'; + +// Access helpers +export { + access, + get, + defined, + empty, + includes, + truthy, + falsy, + equals, + coalesce, +} from './access'; +export type { AccessHelpers } from './access'; + +// Condition builders +export { + conditions, + directOwner, + directOwnerAny, + membership, + membershipByField, + membershipByJoin, + orgHierarchy, + temporal, + publishable, + pathMatch, + hostMatch, + destinationMatch, + namespaceMatch, + serviceMatch, + fieldEquals, + fieldEqualsField, + fieldIn, + fieldNotNull, + fieldIsNull, + allOf, + anyOf, + not, + boolExpr, + always, + never, +} from './conditions'; +export type { ConditionBuilders } from './conditions'; + +// Combined helpers interface +import { match, type MatchHelpers } from './match'; +import { quantifiers, type QuantifierHelpers } from './quantifiers'; +import { access, type AccessHelpers } from './access'; +import { conditions, type ConditionBuilders } from './conditions'; + +/** + * Combined policy helpers interface + */ +export interface SafegresHelpers { + match: MatchHelpers; + quantifiers: QuantifierHelpers; + access: AccessHelpers; + conditions: ConditionBuilders; + // Shorthand access to common helpers + all: QuantifierHelpers['all']; + any: QuantifierHelpers['any']; + none: QuantifierHelpers['none']; + count: QuantifierHelpers['count']; + find: QuantifierHelpers['find']; + get: AccessHelpers['get']; + defined: AccessHelpers['defined']; + empty: AccessHelpers['empty']; + includes: AccessHelpers['includes']; +} + +/** + * Create the combined helpers object + */ +export function createHelpers(): SafegresHelpers { + return { + match, + quantifiers, + access, + conditions, + // Shorthand + all: quantifiers.all, + any: quantifiers.any, + none: quantifiers.none, + count: quantifiers.count, + find: quantifiers.find, + get: access.get, + defined: access.defined, + empty: access.empty, + includes: access.includes, + }; +} + +/** + * Default helpers instance + */ +export const helpers = createHelpers(); diff --git a/packages/safegres/src/helpers/match.ts b/packages/safegres/src/helpers/match.ts new file mode 100644 index 0000000..95e1cd0 --- /dev/null +++ b/packages/safegres/src/helpers/match.ts @@ -0,0 +1,101 @@ +/** + * String Matching Helpers for Safegres + * + * Safe, deterministic string matching operations for policy evaluation. + */ + +/** + * Exact string equality (case-sensitive) + */ +export function exact(a?: string, b?: string): boolean { + if (a === undefined || b === undefined) return false; + return a === b; +} + +/** + * Case-insensitive exact match + */ +export function iexact(a?: string, b?: string): boolean { + if (a === undefined || b === undefined) return false; + return a.toLowerCase() === b.toLowerCase(); +} + +/** + * Check if value starts with prefix + */ +export function prefix(value: string | undefined, pfx: string): boolean { + if (value === undefined) return false; + return value.startsWith(pfx); +} + +/** + * Check if value ends with suffix + */ +export function suffix(value: string | undefined, sfx: string): boolean { + if (value === undefined) return false; + return value.endsWith(sfx); +} + +/** + * Check if value contains substring + */ +export function contains(value: string | undefined, substr: string): boolean { + if (value === undefined) return false; + return value.includes(substr); +} + +/** + * Simple glob matching (supports * and ?) + * * matches any sequence of characters + * ? matches any single character + */ +export function glob(value: string | undefined, pattern: string): boolean { + if (value === undefined) return false; + + // Convert glob pattern to regex + const regexPattern = pattern + .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars + .replace(/\*/g, '.*') // * -> .* + .replace(/\?/g, '.'); // ? -> . + + try { + const regex = new RegExp(`^${regexPattern}$`); + return regex.test(value); + } catch { + return false; + } +} + +/** + * Safe regex matching with timeout protection + * Returns false on invalid patterns or timeout + */ +export function regex( + value: string | undefined, + pattern: string, + flags?: string +): boolean { + if (value === undefined) return false; + + try { + const re = new RegExp(pattern, flags); + return re.test(value); + } catch { + return false; + } +} + +/** + * Match helpers object for convenient access + */ +export const match = { + exact, + iexact, + prefix, + suffix, + contains, + glob, + regex, +}; + +export type MatchHelpers = typeof match; diff --git a/packages/safegres/src/helpers/quantifiers.ts b/packages/safegres/src/helpers/quantifiers.ts new file mode 100644 index 0000000..d58d18d --- /dev/null +++ b/packages/safegres/src/helpers/quantifiers.ts @@ -0,0 +1,115 @@ +/** + * Quantifier Helpers for Safegres + * + * Safe, deterministic iteration helpers for policy evaluation. + */ + +/** + * Check if all items satisfy the predicate + */ +export function all( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): boolean { + if (!items || items.length === 0) return true; + return items.every(pred); +} + +/** + * Check if any item satisfies the predicate + */ +export function any( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): boolean { + if (!items || items.length === 0) return false; + return items.some(pred); +} + +/** + * Check if no items satisfy the predicate + */ +export function none( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): boolean { + if (!items || items.length === 0) return true; + return !items.some(pred); +} + +/** + * Count items that satisfy the predicate + */ +export function count( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): number { + if (!items || items.length === 0) return 0; + return items.filter(pred).length; +} + +/** + * Find first item that satisfies the predicate + */ +export function find( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): T | undefined { + if (!items || items.length === 0) return undefined; + return items.find(pred); +} + +/** + * Find all items that satisfy the predicate + */ +export function filter( + items: readonly T[] | undefined | null, + pred: (x: T) => boolean +): T[] { + if (!items || items.length === 0) return []; + return items.filter(pred); +} + +/** + * Map items through a transformation function + */ +export function map( + items: readonly T[] | undefined | null, + fn: (x: T) => U +): U[] { + if (!items || items.length === 0) return []; + return items.map(fn); +} + +/** + * Get the first item or undefined + */ +export function first(items: readonly T[] | undefined | null): T | undefined { + if (!items || items.length === 0) return undefined; + return items[0]; +} + +/** + * Get the last item or undefined + */ +export function last(items: readonly T[] | undefined | null): T | undefined { + if (!items || items.length === 0) return undefined; + return items[items.length - 1]; +} + +/** + * Quantifier helpers object for convenient access + */ +export const quantifiers = { + all, + any, + none, + count, + find, + filter, + map, + first, + last, +}; + +export type QuantifierHelpers = typeof quantifiers; diff --git a/packages/safegres/src/index.ts b/packages/safegres/src/index.ts new file mode 100644 index 0000000..e2ad40d --- /dev/null +++ b/packages/safegres/src/index.ts @@ -0,0 +1,14 @@ +/** + * Safegres - Unified Security System + * + * A unified security system that extends TypeScript-based policy evaluation + * from postgres (RLS) to ingress and egress layers. + * + * @packageDocumentation + */ + +// Export all types +export * from './types'; + +// Export all helpers +export * from './helpers'; diff --git a/packages/safegres/src/types/conditions.ts b/packages/safegres/src/types/conditions.ts new file mode 100644 index 0000000..5a31b18 --- /dev/null +++ b/packages/safegres/src/types/conditions.ts @@ -0,0 +1,422 @@ +/** + * Condition Node Types for Safegres + * + * These conditions work across all three security layers: + * - Postgres (RLS): Compiled to SQL WHERE clauses + * - Ingress: Evaluated at HTTP request time + * - Egress: Evaluated for outbound connections + */ + +// ============================================================================ +// Identity Conditions (Who can access) +// ============================================================================ + +/** + * Direct user ID comparison + * Postgres: owner_id = current_user_id() + * Ingress: subject = ctx.identity.subject + */ +export interface DirectOwner { + entity_field: string; +} + +/** + * Multiple ownership fields (OR logic) + * Postgres: sender_id = current_user_id() OR receiver_id = current_user_id() + */ +export interface DirectOwnerAny { + entity_fields: string[]; +} + +/** + * Role/group membership check + * Postgres: EXISTS (SELECT 1 FROM sprt WHERE actor_id = current_user_id() AND ...) + * Ingress: ctx.identity.roles.includes(role) + */ +export interface Membership { + membership_type: MembershipType; + permission?: string; + is_admin?: boolean; + is_owner?: boolean; +} + +/** + * Scoped membership with entity binding + * Postgres: entity_id IN (SELECT entity_id FROM sprt WHERE actor_id = current_user_id()) + */ +export interface MembershipByField { + entity_field: string; + membership_type: MembershipType; + permission?: string; + is_admin?: boolean; + is_owner?: boolean; +} + +/** + * JOIN-based membership through related tables + */ +export interface MembershipByJoin { + entity_field: string; + obj_table_id?: string; + obj_table?: string; + obj_schema?: string; + obj_field_id?: string; + obj_field?: string; + membership_type: MembershipType; + permission?: string; +} + +/** + * Hierarchical visibility using closure table + * Postgres: EXISTS (SELECT 1 FROM hierarchy_sprt WHERE ...) + */ +export interface OrgHierarchy { + direction: 'up' | 'down'; + entity_field?: string; // Default: 'entity_id' + anchor_field: string; + max_depth?: number; +} + +/** + * Membership type can be a string literal or numeric ID + */ +export type MembershipType = + | 'App Member' + | 'Organization Member' + | 'Group Member' + | 'Team Member' + | 'Project Member' + | number; + +// ============================================================================ +// Temporal Conditions (When access is valid) +// ============================================================================ + +/** + * Time-window based access control + * Postgres: publish_at <= now() AND (expires_at IS NULL OR expires_at > now()) + */ +export interface Temporal { + valid_from_field?: string; + valid_until_field?: string; + valid_from_inclusive?: boolean; // Default: true + valid_until_inclusive?: boolean; // Default: false +} + +/** + * Published content visibility + */ +export interface Publishable { + is_published_field: string; +} + +// ============================================================================ +// Resource Conditions (What can be accessed) +// ============================================================================ + +/** + * URL path matching (ingress) + */ +export interface PathMatch { + pattern: string; // Glob or regex + method?: string; // HTTP method filter +} + +/** + * Host/domain matching (ingress/egress) + */ +export interface HostMatch { + pattern: string; // Glob pattern (e.g., "*.example.com") +} + +/** + * Egress destination rules + */ +export interface DestinationMatch { + host: string; + ports?: number[]; + protocol?: string; +} + +/** + * Namespace matching (Kubernetes/mesh) + */ +export interface NamespaceMatch { + pattern: string; + exact?: boolean; +} + +/** + * Service matching (Kubernetes/mesh) + */ +export interface ServiceMatch { + name: string; + namespace?: string; +} + +// ============================================================================ +// Comparison Conditions +// ============================================================================ + +/** + * Field comparison with a value + */ +export interface FieldEquals { + field: string; + value: string | number | boolean; +} + +/** + * Field comparison with another field + */ +export interface FieldEqualsField { + field: string; + other_field: string; +} + +/** + * Field is in a list of values + */ +export interface FieldIn { + field: string; + values: (string | number)[]; +} + +/** + * Field is not null + */ +export interface FieldNotNull { + field: string; +} + +/** + * Field is null + */ +export interface FieldIsNull { + field: string; +} + +// ============================================================================ +// Composition Conditions +// ============================================================================ + +/** + * Boolean expression composition + */ +export interface BoolExpr { + boolop: 'AND_EXPR' | 'OR_EXPR' | 'NOT_EXPR'; + args: SafegresCondition[]; +} + +// ============================================================================ +// Constant Conditions +// ============================================================================ + +/** + * Always true condition + */ +export type TrueCondition = Record; + +/** + * Always false condition + */ +export type FalseCondition = Record; + +// ============================================================================ +// Unified Condition Type (Discriminated Union) +// ============================================================================ + +/** + * SafegresCondition is a discriminated union of all condition types. + * Each condition is wrapped in an object with a single key identifying the type. + */ +export type SafegresCondition = + // Identity conditions + | { DirectOwner: DirectOwner } + | { DirectOwnerAny: DirectOwnerAny } + | { Membership: Membership } + | { MembershipByField: MembershipByField } + | { MembershipByJoin: MembershipByJoin } + | { OrgHierarchy: OrgHierarchy } + // Temporal conditions + | { Temporal: Temporal } + | { Publishable: Publishable } + // Resource conditions (ingress/egress) + | { PathMatch: PathMatch } + | { HostMatch: HostMatch } + | { DestinationMatch: DestinationMatch } + | { NamespaceMatch: NamespaceMatch } + | { ServiceMatch: ServiceMatch } + // Comparison conditions + | { FieldEquals: FieldEquals } + | { FieldEqualsField: FieldEqualsField } + | { FieldIn: FieldIn } + | { FieldNotNull: FieldNotNull } + | { FieldIsNull: FieldIsNull } + // Composition + | { BoolExpr: BoolExpr } + | { AnyOf: SafegresCondition[] } + | { AllOf: SafegresCondition[] } + | { Not: SafegresCondition } + // Constants + | { True: TrueCondition } + | { False: FalseCondition }; + +// ============================================================================ +// Type Guards +// ============================================================================ + +export function isDirectOwner( + c: SafegresCondition +): c is { DirectOwner: DirectOwner } { + return 'DirectOwner' in c; +} + +export function isDirectOwnerAny( + c: SafegresCondition +): c is { DirectOwnerAny: DirectOwnerAny } { + return 'DirectOwnerAny' in c; +} + +export function isMembership( + c: SafegresCondition +): c is { Membership: Membership } { + return 'Membership' in c; +} + +export function isMembershipByField( + c: SafegresCondition +): c is { MembershipByField: MembershipByField } { + return 'MembershipByField' in c; +} + +export function isMembershipByJoin( + c: SafegresCondition +): c is { MembershipByJoin: MembershipByJoin } { + return 'MembershipByJoin' in c; +} + +export function isOrgHierarchy( + c: SafegresCondition +): c is { OrgHierarchy: OrgHierarchy } { + return 'OrgHierarchy' in c; +} + +export function isTemporal( + c: SafegresCondition +): c is { Temporal: Temporal } { + return 'Temporal' in c; +} + +export function isPublishable( + c: SafegresCondition +): c is { Publishable: Publishable } { + return 'Publishable' in c; +} + +export function isPathMatch( + c: SafegresCondition +): c is { PathMatch: PathMatch } { + return 'PathMatch' in c; +} + +export function isHostMatch( + c: SafegresCondition +): c is { HostMatch: HostMatch } { + return 'HostMatch' in c; +} + +export function isDestinationMatch( + c: SafegresCondition +): c is { DestinationMatch: DestinationMatch } { + return 'DestinationMatch' in c; +} + +export function isNamespaceMatch( + c: SafegresCondition +): c is { NamespaceMatch: NamespaceMatch } { + return 'NamespaceMatch' in c; +} + +export function isServiceMatch( + c: SafegresCondition +): c is { ServiceMatch: ServiceMatch } { + return 'ServiceMatch' in c; +} + +export function isFieldEquals( + c: SafegresCondition +): c is { FieldEquals: FieldEquals } { + return 'FieldEquals' in c; +} + +export function isFieldEqualsField( + c: SafegresCondition +): c is { FieldEqualsField: FieldEqualsField } { + return 'FieldEqualsField' in c; +} + +export function isFieldIn(c: SafegresCondition): c is { FieldIn: FieldIn } { + return 'FieldIn' in c; +} + +export function isFieldNotNull( + c: SafegresCondition +): c is { FieldNotNull: FieldNotNull } { + return 'FieldNotNull' in c; +} + +export function isFieldIsNull( + c: SafegresCondition +): c is { FieldIsNull: FieldIsNull } { + return 'FieldIsNull' in c; +} + +export function isBoolExpr( + c: SafegresCondition +): c is { BoolExpr: BoolExpr } { + return 'BoolExpr' in c; +} + +export function isAnyOf( + c: SafegresCondition +): c is { AnyOf: SafegresCondition[] } { + return 'AnyOf' in c; +} + +export function isAllOf( + c: SafegresCondition +): c is { AllOf: SafegresCondition[] } { + return 'AllOf' in c; +} + +export function isNot(c: SafegresCondition): c is { Not: SafegresCondition } { + return 'Not' in c; +} + +export function isTrue( + c: SafegresCondition +): c is { True: TrueCondition } { + return 'True' in c; +} + +export function isFalse( + c: SafegresCondition +): c is { False: FalseCondition } { + return 'False' in c; +} + +/** + * Get the condition type key from a SafegresCondition + */ +export function getConditionType(c: SafegresCondition): string { + return Object.keys(c)[0]; +} + +/** + * Get the condition value from a SafegresCondition + */ +export function getConditionValue(c: SafegresCondition): T { + const key = Object.keys(c)[0]; + return (c as Record)[key]; +} diff --git a/packages/safegres/src/types/context.ts b/packages/safegres/src/types/context.ts new file mode 100644 index 0000000..03ebb81 --- /dev/null +++ b/packages/safegres/src/types/context.ts @@ -0,0 +1,171 @@ +/** + * Context Types for Safegres + * + * These types define the runtime context available during policy evaluation. + */ + +/** + * Request information available during policy evaluation + */ +export interface SafegresRequest { + /** Unique request identifier */ + id: string; + /** Request timestamp in ISO format */ + time: string; + /** Client IP address */ + ip?: string; + /** HTTP method (GET, POST, etc.) */ + method?: string; + /** Request host */ + host?: string; + /** Request path */ + path?: string; + /** Request headers */ + headers?: Record; + /** Query parameters */ + query?: Record; + /** Request body (parsed) */ + body?: unknown; + /** Kubernetes/mesh namespace */ + namespace?: string; + /** Service name */ + service?: string; + /** Operation being performed (e.g., "connect", "query", "deploy") */ + operation?: string; + /** Destination for egress policies */ + destination?: { + host: string; + port?: number; + protocol?: string; + }; +} + +/** + * Identity information available during policy evaluation + */ +export interface SafegresIdentity { + /** User or service principal identifier */ + subject: string; + /** Assigned roles */ + roles?: string[]; + /** Group memberships */ + groups?: string[]; + /** JWT claims or other identity attributes */ + claims?: Record; + /** Postgres-specific: current user ID from JWT */ + user_id?: string; + /** Postgres-specific: current database ID */ + database_id?: string; + /** Postgres-specific: current app ID */ + app_id?: string; + /** Postgres-specific: current organization ID */ + org_id?: string; +} + +/** + * Environment information available during policy evaluation + */ +export interface SafegresEnvironment { + /** Tenant identifier for multi-tenant systems */ + tenantId?: string; + /** Cluster name */ + cluster?: string; + /** Region */ + region?: string; + /** Deployment stage */ + stage?: 'dev' | 'staging' | 'prod'; + /** Additional environment variables */ + vars?: Record; +} + +/** + * Complete context for policy evaluation + */ +export interface SafegresContext { + request: SafegresRequest; + identity: SafegresIdentity; + env: SafegresEnvironment; +} + +/** + * Static data available during policy evaluation + * This includes facts, configurations, and cached data + */ +export interface SafegresData { + /** Namespace to group bindings */ + nsBindings?: Record; + /** Egress allowlist per namespace */ + egressAllow?: Record>; + /** RBAC role definitions */ + rbac?: Record; + /** Rate limit configurations */ + rateLimits?: Record; + /** SPRT (Security Predicate Resolution Table) data */ + sprt?: { + memberships?: Array<{ + actor_id: string; + entity_id: string; + membership_type: string | number; + permission_mask?: number; + is_admin?: boolean; + is_owner?: boolean; + }>; + hierarchy?: Array<{ + ancestor_id: string; + descendant_id: string; + depth: number; + }>; + }; + /** Allow arbitrary additional data */ + [key: string]: unknown; +} + +/** + * Create a minimal context for testing + */ +export function createMinimalContext( + overrides?: Partial +): SafegresContext { + return { + request: { + id: 'test-request', + time: new Date().toISOString(), + ...overrides?.request, + }, + identity: { + subject: 'anonymous', + ...overrides?.identity, + }, + env: { + stage: 'dev', + ...overrides?.env, + }, + }; +} + +/** + * Create an authenticated context for testing + */ +export function createAuthenticatedContext( + userId: string, + roles: string[] = ['authenticated'], + overrides?: Partial +): SafegresContext { + return { + request: { + id: 'test-request', + time: new Date().toISOString(), + ...overrides?.request, + }, + identity: { + subject: userId, + user_id: userId, + roles, + ...overrides?.identity, + }, + env: { + stage: 'dev', + ...overrides?.env, + }, + }; +} diff --git a/packages/safegres/src/types/core.ts b/packages/safegres/src/types/core.ts new file mode 100644 index 0000000..41e1c27 --- /dev/null +++ b/packages/safegres/src/types/core.ts @@ -0,0 +1,38 @@ +/** + * Effect represents the outcome of a policy decision + */ +export type Effect = 'allow' | 'deny'; + +/** + * Reason explains why a decision was made + */ +export interface Reason { + /** Stable identifier for analytics and programmatic handling */ + code: string; + /** Human-readable explanation */ + message: string; + /** Optional path to the relevant context field (e.g., "request.path") */ + path?: string; + /** Optional metadata for debugging */ + meta?: Record; +} + +/** + * TraceStep records a step in policy evaluation for debugging + */ +export interface TraceStep { + step: string; + ok: boolean; + meta?: unknown; +} + +/** + * Decision is the result of policy evaluation + */ +export interface Decision { + effect: Effect; + reasons: Reason[]; + obligations?: import('./obligations').SafegresObligation[]; + /** Optional trace for debugging (can be disabled in production) */ + trace?: TraceStep[]; +} diff --git a/packages/safegres/src/types/index.ts b/packages/safegres/src/types/index.ts new file mode 100644 index 0000000..fd7d8bd --- /dev/null +++ b/packages/safegres/src/types/index.ts @@ -0,0 +1,147 @@ +/** + * Safegres Types + * + * Unified type system for security policies across postgres, ingress, and egress layers. + */ + +// Core types +export type { Effect, Reason, TraceStep, Decision } from './core'; + +// Condition types +export type { + DirectOwner, + DirectOwnerAny, + Membership, + MembershipByField, + MembershipByJoin, + OrgHierarchy, + MembershipType, + Temporal, + Publishable, + PathMatch, + HostMatch, + DestinationMatch, + NamespaceMatch, + ServiceMatch, + FieldEquals, + FieldEqualsField, + FieldIn, + FieldNotNull, + FieldIsNull, + BoolExpr, + TrueCondition, + FalseCondition, + SafegresCondition, +} from './conditions'; + +// Condition type guards +export { + isDirectOwner, + isDirectOwnerAny, + isMembership, + isMembershipByField, + isMembershipByJoin, + isOrgHierarchy, + isTemporal, + isPublishable, + isPathMatch, + isHostMatch, + isDestinationMatch, + isNamespaceMatch, + isServiceMatch, + isFieldEquals, + isFieldEqualsField, + isFieldIn, + isFieldNotNull, + isFieldIsNull, + isBoolExpr, + isAnyOf, + isAllOf, + isNot, + isTrue, + isFalse, + getConditionType, + getConditionValue, +} from './conditions'; + +// Obligation types +export type { + LogObligation, + MaskObligation, + RowFilterObligation, + ColumnMaskObligation, + AuditObligation, + SetHeaderObligation, + RateLimitObligation, + RewriteObligation, + RouteObligation, + CacheObligation, + CorsObligation, + ReturnStatusObligation, + RequireAuthObligation, + AllowDestinationObligation, + DenyDestinationObligation, + ProxyThroughObligation, + SafegresObligation, + ObligationKind, +} from './obligations'; + +// Obligation type guards +export { + isLogObligation, + isMaskObligation, + isRowFilterObligation, + isColumnMaskObligation, + isAuditObligation, + isSetHeaderObligation, + isRateLimitObligation, + isRewriteObligation, + isRouteObligation, + isCacheObligation, + isCorsObligation, + isReturnStatusObligation, + isRequireAuthObligation, + isAllowDestinationObligation, + isDenyDestinationObligation, + isProxyThroughObligation, + isPostgresObligation, + isIngressObligation, + isEgressObligation, + isSharedObligation, +} from './obligations'; + +// Context types +export type { + SafegresRequest, + SafegresIdentity, + SafegresEnvironment, + SafegresContext, + SafegresData, +} from './context'; + +// Context helpers +export { createMinimalContext, createAuthenticatedContext } from './context'; + +// Policy types +export type { + SecurityLayer, + SafegresTarget, + SafegresRule, + SafegresPolicy, + SafegresPolicySet, + CompiledPolicy, + PostgresCompiledPolicy, + NginxCompiledPolicy, + PolicyValidationError, + PolicyValidationResult, +} from './policy'; + +// Policy helpers +export { + createPolicy, + createRule, + postgresTarget, + ingressTarget, + egressTarget, + validatePolicy, +} from './policy'; diff --git a/packages/safegres/src/types/obligations.ts b/packages/safegres/src/types/obligations.ts new file mode 100644 index 0000000..6d6a0d4 --- /dev/null +++ b/packages/safegres/src/types/obligations.ts @@ -0,0 +1,377 @@ +/** + * Obligation Types for Safegres + * + * Obligations are side effects applied after a policy decision. + * They are layer-specific but follow a consistent structure. + */ + +// ============================================================================ +// Shared Obligations (work across all layers) +// ============================================================================ + +/** + * Log an event + */ +export interface LogObligation { + kind: 'log'; + args: { + level: 'debug' | 'info' | 'warn' | 'error'; + message: string; + fields?: Record; + }; +} + +/** + * Mask sensitive data + */ +export interface MaskObligation { + kind: 'mask'; + args: { + fields: string[]; + strategy: 'redact' | 'hash' | 'partial' | 'tokenize'; + }; +} + +// ============================================================================ +// Postgres-specific Obligations +// ============================================================================ + +/** + * Apply additional row filter (beyond the policy condition) + */ +export interface RowFilterObligation { + kind: 'rowFilter'; + args: { + expression: string; + }; +} + +/** + * Mask a column value in query results + */ +export interface ColumnMaskObligation { + kind: 'columnMask'; + args: { + column: string; + mask: string; // SQL expression for masking + }; +} + +/** + * Record an audit log entry + */ +export interface AuditObligation { + kind: 'audit'; + args: { + action: string; + table: string; + fields?: string[]; + }; +} + +// ============================================================================ +// Ingress-specific Obligations +// ============================================================================ + +/** + * Set a response or proxy header + */ +export interface SetHeaderObligation { + kind: 'setHeader'; + args: { + name: string; + value: string; + type?: 'response' | 'proxy' | 'request'; + }; +} + +/** + * Apply rate limiting + */ +export interface RateLimitObligation { + kind: 'rateLimit'; + args: { + zone: string; + rate: string; // e.g., "10r/s", "100r/m" + burst?: number; + nodelay?: boolean; + }; +} + +/** + * Rewrite the request URL + */ +export interface RewriteObligation { + kind: 'rewrite'; + args: { + pattern: string; + replacement: string; + flags?: ('last' | 'break' | 'redirect' | 'permanent')[]; + }; +} + +/** + * Route to a specific upstream + */ +export interface RouteObligation { + kind: 'route'; + args: { + upstream: string; + weight?: number; + backup?: boolean; + }; +} + +/** + * Enable caching + */ +export interface CacheObligation { + kind: 'cache'; + args: { + ttl: number; // seconds + key?: string; + zone?: string; + bypass?: string[]; + }; +} + +/** + * Configure CORS headers + */ +export interface CorsObligation { + kind: 'cors'; + args: { + origins: string[]; + methods?: string[]; + headers?: string[]; + credentials?: boolean; + maxAge?: number; + }; +} + +/** + * Return a specific HTTP status + */ +export interface ReturnStatusObligation { + kind: 'returnStatus'; + args: { + status: number; + body?: string; + }; +} + +/** + * Add authentication requirement + */ +export interface RequireAuthObligation { + kind: 'requireAuth'; + args: { + realm?: string; + type?: 'basic' | 'bearer' | 'jwt'; + }; +} + +// ============================================================================ +// Egress-specific Obligations +// ============================================================================ + +/** + * Allow a destination + */ +export interface AllowDestinationObligation { + kind: 'allowDestination'; + args: { + host: string; + ports?: number[]; + protocol?: string; + }; +} + +/** + * Deny a destination with reason + */ +export interface DenyDestinationObligation { + kind: 'denyDestination'; + args: { + host: string; + reason?: string; + }; +} + +/** + * Proxy through a specific endpoint + */ +export interface ProxyThroughObligation { + kind: 'proxyThrough'; + args: { + proxy: string; + auth?: string; + }; +} + +// ============================================================================ +// Unified Obligation Type +// ============================================================================ + +/** + * SafegresObligation is a union of all obligation types + */ +export type SafegresObligation = + // Shared + | LogObligation + | MaskObligation + // Postgres-specific + | RowFilterObligation + | ColumnMaskObligation + | AuditObligation + // Ingress-specific + | SetHeaderObligation + | RateLimitObligation + | RewriteObligation + | RouteObligation + | CacheObligation + | CorsObligation + | ReturnStatusObligation + | RequireAuthObligation + // Egress-specific + | AllowDestinationObligation + | DenyDestinationObligation + | ProxyThroughObligation; + +/** + * Obligation kind type for type-safe kind checking + */ +export type ObligationKind = SafegresObligation['kind']; + +// ============================================================================ +// Type Guards +// ============================================================================ + +export function isLogObligation(o: SafegresObligation): o is LogObligation { + return o.kind === 'log'; +} + +export function isMaskObligation(o: SafegresObligation): o is MaskObligation { + return o.kind === 'mask'; +} + +export function isRowFilterObligation( + o: SafegresObligation +): o is RowFilterObligation { + return o.kind === 'rowFilter'; +} + +export function isColumnMaskObligation( + o: SafegresObligation +): o is ColumnMaskObligation { + return o.kind === 'columnMask'; +} + +export function isAuditObligation( + o: SafegresObligation +): o is AuditObligation { + return o.kind === 'audit'; +} + +export function isSetHeaderObligation( + o: SafegresObligation +): o is SetHeaderObligation { + return o.kind === 'setHeader'; +} + +export function isRateLimitObligation( + o: SafegresObligation +): o is RateLimitObligation { + return o.kind === 'rateLimit'; +} + +export function isRewriteObligation( + o: SafegresObligation +): o is RewriteObligation { + return o.kind === 'rewrite'; +} + +export function isRouteObligation( + o: SafegresObligation +): o is RouteObligation { + return o.kind === 'route'; +} + +export function isCacheObligation( + o: SafegresObligation +): o is CacheObligation { + return o.kind === 'cache'; +} + +export function isCorsObligation(o: SafegresObligation): o is CorsObligation { + return o.kind === 'cors'; +} + +export function isReturnStatusObligation( + o: SafegresObligation +): o is ReturnStatusObligation { + return o.kind === 'returnStatus'; +} + +export function isRequireAuthObligation( + o: SafegresObligation +): o is RequireAuthObligation { + return o.kind === 'requireAuth'; +} + +export function isAllowDestinationObligation( + o: SafegresObligation +): o is AllowDestinationObligation { + return o.kind === 'allowDestination'; +} + +export function isDenyDestinationObligation( + o: SafegresObligation +): o is DenyDestinationObligation { + return o.kind === 'denyDestination'; +} + +export function isProxyThroughObligation( + o: SafegresObligation +): o is ProxyThroughObligation { + return o.kind === 'proxyThrough'; +} + +/** + * Check if an obligation is postgres-specific + */ +export function isPostgresObligation(o: SafegresObligation): boolean { + return ['rowFilter', 'columnMask', 'audit'].includes(o.kind); +} + +/** + * Check if an obligation is ingress-specific + */ +export function isIngressObligation(o: SafegresObligation): boolean { + return [ + 'setHeader', + 'rateLimit', + 'rewrite', + 'route', + 'cache', + 'cors', + 'returnStatus', + 'requireAuth', + ].includes(o.kind); +} + +/** + * Check if an obligation is egress-specific + */ +export function isEgressObligation(o: SafegresObligation): boolean { + return ['allowDestination', 'denyDestination', 'proxyThrough'].includes( + o.kind + ); +} + +/** + * Check if an obligation is shared across layers + */ +export function isSharedObligation(o: SafegresObligation): boolean { + return ['log', 'mask'].includes(o.kind); +} diff --git a/packages/safegres/src/types/policy.ts b/packages/safegres/src/types/policy.ts new file mode 100644 index 0000000..53c95a7 --- /dev/null +++ b/packages/safegres/src/types/policy.ts @@ -0,0 +1,351 @@ +/** + * Policy and Rule Types for Safegres + * + * These types define the structure of policies and rules + * that can be compiled to multiple targets. + */ + +import type { Effect } from './core'; +import type { SafegresCondition } from './conditions'; +import type { SafegresObligation } from './obligations'; + +/** + * Security layer where a policy applies + */ +export type SecurityLayer = 'postgres' | 'ingress' | 'egress'; + +/** + * Target specifies where a policy applies + */ +export interface SafegresTarget { + /** Security layer */ + layer: SecurityLayer; + /** Postgres: schema name */ + schema?: string; + /** Postgres: table name */ + table?: string; + /** Postgres: operation (SELECT, INSERT, UPDATE, DELETE) */ + operation?: string; + /** Ingress/egress: host pattern */ + host?: string; + /** Ingress: path pattern */ + path?: string; + /** Egress: destination pattern */ + destination?: string; + /** Kubernetes: namespace */ + namespace?: string; + /** Kubernetes: service */ + service?: string; +} + +/** + * Rule defines a single access pattern + */ +export interface SafegresRule { + /** Unique rule name within the policy */ + name: string; + /** Human-readable description */ + description?: string; + /** Actors this rule applies to (role names) */ + actors: string[]; + /** Actions/privileges this rule covers */ + actions: string[]; + /** Condition that must be true for the rule to apply */ + condition: SafegresCondition; + /** Effect when condition is met */ + effect: Effect; + /** Side effects to apply */ + obligations?: SafegresObligation[]; + /** Whether this is a permissive policy (default: true) */ + permissive?: boolean; + /** Whether this rule is disabled */ + disabled?: boolean; + /** Priority for rule ordering (higher = evaluated first) */ + priority?: number; +} + +/** + * Policy is a versioned, composable policy unit + */ +export interface SafegresPolicy { + /** Unique policy identifier (e.g., "constructive.posts.access") */ + id: string; + /** Semantic version */ + version: string; + /** Human-readable description */ + description?: string; + /** Where this policy applies */ + target: SafegresTarget; + /** Access rules */ + rules: SafegresRule[]; + /** Tags for organization and filtering */ + tags?: string[]; + /** Whether this policy is disabled */ + disabled?: boolean; +} + +/** + * PolicySet is a collection of related policies + */ +export interface SafegresPolicySet { + /** Unique identifier */ + id: string; + /** Semantic version */ + version: string; + /** Human-readable description */ + description?: string; + /** Policies in this set */ + policies: SafegresPolicy[]; + /** Tags for organization */ + tags?: string[]; +} + +/** + * Compiled policy output for a specific target + */ +export interface CompiledPolicy { + /** Source policy ID */ + sourceId: string; + /** Source policy version */ + sourceVersion: string; + /** Target layer */ + layer: SecurityLayer; + /** Compilation timestamp */ + compiledAt: string; + /** Target-specific output */ + output: unknown; +} + +/** + * PostgreSQL-specific compiled output + */ +export interface PostgresCompiledPolicy extends CompiledPolicy { + layer: 'postgres'; + output: { + /** CREATE POLICY statements */ + policies: string[]; + /** Supporting functions */ + functions?: string[]; + /** Required extensions */ + extensions?: string[]; + }; +} + +/** + * Nginx-specific compiled output + */ +export interface NginxCompiledPolicy extends CompiledPolicy { + layer: 'ingress'; + output: { + /** Server block configurations */ + servers?: string[]; + /** Location block configurations */ + locations?: string[]; + /** Upstream configurations */ + upstreams?: string[]; + /** Map configurations */ + maps?: string[]; + /** Rate limit zone configurations */ + limitReqZones?: string[]; + }; +} + +// ============================================================================ +// Builder Functions +// ============================================================================ + +/** + * Create a new policy + */ +export function createPolicy( + id: string, + version: string, + target: SafegresTarget, + rules: SafegresRule[], + options?: Partial> +): SafegresPolicy { + return { + id, + version, + target, + rules, + ...options, + }; +} + +/** + * Create a new rule + */ +export function createRule( + name: string, + actors: string[], + actions: string[], + condition: SafegresCondition, + effect: Effect = 'allow', + options?: Partial< + Omit + > +): SafegresRule { + return { + name, + actors, + actions, + condition, + effect, + ...options, + }; +} + +/** + * Create a postgres target + */ +export function postgresTarget( + schema: string, + table: string, + operation?: string +): SafegresTarget { + return { + layer: 'postgres', + schema, + table, + operation, + }; +} + +/** + * Create an ingress target + */ +export function ingressTarget( + host?: string, + path?: string, + namespace?: string +): SafegresTarget { + return { + layer: 'ingress', + host, + path, + namespace, + }; +} + +/** + * Create an egress target + */ +export function egressTarget( + destination?: string, + namespace?: string +): SafegresTarget { + return { + layer: 'egress', + destination, + namespace, + }; +} + +// ============================================================================ +// Validation +// ============================================================================ + +/** + * Validation error for policies + */ +export interface PolicyValidationError { + code: string; + message: string; + path?: string; +} + +/** + * Validation result for policies + */ +export interface PolicyValidationResult { + valid: boolean; + errors: PolicyValidationError[]; + warnings: PolicyValidationError[]; +} + +/** + * Validate a policy structure + */ +export function validatePolicy(policy: SafegresPolicy): PolicyValidationResult { + const errors: PolicyValidationError[] = []; + const warnings: PolicyValidationError[] = []; + + if (!policy.id || policy.id.trim() === '') { + errors.push({ + code: 'MISSING_ID', + message: 'Policy must have an id', + path: 'id', + }); + } + + if (!policy.version || policy.version.trim() === '') { + errors.push({ + code: 'MISSING_VERSION', + message: 'Policy must have a version', + path: 'version', + }); + } + + if (!policy.target) { + errors.push({ + code: 'MISSING_TARGET', + message: 'Policy must have a target', + path: 'target', + }); + } else if (!policy.target.layer) { + errors.push({ + code: 'MISSING_LAYER', + message: 'Policy target must have a layer', + path: 'target.layer', + }); + } + + if (!policy.rules || policy.rules.length === 0) { + warnings.push({ + code: 'NO_RULES', + message: 'Policy has no rules', + path: 'rules', + }); + } else { + policy.rules.forEach((rule, index) => { + if (!rule.name || rule.name.trim() === '') { + errors.push({ + code: 'MISSING_RULE_NAME', + message: `Rule at index ${index} must have a name`, + path: `rules[${index}].name`, + }); + } + + if (!rule.actors || rule.actors.length === 0) { + errors.push({ + code: 'MISSING_ACTORS', + message: `Rule "${rule.name}" must have at least one actor`, + path: `rules[${index}].actors`, + }); + } + + if (!rule.actions || rule.actions.length === 0) { + errors.push({ + code: 'MISSING_ACTIONS', + message: `Rule "${rule.name}" must have at least one action`, + path: `rules[${index}].actions`, + }); + } + + if (!rule.condition) { + errors.push({ + code: 'MISSING_CONDITION', + message: `Rule "${rule.name}" must have a condition`, + path: `rules[${index}].condition`, + }); + } + }); + } + + return { + valid: errors.length === 0, + errors, + warnings, + }; +} diff --git a/packages/safegres/tsconfig.esm.json b/packages/safegres/tsconfig.esm.json new file mode 100644 index 0000000..f106773 --- /dev/null +++ b/packages/safegres/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "ES2020" + } +} diff --git a/packages/safegres/tsconfig.json b/packages/safegres/tsconfig.json new file mode 100644 index 0000000..c1ce63f --- /dev/null +++ b/packages/safegres/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "__tests__"] +} From b12774ea4aeff0a2756c9fbeb5548af55ab6fe71 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 9 Jan 2026 19:18:29 +0000 Subject: [PATCH 07/12] chore: update pnpm-lock.yaml for safegres package --- pnpm-lock.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe3a502..e88d19a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,13 @@ importers: version: 0.1.10 publishDirectory: dist + packages/safegres: + devDependencies: + makage: + specifier: ^0.1.8 + version: 0.1.10 + publishDirectory: dist + packages: '@babel/code-frame@7.27.1': From 875ae3eba0801e7a6cd61a275c2d8963b753a15b Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 10 Jan 2026 10:27:38 +0700 Subject: [PATCH 08/12] wip --- README.md | 8 +------- packages/bash-parser/README.md | 4 ++++ packages/docker-parser/README.md | 4 ++++ packages/nginx-parser/README.md | 4 ++++ packages/policy-engine/README.md | 4 ++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 75c4cad..5a5c22d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,7 @@ # dockerjs

- -

- -

- - - +

Dockerfile and Bash parsers for JavaScript/TypeScript. diff --git a/packages/bash-parser/README.md b/packages/bash-parser/README.md index ddf7d62..39bda65 100644 --- a/packages/bash-parser/README.md +++ b/packages/bash-parser/README.md @@ -1,5 +1,9 @@ # bash-parser +

+ +

+ Bash/shell command parser and deparser for JavaScript/TypeScript. ## Installation diff --git a/packages/docker-parser/README.md b/packages/docker-parser/README.md index d17e84b..f50f8c4 100644 --- a/packages/docker-parser/README.md +++ b/packages/docker-parser/README.md @@ -1,5 +1,9 @@ # docker-parser +

+ +

+ Dockerfile parser and deparser for JavaScript/TypeScript. ## Installation diff --git a/packages/nginx-parser/README.md b/packages/nginx-parser/README.md index c57cab4..72b4eb3 100644 --- a/packages/nginx-parser/README.md +++ b/packages/nginx-parser/README.md @@ -1,5 +1,9 @@ # nginx-parser +

+ +

+ TypeScript Nginx configuration parser and deparser. Parse nginx.conf files into AST and regenerate configuration from AST. ## Installation diff --git a/packages/policy-engine/README.md b/packages/policy-engine/README.md index 9533d61..ddba55b 100644 --- a/packages/policy-engine/README.md +++ b/packages/policy-engine/README.md @@ -1,5 +1,9 @@ # policy-engine +

+ +

+ TypeScript policy engine with deterministic evaluation. Define authorization policies as pure TypeScript functions that return allow/deny decisions with obligations. ## Installation From 02f54e987a862766630ced70b661b993b0e14b35 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 10 Jan 2026 10:39:02 +0700 Subject: [PATCH 09/12] readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a5c22d..7e0ea92 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# dockerjs +# safegres

-Dockerfile and Bash parsers for JavaScript/TypeScript. +Parsers and policy engine for JavaScript/TypeScript. ## Packages @@ -12,6 +12,8 @@ Dockerfile and Bash parsers for JavaScript/TypeScript. |---------|-------------| | [docker-parser](./packages/docker-parser) | Parse Dockerfiles into AST and deparse back to source | | [bash-parser](./packages/bash-parser) | Parse bash/shell commands into AST and deparse back to source | +| [nginx-parser](./packages/nginx-parser) | Parse Nginx configuration into AST and deparse back to source | +| [policy-engine](./packages/policy-engine) | Policy engine with deterministic evaluation | ## Getting Started From fb070360a28123b4526c3cb2eb1d06857cbe9436 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 10 Jan 2026 04:21:34 +0000 Subject: [PATCH 10/12] docs: update README with safegres architecture and mermaid diagrams - Rename project from dockerjs to Safegres - Add architecture overview diagram showing policy definition, engine, and compilers - Add security flow diagram showing ingress, database, and egress layers - Add condition types diagram showing identity, temporal, resource, and composition - Update packages table to include safegres and policy-engine - Add quick example showing policy definition with TypeScript - Add design principles and roadmap sections - Update license to All Rights Reserved, Interweb, Inc. --- README.md | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 215 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 75c4cad..efbccb3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,211 @@ -# dockerjs +# Safegres

- - + +

-Dockerfile and Bash parsers for JavaScript/TypeScript. +**Safegres** is a unified security system that extends TypeScript-based policy evaluation across three security domains: PostgreSQL Row-Level Security (RLS), ingress (HTTP request filtering), and egress (outbound connection control). Define access rules once in TypeScript, compile to multiple targets. + +## Architecture Overview + +```mermaid +flowchart TB + subgraph Definition["Policy Definition Layer"] + Policy["SafegresPolicy
(TypeScript)"] + Rules["SafegresRule[]"] + Conditions["SafegresCondition"] + Obligations["SafegresObligation"] + end + + subgraph Engine["Policy Engine"] + Evaluator["Runtime Evaluator"] + Validator["Policy Validator"] + Helpers["PolicyHelpers
(match, quantifiers, access)"] + end + + subgraph Compilers["Target Compilers"] + PGCompiler["PostgreSQL Compiler"] + NGXCompiler["Nginx Compiler"] + EnvoyCompiler["Envoy Compiler
(Future)"] + end + + subgraph Targets["Security Targets"] + Postgres["PostgreSQL
CREATE POLICY statements"] + Nginx["Nginx
nginx.conf directives"] + Envoy["Envoy
xDS Config"] + end + + Policy --> Rules + Rules --> Conditions + Rules --> Obligations + + Policy --> Evaluator + Evaluator --> Helpers + Validator --> Policy + + Policy --> PGCompiler + Policy --> NGXCompiler + Policy --> EnvoyCompiler + + PGCompiler --> Postgres + NGXCompiler --> Nginx + EnvoyCompiler --> Envoy +``` + +## Security Flow + +The following diagram shows how safegres secures traffic at each layer: + +```mermaid +flowchart LR + subgraph Client["Client"] + Request["HTTP Request"] + end + + subgraph Ingress["Ingress Layer"] + direction TB + NGX["Nginx / API Gateway"] + IngressPolicy["Ingress Policies
- Rate limiting
- Authentication
- Path routing
- CORS"] + end + + subgraph App["Application Layer"] + direction TB + API["GraphQL / REST API"] + JWT["JWT Claims Injection"] + end + + subgraph Database["Database Layer"] + direction TB + PG["PostgreSQL"] + RLS["RLS Policies
- Row filtering
- Column masking
- Ownership checks
- Membership validation"] + end + + subgraph Egress["Egress Layer"] + direction TB + EgressProxy["Egress Proxy"] + EgressPolicy["Egress Policies
- Destination allowlists
- Port restrictions
- Protocol filtering"] + end + + subgraph External["External Services"] + ExtAPI["External APIs"] + end + + Request --> NGX + NGX --> IngressPolicy + IngressPolicy --> API + API --> JWT + JWT --> PG + PG --> RLS + + PG --> EgressProxy + EgressProxy --> EgressPolicy + EgressPolicy --> ExtAPI +``` + +## Condition Types + +Safegres provides a rich set of condition types for expressing access control logic: + +```mermaid +flowchart TB + subgraph Identity["Identity Conditions (Who)"] + DirectOwner["DirectOwner
owner_id = current_user"] + DirectOwnerAny["DirectOwnerAny
sender_id OR receiver_id"] + Membership["Membership
Role/group membership"] + MembershipByField["MembershipByField
Scoped to entity"] + MembershipByJoin["MembershipByJoin
JOIN-based lookup"] + OrgHierarchy["OrgHierarchy
Hierarchical visibility"] + end + + subgraph Temporal["Temporal Conditions (When)"] + TemporalCond["Temporal
Time-window access"] + Publishable["Publishable
Published content"] + end + + subgraph Resource["Resource Conditions (What)"] + PathMatch["PathMatch
URL path matching"] + HostMatch["HostMatch
Domain matching"] + DestinationMatch["DestinationMatch
Egress destinations"] + FieldEquals["FieldEquals
Field comparison"] + end + + subgraph Composition["Composition"] + AllOf["AllOf (AND)"] + AnyOf["AnyOf (OR)"] + Not["Not (negation)"] + BoolExpr["BoolExpr"] + end + + Identity --> Composition + Temporal --> Composition + Resource --> Composition +``` ## Packages | Package | Description | |---------|-------------| -| [docker-parser](./packages/docker-parser) | Parse Dockerfiles into AST and deparse back to source | -| [bash-parser](./packages/bash-parser) | Parse bash/shell commands into AST and deparse back to source | +| [safegres](./packages/safegres) | Core unified types, conditions, obligations, and helpers | +| [policy-engine](./packages/policy-engine) | Runtime policy evaluation with deny-overrides strategy | +| [nginx-parser](./packages/nginx-parser) | Parse and generate Nginx configuration files | +| [docker-parser](./packages/docker-parser) | Parse Dockerfiles into AST with heterogeneous bash parsing | +| [bash-parser](./packages/bash-parser) | Parse bash/shell commands into AST | + +## Quick Example + +```typescript +import { + createPolicy, + createRule, + postgresTarget, + directOwner, + membershipByField, + publishable, + anyOf +} from 'safegres'; + +// Define a policy for the posts table +const postsPolicy = createPolicy({ + id: 'posts.access', + version: '1.0.0', + description: 'Access control for blog posts', + target: postgresTarget('public', 'posts'), + rules: [ + // Owners have full access to their posts + createRule({ + name: 'owner_access', + actors: ['authenticated'], + actions: ['select', 'insert', 'update', 'delete'], + condition: directOwner('owner_id'), + effect: 'allow' + }), + + // Organization members can read posts + createRule({ + name: 'org_member_read', + actors: ['authenticated'], + actions: ['select'], + condition: membershipByField('org_id', 'Organization Member'), + effect: 'allow' + }), + + // Published posts are publicly readable + createRule({ + name: 'public_read', + actors: ['anonymous', 'authenticated'], + actions: ['select'], + condition: publishable('is_published'), + effect: 'allow' + }) + ] +}); +``` ## Getting Started @@ -37,10 +225,31 @@ pnpm test - Node.js 20+ - pnpm +## Design Principles + +1. **Single Source of Truth**: Define access rules once, compile to multiple targets +2. **Intent-Based**: Rules describe business intent, not implementation details +3. **Composable**: Conditions combine with AND/OR/NOT logic +4. **Type-Safe**: Full TypeScript type definitions for all constructs +5. **Deterministic**: Pure functions with no side effects during evaluation +6. **Auditable**: Clear mapping from business rules to technical implementation + +## Roadmap + +- [x] Phase 1: Core unified types and helpers (safegres package) +- [ ] Phase 2: Condition evaluator and policy validator +- [ ] Phase 3: PostgreSQL RLS compiler (safegres-postgres) +- [ ] Phase 4: Nginx compiler (safegres-nginx) +- [ ] Phase 5: Integration testing and benchmarks + ## Credits Built by the [Constructive](https://constructive.io) team. +## License + +All Rights Reserved, Interweb, Inc. + ## Disclaimer AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. From 94590b310d5154308c3447d8f8c253e6850dc6f6 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 10 Jan 2026 04:27:31 +0000 Subject: [PATCH 11/12] docs: add safegres brand header to all package READMEs - Add centered logo image and CI badge to all package READMEs - Updated packages: safegres, policy-engine, docker-parser, bash-parser, nginx-parser --- packages/bash-parser/README.md | 10 ++++++++++ packages/docker-parser/README.md | 10 ++++++++++ packages/nginx-parser/README.md | 10 ++++++++++ packages/policy-engine/README.md | 10 ++++++++++ packages/safegres/README.md | 10 ++++++++++ 5 files changed, 50 insertions(+) diff --git a/packages/bash-parser/README.md b/packages/bash-parser/README.md index ddf7d62..bc244ef 100644 --- a/packages/bash-parser/README.md +++ b/packages/bash-parser/README.md @@ -1,5 +1,15 @@ # bash-parser +

+ +

+ +

+ + + +

+ Bash/shell command parser and deparser for JavaScript/TypeScript. ## Installation diff --git a/packages/docker-parser/README.md b/packages/docker-parser/README.md index d17e84b..4a7a908 100644 --- a/packages/docker-parser/README.md +++ b/packages/docker-parser/README.md @@ -1,5 +1,15 @@ # docker-parser +

+ +

+ +

+ + + +

+ Dockerfile parser and deparser for JavaScript/TypeScript. ## Installation diff --git a/packages/nginx-parser/README.md b/packages/nginx-parser/README.md index c57cab4..0bfadb4 100644 --- a/packages/nginx-parser/README.md +++ b/packages/nginx-parser/README.md @@ -1,5 +1,15 @@ # nginx-parser +

+ +

+ +

+ + + +

+ TypeScript Nginx configuration parser and deparser. Parse nginx.conf files into AST and regenerate configuration from AST. ## Installation diff --git a/packages/policy-engine/README.md b/packages/policy-engine/README.md index 9533d61..41b1590 100644 --- a/packages/policy-engine/README.md +++ b/packages/policy-engine/README.md @@ -1,5 +1,15 @@ # policy-engine +

+ +

+ +

+ + + +

+ TypeScript policy engine with deterministic evaluation. Define authorization policies as pure TypeScript functions that return allow/deny decisions with obligations. ## Installation diff --git a/packages/safegres/README.md b/packages/safegres/README.md index 121b6c6..62a6dd6 100644 --- a/packages/safegres/README.md +++ b/packages/safegres/README.md @@ -1,5 +1,15 @@ # safegres +

+ +

+ +

+ + + +

+ Unified security system for postgres, ingress, and egress policies. ## Overview From 4a2c8d66631074e5e6e44ccacf7c5a645fc08bc8 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 27 Apr 2026 20:25:44 +0000 Subject: [PATCH 12/12] chore: align parser packages with dev-utils conventions (makage build, MIT license, CI matrix) --- .github/workflows/ci.yml | 3 + packages/bash-parser/jest.config.js | 17 +- packages/bash-parser/package.json | 19 +- packages/bash-parser/tsconfig.esm.json | 6 +- packages/bash-parser/tsconfig.json | 6 +- packages/docker-parser/jest.config.js | 17 +- packages/docker-parser/package.json | 19 +- packages/docker-parser/tsconfig.esm.json | 6 +- packages/docker-parser/tsconfig.json | 6 +- packages/nginx-parser/jest.config.js | 16 +- packages/nginx-parser/package.json | 19 +- packages/nginx-parser/tsconfig.esm.json | 4 +- packages/nginx-parser/tsconfig.json | 6 +- pnpm-lock.yaml | 7863 ++++++++-------------- 14 files changed, 2728 insertions(+), 5279 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a42140e..3d57106 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,9 @@ jobs: - genomic - inquirerer-utils - create-gen-app-test + - bash-parser + - docker-parser + - nginx-parser steps: - name: Checkout code diff --git a/packages/bash-parser/jest.config.js b/packages/bash-parser/jest.config.js index 0cdb26d..057a942 100644 --- a/packages/bash-parser/jest.config.js +++ b/packages/bash-parser/jest.config.js @@ -1,9 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { preset: 'ts-jest', testEnvironment: 'node', - testMatch: ['**/__tests__/**/*.test.ts'], + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - collectCoverageFrom: ['src/**/*.ts'], - coverageDirectory: 'coverage', - verbose: true + modulePathIgnorePatterns: ['dist/*'] }; diff --git a/packages/bash-parser/package.json b/packages/bash-parser/package.json index 83c0315..63ad5d1 100644 --- a/packages/bash-parser/package.json +++ b/packages/bash-parser/package.json @@ -6,26 +6,25 @@ "main": "index.js", "module": "esm/index.js", "types": "index.d.ts", - "homepage": "https://github.com/constructive-io/dockerjs", - "license": "SEE LICENSE IN LICENSE", + "homepage": "https://github.com/constructive-io/dev-utils", + "license": "MIT", "publishConfig": { - "access": "restricted", + "access": "public", "directory": "dist" }, "repository": { "type": "git", - "url": "https://github.com/constructive-io/dockerjs" + "url": "https://github.com/constructive-io/dev-utils" }, "bugs": { - "url": "https://github.com/constructive-io/dockerjs/issues" + "url": "https://github.com/constructive-io/dev-utils/issues" }, "scripts": { "copy": "makage assets", - "clean": "makage clean dist", + "clean": "makage clean", "prepublishOnly": "npm run build", - "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", - "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", - "lint": "cd ../.. && eslint packages/bash-parser --fix", + "build": "makage build", + "lint": "eslint . --fix", "test": "jest", "test:watch": "jest --watch" }, @@ -37,6 +36,6 @@ "deparser" ], "devDependencies": { - "makage": "^0.1.8" + "makage": "0.1.10" } } diff --git a/packages/bash-parser/tsconfig.esm.json b/packages/bash-parser/tsconfig.esm.json index aa8f22b..800d750 100644 --- a/packages/bash-parser/tsconfig.esm.json +++ b/packages/bash-parser/tsconfig.esm.json @@ -1,7 +1,9 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "module": "ES2020", - "outDir": "dist/esm" + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false } } diff --git a/packages/bash-parser/tsconfig.json b/packages/bash-parser/tsconfig.json index c1ce63f..1a9d569 100644 --- a/packages/bash-parser/tsconfig.json +++ b/packages/bash-parser/tsconfig.json @@ -2,8 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src/" }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "__tests__"] + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] } diff --git a/packages/docker-parser/jest.config.js b/packages/docker-parser/jest.config.js index 0cdb26d..057a942 100644 --- a/packages/docker-parser/jest.config.js +++ b/packages/docker-parser/jest.config.js @@ -1,9 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { preset: 'ts-jest', testEnvironment: 'node', - testMatch: ['**/__tests__/**/*.test.ts'], + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - collectCoverageFrom: ['src/**/*.ts'], - coverageDirectory: 'coverage', - verbose: true + modulePathIgnorePatterns: ['dist/*'] }; diff --git a/packages/docker-parser/package.json b/packages/docker-parser/package.json index 2f0dd74..5852595 100644 --- a/packages/docker-parser/package.json +++ b/packages/docker-parser/package.json @@ -6,26 +6,25 @@ "main": "index.js", "module": "esm/index.js", "types": "index.d.ts", - "homepage": "https://github.com/constructive-io/dockerjs", - "license": "SEE LICENSE IN LICENSE", + "homepage": "https://github.com/constructive-io/dev-utils", + "license": "MIT", "publishConfig": { - "access": "restricted", + "access": "public", "directory": "dist" }, "repository": { "type": "git", - "url": "https://github.com/constructive-io/dockerjs" + "url": "https://github.com/constructive-io/dev-utils" }, "bugs": { - "url": "https://github.com/constructive-io/dockerjs/issues" + "url": "https://github.com/constructive-io/dev-utils/issues" }, "scripts": { "copy": "makage assets", - "clean": "makage clean dist", + "clean": "makage clean", "prepublishOnly": "npm run build", - "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", - "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", - "lint": "cd ../.. && eslint packages/docker-parser --fix", + "build": "makage build", + "lint": "eslint . --fix", "test": "jest", "test:watch": "jest --watch" }, @@ -40,6 +39,6 @@ "bash-parser": "workspace:*" }, "devDependencies": { - "makage": "^0.1.8" + "makage": "0.1.10" } } diff --git a/packages/docker-parser/tsconfig.esm.json b/packages/docker-parser/tsconfig.esm.json index aa8f22b..800d750 100644 --- a/packages/docker-parser/tsconfig.esm.json +++ b/packages/docker-parser/tsconfig.esm.json @@ -1,7 +1,9 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "module": "ES2020", - "outDir": "dist/esm" + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false } } diff --git a/packages/docker-parser/tsconfig.json b/packages/docker-parser/tsconfig.json index c1ce63f..1a9d569 100644 --- a/packages/docker-parser/tsconfig.json +++ b/packages/docker-parser/tsconfig.json @@ -2,8 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src/" }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "__tests__"] + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] } diff --git a/packages/nginx-parser/jest.config.js b/packages/nginx-parser/jest.config.js index 5642f3c..057a942 100644 --- a/packages/nginx-parser/jest.config.js +++ b/packages/nginx-parser/jest.config.js @@ -1,8 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { + preset: 'ts-jest', testEnvironment: 'node', transform: { - '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }] + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], }, - testMatch: ['**/__tests__/**/*.test.ts'], - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + modulePathIgnorePatterns: ['dist/*'] }; diff --git a/packages/nginx-parser/package.json b/packages/nginx-parser/package.json index ca99356..a452e96 100644 --- a/packages/nginx-parser/package.json +++ b/packages/nginx-parser/package.json @@ -6,26 +6,25 @@ "main": "index.js", "module": "esm/index.js", "types": "index.d.ts", - "homepage": "https://github.com/constructive-io/dockerjs", - "license": "SEE LICENSE IN LICENSE", + "homepage": "https://github.com/constructive-io/dev-utils", + "license": "MIT", "publishConfig": { - "access": "restricted", + "access": "public", "directory": "dist" }, "repository": { "type": "git", - "url": "https://github.com/constructive-io/dockerjs" + "url": "https://github.com/constructive-io/dev-utils" }, "bugs": { - "url": "https://github.com/constructive-io/dockerjs/issues" + "url": "https://github.com/constructive-io/dev-utils/issues" }, "scripts": { "copy": "makage assets", - "clean": "makage clean dist", + "clean": "makage clean", "prepublishOnly": "npm run build", - "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy", - "build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy", - "lint": "cd ../.. && eslint packages/nginx-parser --fix", + "build": "makage build", + "lint": "eslint . --fix", "test": "jest", "test:watch": "jest --watch" }, @@ -37,6 +36,6 @@ "typescript" ], "devDependencies": { - "makage": "^0.1.8" + "makage": "0.1.10" } } diff --git a/packages/nginx-parser/tsconfig.esm.json b/packages/nginx-parser/tsconfig.esm.json index f106773..800d750 100644 --- a/packages/nginx-parser/tsconfig.esm.json +++ b/packages/nginx-parser/tsconfig.esm.json @@ -2,6 +2,8 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "dist/esm", - "module": "ES2020" + "module": "es2022", + "rootDir": "src/", + "declaration": false } } diff --git a/packages/nginx-parser/tsconfig.json b/packages/nginx-parser/tsconfig.json index c1ce63f..1a9d569 100644 --- a/packages/nginx-parser/tsconfig.json +++ b/packages/nginx-parser/tsconfig.json @@ -2,8 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src/" }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "__tests__"] + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1df1531..a63fde0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,22 +1,23 @@ -lockfileVersion: "9.0" +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false importers: + .: devDependencies: - "@types/jest": + '@types/jest': specifier: ^30.0.0 version: 30.0.0 - "@types/node": + '@types/node': specifier: ^22.10.2 version: 22.19.1 - "@typescript-eslint/eslint-plugin": + '@typescript-eslint/eslint-plugin': specifier: ^8.53.1 version: 8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - "@typescript-eslint/parser": + '@typescript-eslint/parser': specifier: ^8.53.1 version: 8.53.1(eslint@9.39.2)(typescript@5.9.3) cpy-cli: @@ -66,18 +67,25 @@ importers: version: 0.1.10 publishDirectory: dist + packages/bash-parser: + devDependencies: + makage: + specifier: 0.1.10 + version: 0.1.10 + publishDirectory: dist + packages/cel-proto-parser: dependencies: - "@babel/generator": + '@babel/generator': specifier: ^7.28.6 version: 7.28.6 - "@babel/types": + '@babel/types': specifier: ^7.28.6 version: 7.28.6 - "@launchql/protobufjs": + '@launchql/protobufjs': specifier: ^7.2.6 version: 7.2.6 - "@marcbachmann/cel-js": + '@marcbachmann/cel-js': specifier: ^7.1.0 version: 7.1.0 nested-obj: @@ -87,7 +95,7 @@ importers: specifier: workspace:* version: link:../strfy-js/dist devDependencies: - "@types/babel__generator": + '@types/babel__generator': specifier: ^7.6.8 version: 7.27.0 makage: @@ -120,7 +128,7 @@ importers: specifier: ^1.2.8 version: 1.2.8 devDependencies: - "@types/minimist": + '@types/minimist': specifier: ^1.2.5 version: 1.2.5 makage: @@ -128,16 +136,27 @@ importers: version: 0.1.10 publishDirectory: dist + packages/docker-parser: + dependencies: + bash-parser: + specifier: workspace:* + version: link:../bash-parser/dist + devDependencies: + makage: + specifier: 0.1.10 + version: 0.1.10 + publishDirectory: dist + packages/fetch-api-client: dependencies: - "@constructive-io/http-errors": + '@constructive-io/http-errors': specifier: workspace:* version: link:../http-errors/dist isomorphic-fetch: specifier: ^3.0.0 version: 3.0.0(encoding@0.1.13) devDependencies: - "@types/isomorphic-fetch": + '@types/isomorphic-fetch': specifier: ^0.0.39 version: 0.0.39 makage: @@ -205,7 +224,7 @@ importers: specifier: workspace:* version: link:../yanse/dist devDependencies: - "@types/minimist": + '@types/minimist': specifier: ^1.2.5 version: 1.2.5 clean-ansi: @@ -228,10 +247,10 @@ importers: specifier: workspace:* version: link:../inquirerer/dist devDependencies: - "@types/jest": + '@types/jest': specifier: ^30.0.0 version: 30.0.0 - "@types/minimist": + '@types/minimist': specifier: ^1.2.5 version: 1.2.5 jest: @@ -254,10 +273,10 @@ importers: specifier: ^7.7.4 version: 7.7.4 devDependencies: - "@types/minimist": + '@types/minimist': specifier: ^1.2.5 version: 1.2.5 - "@types/semver": + '@types/semver': specifier: ^7.7.1 version: 7.7.1 makage: @@ -297,9 +316,16 @@ importers: version: 0.1.10 publishDirectory: dist + packages/nginx-parser: + devDependencies: + makage: + specifier: 0.1.10 + version: 0.1.10 + publishDirectory: dist + packages/node-api-client: dependencies: - "@constructive-io/http-errors": + '@constructive-io/http-errors': specifier: workspace:* version: link:../http-errors/dist devDependencies: @@ -317,19 +343,19 @@ importers: packages/schema-sdk: dependencies: - "@babel/generator": + '@babel/generator': specifier: 7.28.6 version: 7.28.6 - "@babel/parser": + '@babel/parser': specifier: ^7.28.6 version: 7.28.6 - "@babel/traverse": + '@babel/traverse': specifier: 7.28.6 version: 7.28.6 - "@babel/types": + '@babel/types': specifier: 7.28.6 version: 7.28.6 - "@constructive-io/fetch-api-client": + '@constructive-io/fetch-api-client': specifier: workspace:* version: link:../fetch-api-client/dist deepmerge: @@ -345,7 +371,7 @@ importers: specifier: workspace:* version: link:../schema-typescript/dist devDependencies: - "@types/babel__generator": + '@types/babel__generator': specifier: ^7.27.0 version: 7.27.0 jest-diff: @@ -365,10 +391,10 @@ importers: packages/schema-typescript: dependencies: - "@babel/generator": + '@babel/generator': specifier: ^7.28.6 version: 7.28.6 - "@babel/types": + '@babel/types': specifier: ^7.28.6 version: 7.28.6 deepmerge: @@ -381,7 +407,7 @@ importers: specifier: ^10.1.1 version: 10.1.1 devDependencies: - "@types/babel__generator": + '@types/babel__generator': specifier: ^7.27.0 version: 7.27.0 makage: @@ -422,2325 +448,1351 @@ importers: publishDirectory: dist packages: - "@babel/code-frame@7.27.1": - resolution: - { - integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==, - } - engines: { node: ">=6.9.0" } - - "@babel/code-frame@7.28.6": - resolution: - { - integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==, - } - engines: { node: ">=6.9.0" } - - "@babel/compat-data@7.28.5": - resolution: - { - integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==, - } - engines: { node: ">=6.9.0" } - - "@babel/core@7.28.5": - resolution: - { - integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==, - } - engines: { node: ">=6.9.0" } - - "@babel/generator@7.28.6": - resolution: - { - integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-compilation-targets@7.27.2": - resolution: - { - integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-globals@7.28.0": - resolution: - { - integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-module-imports@7.27.1": - resolution: - { - integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-module-transforms@7.28.3": - resolution: - { - integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==, - } - engines: { node: ">=6.9.0" } + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/code-frame@7.28.6': + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.6': + resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-plugin-utils@7.27.1": - resolution: - { - integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-string-parser@7.27.1": - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-validator-identifier@7.28.5": - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-validator-option@7.27.1": - resolution: - { - integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, - } - engines: { node: ">=6.9.0" } - - "@babel/helpers@7.28.4": - resolution: - { - integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==, - } - engines: { node: ">=6.9.0" } - - "@babel/parser@7.28.6": - resolution: - { - integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==, - } - engines: { node: ">=6.0.0" } + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.6': + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + engines: {node: '>=6.0.0'} hasBin: true - "@babel/plugin-syntax-async-generators@7.8.4": - resolution: - { - integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==, - } + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-bigint@7.8.3": - resolution: - { - integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==, - } + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-class-properties@7.12.13": - resolution: - { - integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==, - } + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-class-static-block@7.14.5": - resolution: - { - integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-import-attributes@7.27.1": - resolution: - { - integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-import-meta@7.10.4": - resolution: - { - integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==, - } + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-json-strings@7.8.3": - resolution: - { - integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==, - } + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-jsx@7.27.1": - resolution: - { - integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-logical-assignment-operators@7.10.4": - resolution: - { - integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==, - } + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-nullish-coalescing-operator@7.8.3": - resolution: - { - integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==, - } + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-numeric-separator@7.10.4": - resolution: - { - integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==, - } + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-object-rest-spread@7.8.3": - resolution: - { - integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==, - } + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-optional-catch-binding@7.8.3": - resolution: - { - integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==, - } + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@babel/plugin-syntax-optional-chaining@7.8.3": - resolution: - { - integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==, - } + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-private-property-in-object@7.14.5": - resolution: - { - integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-top-level-await@7.14.5": - resolution: - { - integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-typescript@7.27.1": - resolution: - { - integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==, - } - engines: { node: ">=6.9.0" } + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/template@7.27.2": - resolution: - { - integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==, - } - engines: { node: ">=6.9.0" } - - "@babel/template@7.28.6": - resolution: - { - integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, - } - engines: { node: ">=6.9.0" } - - "@babel/traverse@7.28.6": - resolution: - { - integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==, - } - engines: { node: ">=6.9.0" } - - "@babel/types@7.28.6": - resolution: - { - integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==, - } - engines: { node: ">=6.9.0" } - - "@bcoe/v8-coverage@0.2.3": - resolution: - { - integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, - } - - "@cspotcode/source-map-support@0.8.1": - resolution: - { - integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, - } - engines: { node: ">=12" } - - "@emnapi/core@1.7.1": - resolution: - { - integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==, - } - - "@emnapi/runtime@1.7.1": - resolution: - { - integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==, - } - - "@emnapi/wasi-threads@1.1.0": - resolution: - { - integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==, - } - - "@eslint-community/eslint-utils@4.9.1": - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.6': + resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.6': + resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - "@eslint-community/regexpp@4.12.2": - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } - - "@eslint/config-array@0.21.1": - resolution: - { - integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/config-helpers@0.4.2": - resolution: - { - integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/core@0.17.0": - resolution: - { - integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/eslintrc@3.3.3": - resolution: - { - integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/js@9.39.2": - resolution: - { - integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/object-schema@2.1.7": - resolution: - { - integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/plugin-kit@0.4.1": - resolution: - { - integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@humanfs/core@0.19.1": - resolution: - { - integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==, - } - engines: { node: ">=18.18.0" } - - "@humanfs/node@0.16.7": - resolution: - { - integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==, - } - engines: { node: ">=18.18.0" } - - "@humanwhocodes/module-importer@1.0.1": - resolution: - { - integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, - } - engines: { node: ">=12.22" } - - "@humanwhocodes/retry@0.4.3": - resolution: - { - integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, - } - engines: { node: ">=18.18" } - - "@hutson/parse-repository-url@3.0.2": - resolution: - { - integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==, - } - engines: { node: ">=6.9.0" } - - "@inquirer/external-editor@1.0.3": - resolution: - { - integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==, - } - engines: { node: ">=18" } + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@hutson/parse-repository-url@3.0.2': + resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} + engines: {node: '>=6.9.0'} + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} peerDependencies: - "@types/node": ">=18" + '@types/node': '>=18' peerDependenciesMeta: - "@types/node": + '@types/node': optional: true - "@isaacs/balanced-match@4.0.1": - resolution: - { - integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==, - } - engines: { node: 20 || >=22 } - - "@isaacs/brace-expansion@5.0.0": - resolution: - { - integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==, - } - engines: { node: 20 || >=22 } - - "@isaacs/cliui@8.0.2": - resolution: - { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, - } - engines: { node: ">=12" } - - "@isaacs/string-locale-compare@1.1.0": - resolution: - { - integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==, - } - - "@istanbuljs/load-nyc-config@1.1.0": - resolution: - { - integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==, - } - engines: { node: ">=8" } - - "@istanbuljs/schema@0.1.3": - resolution: - { - integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==, - } - engines: { node: ">=8" } - - "@jest/console@30.2.0": - resolution: - { - integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/core@30.2.0": - resolution: - { - integrity: sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/string-locale-compare@1.1.0': + resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@30.2.0': + resolution: {integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/core@30.2.0': + resolution: {integrity: sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - "@jest/diff-sequences@30.0.1": - resolution: - { - integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/environment@30.2.0": - resolution: - { - integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/expect-utils@30.2.0": - resolution: - { - integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/expect@30.2.0": - resolution: - { - integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/fake-timers@30.2.0": - resolution: - { - integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/get-type@30.1.0": - resolution: - { - integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/globals@30.2.0": - resolution: - { - integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/pattern@30.0.1": - resolution: - { - integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/reporters@30.2.0": - resolution: - { - integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment@30.2.0': + resolution: {integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.2.0': + resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect@30.2.0': + resolution: {integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/fake-timers@30.2.0': + resolution: {integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.2.0': + resolution: {integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.1': + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.2.0': + resolution: {integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - "@jest/schemas@29.6.3": - resolution: - { - integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } - - "@jest/schemas@30.0.5": - resolution: - { - integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/snapshot-utils@30.2.0": - resolution: - { - integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/source-map@30.0.1": - resolution: - { - integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/test-result@30.2.0": - resolution: - { - integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/test-sequencer@30.2.0": - resolution: - { - integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/transform@30.2.0": - resolution: - { - integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jest/types@30.2.0": - resolution: - { - integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - - "@jridgewell/gen-mapping@0.3.13": - resolution: - { - integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, - } - - "@jridgewell/remapping@2.3.5": - resolution: - { - integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, - } - - "@jridgewell/resolve-uri@3.1.2": - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: ">=6.0.0" } - - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } - - "@jridgewell/trace-mapping@0.3.31": - resolution: - { - integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, - } - - "@jridgewell/trace-mapping@0.3.9": - resolution: - { - integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, - } - - "@launchql/protobufjs@7.2.6": - resolution: - { - integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==, - } - engines: { node: ">=12.0.0" } - - "@lerna/create@8.2.4": - resolution: - { - integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==, - } - engines: { node: ">=18.0.0" } + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.2.0': + resolution: {integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-result@30.2.0': + resolution: {integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-sequencer@30.2.0': + resolution: {integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/transform@30.2.0': + resolution: {integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@30.2.0': + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@launchql/protobufjs@7.2.6': + resolution: {integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==} + engines: {node: '>=12.0.0'} + + '@lerna/create@8.2.4': + resolution: {integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==} + engines: {node: '>=18.0.0'} deprecated: This package is an implementation detail of Lerna and is no longer published separately. - "@marcbachmann/cel-js@7.1.0": - resolution: - { - integrity: sha512-pWAOYqaH41M47OBzt9OPcam7qello+vAdrjt+c2UFEbjVUjQq9rTfCRnEtzIAEScwarkPX90M5qMv0MK2ao5ZQ==, - } - engines: { node: ">=20.19.0" } + '@marcbachmann/cel-js@7.1.0': + resolution: {integrity: sha512-pWAOYqaH41M47OBzt9OPcam7qello+vAdrjt+c2UFEbjVUjQq9rTfCRnEtzIAEScwarkPX90M5qMv0MK2ao5ZQ==} + engines: {node: '>=20.19.0'} hasBin: true - "@napi-rs/wasm-runtime@0.2.12": - resolution: - { - integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==, - } - - "@napi-rs/wasm-runtime@0.2.4": - resolution: - { - integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==, - } - - "@nodelib/fs.scandir@2.1.5": - resolution: - { - integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, - } - engines: { node: ">= 8" } - - "@nodelib/fs.stat@2.0.5": - resolution: - { - integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, - } - engines: { node: ">= 8" } - - "@nodelib/fs.walk@1.2.8": - resolution: - { - integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, - } - engines: { node: ">= 8" } - - "@npmcli/agent@2.2.2": - resolution: - { - integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/arborist@7.5.4": - resolution: - { - integrity: sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@napi-rs/wasm-runtime@0.2.4': + resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@npmcli/agent@2.2.2': + resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/arborist@7.5.4': + resolution: {integrity: sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true - "@npmcli/fs@3.1.1": - resolution: - { - integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - "@npmcli/git@5.0.8": - resolution: - { - integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/installed-package-contents@2.1.0": - resolution: - { - integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + '@npmcli/fs@3.1.1': + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/git@5.0.8': + resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/installed-package-contents@2.1.0': + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true - "@npmcli/map-workspaces@3.0.6": - resolution: - { - integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - "@npmcli/metavuln-calculator@7.1.1": - resolution: - { - integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/name-from-folder@2.0.0": - resolution: - { - integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - "@npmcli/node-gyp@3.0.0": - resolution: - { - integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - "@npmcli/package-json@5.2.0": - resolution: - { - integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/promise-spawn@7.0.2": - resolution: - { - integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/query@3.1.0": - resolution: - { - integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - "@npmcli/redact@2.0.1": - resolution: - { - integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@npmcli/run-script@8.1.0": - resolution: - { - integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@nx/devkit@20.8.3": - resolution: - { - integrity: sha512-5lbfJ6ICFOiGeirldQOU5fQ/W/VQ8L3dfWnmHG4UgpWSLoK/YFdRf4lTB4rS0aDXsBL0gyWABz3sZGLPGNYnPA==, - } + '@npmcli/map-workspaces@3.0.6': + resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/metavuln-calculator@7.1.1': + resolution: {integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/name-from-folder@2.0.0': + resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/node-gyp@3.0.0': + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/package-json@5.2.0': + resolution: {integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/promise-spawn@7.0.2': + resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/query@3.1.0': + resolution: {integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/redact@2.0.1': + resolution: {integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/run-script@8.1.0': + resolution: {integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@nx/devkit@20.8.3': + resolution: {integrity: sha512-5lbfJ6ICFOiGeirldQOU5fQ/W/VQ8L3dfWnmHG4UgpWSLoK/YFdRf4lTB4rS0aDXsBL0gyWABz3sZGLPGNYnPA==} peerDependencies: - nx: ">= 19 <= 21" - - "@nx/nx-darwin-arm64@20.8.3": - resolution: - { - integrity: sha512-BeYnPAcnaerg6q+qR0bAb0nebwwrsvm4STSVqqVlaqLmmQpU3Bfpx44CEa5d6T9b0V11ZqVE/bkmRhMqhUcrhw==, - } - engines: { node: ">= 10" } + nx: '>= 19 <= 21' + + '@nx/nx-darwin-arm64@20.8.3': + resolution: {integrity: sha512-BeYnPAcnaerg6q+qR0bAb0nebwwrsvm4STSVqqVlaqLmmQpU3Bfpx44CEa5d6T9b0V11ZqVE/bkmRhMqhUcrhw==} + engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - "@nx/nx-darwin-x64@20.8.3": - resolution: - { - integrity: sha512-RIFg1VkQ4jhI+ErqEZuIeGBcJGD8t+u9J5CdQBDIASd8QRhtudBkiYLYCJb+qaQly09G7nVfxuyItlS2uRW3qA==, - } - engines: { node: ">= 10" } + '@nx/nx-darwin-x64@20.8.3': + resolution: {integrity: sha512-RIFg1VkQ4jhI+ErqEZuIeGBcJGD8t+u9J5CdQBDIASd8QRhtudBkiYLYCJb+qaQly09G7nVfxuyItlS2uRW3qA==} + engines: {node: '>= 10'} cpu: [x64] os: [darwin] - "@nx/nx-freebsd-x64@20.8.3": - resolution: - { - integrity: sha512-boQTgMUdnqpZhHMrV/xgnp/dTg5dfxw8I4d16NBwmW4j+Sez7zi/dydgsJpfZsj8TicOHvPu6KK4W5wzp82NPw==, - } - engines: { node: ">= 10" } + '@nx/nx-freebsd-x64@20.8.3': + resolution: {integrity: sha512-boQTgMUdnqpZhHMrV/xgnp/dTg5dfxw8I4d16NBwmW4j+Sez7zi/dydgsJpfZsj8TicOHvPu6KK4W5wzp82NPw==} + engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - "@nx/nx-linux-arm-gnueabihf@20.8.3": - resolution: - { - integrity: sha512-wpiNyY1igx1rLN3EsTLum2lDtblFijdBZB9/9u/6UDub4z9CaQ4yaC4h9n5v7yFYILwfL44YTsQKzrE+iv0y1Q==, - } - engines: { node: ">= 10" } + '@nx/nx-linux-arm-gnueabihf@20.8.3': + resolution: {integrity: sha512-wpiNyY1igx1rLN3EsTLum2lDtblFijdBZB9/9u/6UDub4z9CaQ4yaC4h9n5v7yFYILwfL44YTsQKzrE+iv0y1Q==} + engines: {node: '>= 10'} cpu: [arm] os: [linux] - "@nx/nx-linux-arm64-gnu@20.8.3": - resolution: - { - integrity: sha512-nbi/eZtJfWxuDwdUCiP+VJolFubtrz6XxVtB26eMAkODnREOKELHZtMOrlm8JBZCdtWCvTqibq9Az74XsqSfdA==, - } - engines: { node: ">= 10" } + '@nx/nx-linux-arm64-gnu@20.8.3': + resolution: {integrity: sha512-nbi/eZtJfWxuDwdUCiP+VJolFubtrz6XxVtB26eMAkODnREOKELHZtMOrlm8JBZCdtWCvTqibq9Az74XsqSfdA==} + engines: {node: '>= 10'} cpu: [arm64] os: [linux] - "@nx/nx-linux-arm64-musl@20.8.3": - resolution: - { - integrity: sha512-LTTGzI8YVPlF1v0YlVf+exM+1q7rpsiUbjTTHJcfHFRU5t4BsiZD54K19Y1UBg1XFx5cwhEaIomSmJ88RwPPVQ==, - } - engines: { node: ">= 10" } + '@nx/nx-linux-arm64-musl@20.8.3': + resolution: {integrity: sha512-LTTGzI8YVPlF1v0YlVf+exM+1q7rpsiUbjTTHJcfHFRU5t4BsiZD54K19Y1UBg1XFx5cwhEaIomSmJ88RwPPVQ==} + engines: {node: '>= 10'} cpu: [arm64] os: [linux] - "@nx/nx-linux-x64-gnu@20.8.3": - resolution: - { - integrity: sha512-SlA4GtXvQbSzSIWLgiIiLBOjdINPOUR/im+TUbaEMZ8wiGrOY8cnk0PVt95TIQJVBeXBCeb5HnoY0lHJpMOODg==, - } - engines: { node: ">= 10" } + '@nx/nx-linux-x64-gnu@20.8.3': + resolution: {integrity: sha512-SlA4GtXvQbSzSIWLgiIiLBOjdINPOUR/im+TUbaEMZ8wiGrOY8cnk0PVt95TIQJVBeXBCeb5HnoY0lHJpMOODg==} + engines: {node: '>= 10'} cpu: [x64] os: [linux] - "@nx/nx-linux-x64-musl@20.8.3": - resolution: - { - integrity: sha512-MNzkEwPktp5SQH9dJDH2wP9hgG9LsBDhKJXJfKw6sUI/6qz5+/aAjFziKy+zBnhU4AO1yXt5qEWzR8lDcIriVQ==, - } - engines: { node: ">= 10" } + '@nx/nx-linux-x64-musl@20.8.3': + resolution: {integrity: sha512-MNzkEwPktp5SQH9dJDH2wP9hgG9LsBDhKJXJfKw6sUI/6qz5+/aAjFziKy+zBnhU4AO1yXt5qEWzR8lDcIriVQ==} + engines: {node: '>= 10'} cpu: [x64] os: [linux] - "@nx/nx-win32-arm64-msvc@20.8.3": - resolution: - { - integrity: sha512-qUV7CyXKwRCM/lkvyS6Xa1MqgAuK5da6w27RAehh7LATBUKn1I4/M7DGn6L7ERCxpZuh1TrDz9pUzEy0R+Ekkg==, - } - engines: { node: ">= 10" } + '@nx/nx-win32-arm64-msvc@20.8.3': + resolution: {integrity: sha512-qUV7CyXKwRCM/lkvyS6Xa1MqgAuK5da6w27RAehh7LATBUKn1I4/M7DGn6L7ERCxpZuh1TrDz9pUzEy0R+Ekkg==} + engines: {node: '>= 10'} cpu: [arm64] os: [win32] - "@nx/nx-win32-x64-msvc@20.8.3": - resolution: - { - integrity: sha512-gX1G8u6W6EPX6PO/wv07+B++UHyCHBXyVWXITA3Kv6HoSajOxIa2Kk1rv1iDQGmX1WWxBaj3bUyYJAFBDITe4w==, - } - engines: { node: ">= 10" } + '@nx/nx-win32-x64-msvc@20.8.3': + resolution: {integrity: sha512-gX1G8u6W6EPX6PO/wv07+B++UHyCHBXyVWXITA3Kv6HoSajOxIa2Kk1rv1iDQGmX1WWxBaj3bUyYJAFBDITe4w==} + engines: {node: '>= 10'} cpu: [x64] os: [win32] - "@octokit/auth-token@4.0.0": - resolution: - { - integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==, - } - engines: { node: ">= 18" } - - "@octokit/core@5.2.2": - resolution: - { - integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==, - } - engines: { node: ">= 18" } - - "@octokit/endpoint@9.0.6": - resolution: - { - integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==, - } - engines: { node: ">= 18" } - - "@octokit/graphql@7.1.1": - resolution: - { - integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==, - } - engines: { node: ">= 18" } - - "@octokit/openapi-types@24.2.0": - resolution: - { - integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==, - } - - "@octokit/plugin-enterprise-rest@6.0.1": - resolution: - { - integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==, - } - - "@octokit/plugin-paginate-rest@11.4.4-cjs.2": - resolution: - { - integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==, - } - engines: { node: ">= 18" } + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + + '@octokit/core@5.2.2': + resolution: {integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@9.0.6': + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.1.1': + resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@24.2.0': + resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} + + '@octokit/plugin-enterprise-rest@6.0.1': + resolution: {integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==} + + '@octokit/plugin-paginate-rest@11.4.4-cjs.2': + resolution: {integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==} + engines: {node: '>= 18'} peerDependencies: - "@octokit/core": "5" - - "@octokit/plugin-request-log@4.0.1": - resolution: - { - integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==, - } - engines: { node: ">= 18" } + '@octokit/core': '5' + + '@octokit/plugin-request-log@4.0.1': + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} peerDependencies: - "@octokit/core": "5" - - "@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1": - resolution: - { - integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==, - } - engines: { node: ">= 18" } + '@octokit/core': '5' + + '@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1': + resolution: {integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==} + engines: {node: '>= 18'} peerDependencies: - "@octokit/core": ^5 - - "@octokit/request-error@5.1.1": - resolution: - { - integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==, - } - engines: { node: ">= 18" } - - "@octokit/request@8.4.1": - resolution: - { - integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==, - } - engines: { node: ">= 18" } - - "@octokit/rest@20.1.2": - resolution: - { - integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==, - } - engines: { node: ">= 18" } - - "@octokit/types@13.10.0": - resolution: - { - integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==, - } - - "@pkgjs/parseargs@0.11.0": - resolution: - { - integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, - } - engines: { node: ">=14" } - - "@pkgr/core@0.2.9": - resolution: - { - integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } - - "@protobufjs/aspromise@1.1.2": - resolution: - { - integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==, - } - - "@protobufjs/base64@1.1.2": - resolution: - { - integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==, - } - - "@protobufjs/codegen@2.0.4": - resolution: - { - integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==, - } - - "@protobufjs/eventemitter@1.1.0": - resolution: - { - integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==, - } - - "@protobufjs/fetch@1.1.0": - resolution: - { - integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==, - } - - "@protobufjs/float@1.0.2": - resolution: - { - integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==, - } - - "@protobufjs/inquire@1.1.0": - resolution: - { - integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==, - } - - "@protobufjs/path@1.1.2": - resolution: - { - integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==, - } - - "@protobufjs/pool@1.1.0": - resolution: - { - integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==, - } - - "@protobufjs/utf8@1.1.0": - resolution: - { - integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==, - } - - "@sigstore/bundle@2.3.2": - resolution: - { - integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@sigstore/core@1.1.0": - resolution: - { - integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@sigstore/protobuf-specs@0.3.3": - resolution: - { - integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==, - } - engines: { node: ^18.17.0 || >=20.5.0 } - - "@sigstore/sign@2.3.2": - resolution: - { - integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@sigstore/tuf@2.3.4": - resolution: - { - integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@sigstore/verify@1.2.1": - resolution: - { - integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@sinclair/typebox@0.27.8": - resolution: - { - integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==, - } - - "@sinclair/typebox@0.34.41": - resolution: - { - integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==, - } - - "@sindresorhus/merge-streams@4.0.0": - resolution: - { - integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==, - } - engines: { node: ">=18" } - - "@sinonjs/commons@3.0.1": - resolution: - { - integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==, - } - - "@sinonjs/fake-timers@13.0.5": - resolution: - { - integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==, - } - - "@tsconfig/node10@1.0.12": - resolution: - { - integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==, - } - - "@tsconfig/node12@1.0.11": - resolution: - { - integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, - } - - "@tsconfig/node14@1.0.3": - resolution: - { - integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, - } - - "@tsconfig/node16@1.0.4": - resolution: - { - integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, - } - - "@tufjs/canonical-json@2.0.0": - resolution: - { - integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@tufjs/models@2.0.1": - resolution: - { - integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - "@tybys/wasm-util@0.10.1": - resolution: - { - integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, - } - - "@tybys/wasm-util@0.9.0": - resolution: - { - integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==, - } - - "@types/babel__core@7.20.5": - resolution: - { - integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==, - } - - "@types/babel__generator@7.27.0": - resolution: - { - integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==, - } - - "@types/babel__template@7.4.4": - resolution: - { - integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==, - } - - "@types/babel__traverse@7.28.0": - resolution: - { - integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==, - } - - "@types/estree@1.0.8": - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } - - "@types/isomorphic-fetch@0.0.39": - resolution: - { - integrity: sha512-I0gou/ZdA1vMG7t7gMzL7VYu2xAKU78rW9U1l10MI0nn77pEHq3tQqHQ8hMmXdMpBlkxZOorjI4sO594Z3kKJw==, - } - - "@types/istanbul-lib-coverage@2.0.6": - resolution: - { - integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==, - } - - "@types/istanbul-lib-report@3.0.3": - resolution: - { - integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==, - } - - "@types/istanbul-reports@3.0.4": - resolution: - { - integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==, - } - - "@types/jest@30.0.0": - resolution: - { - integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==, - } - - "@types/json-schema@7.0.15": - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } - - "@types/minimatch@3.0.5": - resolution: - { - integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==, - } - - "@types/minimist@1.2.5": - resolution: - { - integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==, - } - - "@types/node@22.19.1": - resolution: - { - integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==, - } - - "@types/normalize-package-data@2.4.4": - resolution: - { - integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==, - } - - "@types/semver@7.7.1": - resolution: - { - integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==, - } - - "@types/stack-utils@2.0.3": - resolution: - { - integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==, - } - - "@types/yargs-parser@21.0.3": - resolution: - { - integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==, - } - - "@types/yargs@17.0.35": - resolution: - { - integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==, - } - - "@typescript-eslint/eslint-plugin@8.53.1": - resolution: - { - integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@octokit/core': ^5 + + '@octokit/request-error@5.1.1': + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} + engines: {node: '>= 18'} + + '@octokit/request@8.4.1': + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} + engines: {node: '>= 18'} + + '@octokit/rest@20.1.2': + resolution: {integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==} + engines: {node: '>= 18'} + + '@octokit/types@13.10.0': + resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@sigstore/bundle@2.3.2': + resolution: {integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/core@1.1.0': + resolution: {integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/protobuf-specs@0.3.3': + resolution: {integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + '@sigstore/sign@2.3.2': + resolution: {integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/tuf@2.3.4': + resolution: {integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sigstore/verify@1.2.1': + resolution: {integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinclair/typebox@0.34.41': + resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@13.0.5': + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tufjs/canonical-json@2.0.0': + resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@tufjs/models@2.0.1': + resolution: {integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/isomorphic-fetch@0.0.39': + resolution: {integrity: sha512-I0gou/ZdA1vMG7t7gMzL7VYu2xAKU78rW9U1l10MI0nn77pEHq3tQqHQ8hMmXdMpBlkxZOorjI4sO594Z3kKJw==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/minimatch@3.0.5': + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node@22.19.1': + resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@typescript-eslint/eslint-plugin@8.53.1': + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - "@typescript-eslint/parser": ^8.53.1 + '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/parser@8.53.1": - resolution: - { - integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.53.1': + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/project-service@8.53.1": - resolution: - { - integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.53.1': + resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/scope-manager@8.53.1": - resolution: - { - integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/tsconfig-utils@8.53.1": - resolution: - { - integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.53.1': + resolution: {integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.53.1': + resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/type-utils@8.53.1": - resolution: - { - integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.53.1': + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/types@8.53.1": - resolution: - { - integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/typescript-estree@8.53.1": - resolution: - { - integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.53.1': + resolution: {integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.53.1': + resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/utils@8.53.1": - resolution: - { - integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.53.1': + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/visitor-keys@8.53.1": - resolution: - { - integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@ungap/structured-clone@1.3.0": - resolution: - { - integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==, - } - - "@unrs/resolver-binding-android-arm-eabi@1.11.1": - resolution: - { - integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==, - } + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.53.1': + resolution: {integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} cpu: [arm] os: [android] - "@unrs/resolver-binding-android-arm64@1.11.1": - resolution: - { - integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==, - } + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} cpu: [arm64] os: [android] - "@unrs/resolver-binding-darwin-arm64@1.11.1": - resolution: - { - integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==, - } + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} cpu: [arm64] os: [darwin] - "@unrs/resolver-binding-darwin-x64@1.11.1": - resolution: - { - integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==, - } + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} cpu: [x64] os: [darwin] - "@unrs/resolver-binding-freebsd-x64@1.11.1": - resolution: - { - integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==, - } + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} cpu: [x64] os: [freebsd] - "@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": - resolution: - { - integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==, - } + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} cpu: [arm] os: [linux] - "@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": - resolution: - { - integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==, - } + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} cpu: [arm] os: [linux] - "@unrs/resolver-binding-linux-arm64-gnu@1.11.1": - resolution: - { - integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==, - } + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] - "@unrs/resolver-binding-linux-arm64-musl@1.11.1": - resolution: - { - integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==, - } + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] - "@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": - resolution: - { - integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==, - } + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] - "@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": - resolution: - { - integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==, - } + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] - "@unrs/resolver-binding-linux-riscv64-musl@1.11.1": - resolution: - { - integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==, - } + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] - "@unrs/resolver-binding-linux-s390x-gnu@1.11.1": - resolution: - { - integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==, - } + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] - "@unrs/resolver-binding-linux-x64-gnu@1.11.1": - resolution: - { - integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==, - } + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] - "@unrs/resolver-binding-linux-x64-musl@1.11.1": - resolution: - { - integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==, - } + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] - "@unrs/resolver-binding-wasm32-wasi@1.11.1": - resolution: - { - integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==, - } - engines: { node: ">=14.0.0" } + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} cpu: [wasm32] - "@unrs/resolver-binding-win32-arm64-msvc@1.11.1": - resolution: - { - integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==, - } + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} cpu: [arm64] os: [win32] - "@unrs/resolver-binding-win32-ia32-msvc@1.11.1": - resolution: - { - integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==, - } + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} cpu: [ia32] os: [win32] - "@unrs/resolver-binding-win32-x64-msvc@1.11.1": - resolution: - { - integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==, - } + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} cpu: [x64] os: [win32] - "@yarnpkg/lockfile@1.1.0": - resolution: - { - integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==, - } - - "@yarnpkg/parsers@3.0.2": - resolution: - { - integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==, - } - engines: { node: ">=18.12.0" } - - "@zkochan/js-yaml@0.0.7": - resolution: - { - integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==, - } + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + '@yarnpkg/parsers@3.0.2': + resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} + engines: {node: '>=18.12.0'} + + '@zkochan/js-yaml@0.0.7': + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} hasBin: true JSONStream@1.3.5: - resolution: - { - integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==, - } + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true abbrev@2.0.0: - resolution: - { - integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn-walk@8.3.4: - resolution: - { - integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} acorn@8.15.0: - resolution: - { - integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} hasBin: true add-stream@1.0.0: - resolution: - { - integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==, - } + resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} agent-base@7.1.4: - resolution: - { - integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} aggregate-error@3.1.0: - resolution: - { - integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} ajv@6.12.6: - resolution: - { - integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, - } + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} ansi-colors@4.1.3: - resolution: - { - integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} ansi-escapes@4.3.2: - resolution: - { - integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} ansi-regex@6.2.2: - resolution: - { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} ansi-styles@5.2.0: - resolution: - { - integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} ansi-styles@6.2.3: - resolution: - { - integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} anymatch@3.1.3: - resolution: - { - integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} aproba@2.0.0: - resolution: - { - integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==, - } + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} arg@4.1.3: - resolution: - { - integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, - } + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} argparse@1.0.10: - resolution: - { - integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, - } + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} array-differ@3.0.0: - resolution: - { - integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} array-ify@1.0.0: - resolution: - { - integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==, - } + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} array-union@2.1.0: - resolution: - { - integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} arrify@1.0.1: - resolution: - { - integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} arrify@2.0.1: - resolution: - { - integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} async@3.2.6: - resolution: - { - integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, - } + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: - resolution: - { - integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, - } + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} axios@1.13.2: - resolution: - { - integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==, - } + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} babel-jest@30.2.0: - resolution: - { - integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-0 + '@babel/core': ^7.11.0 || ^8.0.0-0 babel-plugin-istanbul@7.0.1: - resolution: - { - integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} babel-plugin-jest-hoist@30.2.0: - resolution: - { - integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} babel-preset-current-node-syntax@1.2.0: - resolution: - { - integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==, - } + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: - "@babel/core": ^7.0.0 || ^8.0.0-0 + '@babel/core': ^7.0.0 || ^8.0.0-0 babel-preset-jest@30.2.0: - resolution: - { - integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-beta.1 + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} base64-js@1.5.1: - resolution: - { - integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, - } + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} baseline-browser-mapping@2.8.30: - resolution: - { - integrity: sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==, - } + resolution: {integrity: sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==} hasBin: true before-after-hook@2.2.3: - resolution: - { - integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==, - } + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} bin-links@4.0.4: - resolution: - { - integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} bl@4.1.0: - resolution: - { - integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==, - } + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} brace-expansion@1.1.12: - resolution: - { - integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==, - } + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} brace-expansion@2.0.2: - resolution: - { - integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==, - } + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: - resolution: - { - integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} browserslist@4.28.0: - resolution: - { - integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==, - } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true bs-logger@0.2.6: - resolution: - { - integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} bser@2.1.1: - resolution: - { - integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==, - } + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} buffer-from@1.1.2: - resolution: - { - integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, - } + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} buffer@5.7.1: - resolution: - { - integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, - } + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} byte-size@8.1.1: - resolution: - { - integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==, - } - engines: { node: ">=12.17" } + resolution: {integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==} + engines: {node: '>=12.17'} cacache@18.0.4: - resolution: - { - integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} + engines: {node: ^16.14.0 || >=18.0.0} call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} callsites@3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} camelcase-keys@6.2.2: - resolution: - { - integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} camelcase@5.3.1: - resolution: - { - integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} camelcase@6.3.0: - resolution: - { - integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} caniuse-lite@1.0.30001756: - resolution: - { - integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==, - } + resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} chalk@4.1.0: - resolution: - { - integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} + engines: {node: '>=10'} chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} char-regex@1.0.2: - resolution: - { - integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} chardet@2.1.1: - resolution: - { - integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==, - } + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} chownr@2.0.0: - resolution: - { - integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} ci-info@3.9.0: - resolution: - { - integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} ci-info@4.3.1: - resolution: - { - integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} cjs-module-lexer@2.1.1: - resolution: - { - integrity: sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==, - } + resolution: {integrity: sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==} clean-stack@2.2.0: - resolution: - { - integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} cli-cursor@3.1.0: - resolution: - { - integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} cli-spinners@2.6.1: - resolution: - { - integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} cli-spinners@2.9.2: - resolution: - { - integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} cli-width@3.0.0: - resolution: - { - integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==, - } - engines: { node: ">= 10" } + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} cliui@7.0.4: - resolution: - { - integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==, - } + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} cliui@8.0.1: - resolution: - { - integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} clone-deep@4.0.1: - resolution: - { - integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} clone@1.0.4: - resolution: - { - integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, - } - engines: { node: ">=0.8" } + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} cmd-shim@6.0.3: - resolution: - { - integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} co@4.6.0: - resolution: - { - integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==, - } - engines: { iojs: ">= 1.0.0", node: ">= 0.12.0" } + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} collect-v8-coverage@1.0.3: - resolution: - { - integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==, - } + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} color-support@1.1.3: - resolution: - { - integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==, - } + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true columnify@1.6.0: - resolution: - { - integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==, - } - engines: { node: ">=8.0.0" } + resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==} + engines: {node: '>=8.0.0'} combined-stream@1.0.8: - resolution: - { - integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} common-ancestor-path@1.0.1: - resolution: - { - integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==, - } + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} compare-func@2.0.0: - resolution: - { - integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==, - } + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} concat-map@0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, - } + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} concat-stream@2.0.0: - resolution: - { - integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==, - } - engines: { "0": node >= 6.0 } + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} console-control-strings@1.1.0: - resolution: - { - integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, - } + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} conventional-changelog-angular@7.0.0: - resolution: - { - integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} conventional-changelog-core@5.0.1: - resolution: - { - integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} + engines: {node: '>=14'} conventional-changelog-preset-loader@3.0.0: - resolution: - { - integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} + engines: {node: '>=14'} conventional-changelog-writer@6.0.1: - resolution: - { - integrity: sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==} + engines: {node: '>=14'} hasBin: true conventional-commits-filter@3.0.0: - resolution: - { - integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==} + engines: {node: '>=14'} conventional-commits-parser@4.0.0: - resolution: - { - integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==} + engines: {node: '>=14'} hasBin: true conventional-recommended-bump@7.0.1: - resolution: - { - integrity: sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==} + engines: {node: '>=14'} hasBin: true convert-source-map@2.0.0: - resolution: - { - integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, - } + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} copy-file@11.1.0: - resolution: - { - integrity: sha512-X8XDzyvYaA6msMyAM575CUoygY5b44QzLcGRKsK3MFmXcOvQa518dNPLsKYwkYsn72g3EiW+LE0ytd/FlqWmyw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-X8XDzyvYaA6msMyAM575CUoygY5b44QzLcGRKsK3MFmXcOvQa518dNPLsKYwkYsn72g3EiW+LE0ytd/FlqWmyw==} + engines: {node: '>=18'} copyfiles@2.4.1: - resolution: - { - integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==, - } + resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} hasBin: true core-util-is@1.0.3: - resolution: - { - integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, - } + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} cosmiconfig@9.0.0: - resolution: - { - integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} peerDependencies: - typescript: ">=4.9.5" + typescript: '>=4.9.5' peerDependenciesMeta: typescript: optional: true cpy-cli@6.0.0: - resolution: - { - integrity: sha512-q7GUqTDnRymCbScJ4Ph1IUM86wWdKG8JbgrvKLgvvehH4wrbRcVN+jRwOTlxJdwm7ykdXMKSp6IESksFeHa0eA==, - } - engines: { node: ">=20" } + resolution: {integrity: sha512-q7GUqTDnRymCbScJ4Ph1IUM86wWdKG8JbgrvKLgvvehH4wrbRcVN+jRwOTlxJdwm7ykdXMKSp6IESksFeHa0eA==} + engines: {node: '>=20'} hasBin: true cpy@12.1.0: - resolution: - { - integrity: sha512-3z9tP1rPBLG7pQYn9iRgl7JOSew0SMPuWmakaRfzhXpmFBHmRbp7JekpuqPkXbbWOdSeKSbInYEcdIZjov2fNQ==, - } - engines: { node: ">=20" } + resolution: {integrity: sha512-3z9tP1rPBLG7pQYn9iRgl7JOSew0SMPuWmakaRfzhXpmFBHmRbp7JekpuqPkXbbWOdSeKSbInYEcdIZjov2fNQ==} + engines: {node: '>=20'} create-require@1.1.1: - resolution: - { - integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, - } + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} cssesc@3.0.0: - resolution: - { - integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} hasBin: true dargs@7.0.0: - resolution: - { - integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} dateformat@3.0.3: - resolution: - { - integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==, - } + resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} peerDependencies: - supports-color: "*" + supports-color: '*' peerDependenciesMeta: supports-color: optional: true decamelize-keys@1.1.1: - resolution: - { - integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} decamelize@1.2.0: - resolution: - { - integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} dedent@1.5.3: - resolution: - { - integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==, - } + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -2748,10 +1800,7 @@ packages: optional: true dedent@1.7.0: - resolution: - { - integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==, - } + resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -2759,459 +1808,267 @@ packages: optional: true deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} deepmerge@4.3.1: - resolution: - { - integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} defaults@1.0.4: - resolution: - { - integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, - } + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} define-lazy-prop@2.0.0: - resolution: - { - integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} delayed-stream@1.0.0: - resolution: - { - integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} deprecation@2.3.1: - resolution: - { - integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==, - } + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} detect-indent@5.0.0: - resolution: - { - integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==} + engines: {node: '>=4'} detect-newline@3.1.0: - resolution: - { - integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} diff-sequences@29.6.3: - resolution: - { - integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} diff@4.0.2: - resolution: - { - integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==, - } - engines: { node: ">=0.3.1" } + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} dot-prop@5.3.0: - resolution: - { - integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} dotenv-expand@11.0.7: - resolution: - { - integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} dotenv@16.4.7: - resolution: - { - integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} eastasianwidth@0.2.0: - resolution: - { - integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, - } + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} ejs@3.1.10: - resolution: - { - integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} hasBin: true electron-to-chromium@1.5.259: - resolution: - { - integrity: sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==, - } + resolution: {integrity: sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==} emittery@0.13.1: - resolution: - { - integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: - resolution: - { - integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, - } + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} encoding@0.1.13: - resolution: - { - integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==, - } + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} end-of-stream@1.4.5: - resolution: - { - integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==, - } + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} enquirer@2.3.6: - resolution: - { - integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==, - } - engines: { node: ">=8.6" } + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} env-paths@2.2.1: - resolution: - { - integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} envinfo@7.13.0: - resolution: - { - integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} + engines: {node: '>=4'} hasBin: true err-code@2.0.3: - resolution: - { - integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==, - } + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} error-ex@1.3.4: - resolution: - { - integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, - } + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} es-set-tostringtag@2.1.0: - resolution: - { - integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} escape-string-regexp@1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: ">=0.8.0" } + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} escape-string-regexp@2.0.0: - resolution: - { - integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: - eslint: ">=7.0.0" + eslint: '>=7.0.0' eslint-plugin-prettier@5.5.5: - resolution: - { - integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - "@types/eslint": ">=8.0.0" - eslint: ">=8.0.0" - eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" - prettier: ">=3.0.0" + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' peerDependenciesMeta: - "@types/eslint": + '@types/eslint': optional: true eslint-config-prettier: optional: true eslint-plugin-simple-import-sort@12.1.1: - resolution: - { - integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==, - } + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} peerDependencies: - eslint: ">=5.0.0" + eslint: '>=5.0.0' eslint-plugin-unused-imports@4.3.0: - resolution: - { - integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==, - } + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} peerDependencies: - "@typescript-eslint/eslint-plugin": ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 eslint: ^9.0.0 || ^8.0.0 peerDependenciesMeta: - "@typescript-eslint/eslint-plugin": + '@typescript-eslint/eslint-plugin': optional: true eslint-scope@8.4.0: - resolution: - { - integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@4.2.1: - resolution: - { - integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint@9.39.2: - resolution: - { - integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: - jiti: "*" + jiti: '*' peerDependenciesMeta: jiti: optional: true espree@10.4.0: - resolution: - { - integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: - resolution: - { - integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} hasBin: true esquery@1.7.0: - resolution: - { - integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, - } - engines: { node: ">=0.10" } + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} eventemitter3@4.0.7: - resolution: - { - integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, - } + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} execa@5.0.0: - resolution: - { - integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==} + engines: {node: '>=10'} execa@5.1.1: - resolution: - { - integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} exit-x@0.2.2: - resolution: - { - integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} expect@30.2.0: - resolution: - { - integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} exponential-backoff@3.1.3: - resolution: - { - integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==, - } + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} fast-diff@1.3.0: - resolution: - { - integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==, - } + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} fast-glob@3.3.3: - resolution: - { - integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, - } - engines: { node: ">=8.6.0" } + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} fast-json-patch@3.1.1: - resolution: - { - integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==, - } + resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==} fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fastq@1.19.1: - resolution: - { - integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==, - } + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} fb-watchman@2.0.2: - resolution: - { - integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==, - } + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -3219,825 +2076,471 @@ packages: optional: true figures@3.2.0: - resolution: - { - integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} file-entry-cache@8.0.0: - resolution: - { - integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, - } - engines: { node: ">=16.0.0" } + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} filelist@1.0.4: - resolution: - { - integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==, - } + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} fill-range@7.1.1: - resolution: - { - integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} find-up@2.1.0: - resolution: - { - integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} find-up@4.1.0: - resolution: - { - integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} find-up@5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} flat-cache@4.0.1: - resolution: - { - integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flat@5.0.2: - resolution: - { - integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==, - } + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true flatted@3.3.3: - resolution: - { - integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==, - } + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} follow-redirects@1.15.11: - resolution: - { - integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} peerDependencies: - debug: "*" + debug: '*' peerDependenciesMeta: debug: optional: true foreground-child@3.3.1: - resolution: - { - integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} form-data@4.0.5: - resolution: - { - integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} front-matter@4.0.2: - resolution: - { - integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==, - } + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} fs-constants@1.0.0: - resolution: - { - integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==, - } + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} fs-extra@11.3.2: - resolution: - { - integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==, - } - engines: { node: ">=14.14" } + resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} + engines: {node: '>=14.14'} fs-minipass@2.1.0: - resolution: - { - integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} fs-minipass@3.0.3: - resolution: - { - integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} fs.realpath@1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, - } + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} gensync@1.0.0-beta.2: - resolution: - { - integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, - } - engines: { node: ">=6.9.0" } + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} get-caller-file@2.0.5: - resolution: - { - integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, - } - engines: { node: 6.* || 8.* || >= 10.* } + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} get-package-type@0.1.0: - resolution: - { - integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==, - } - engines: { node: ">=8.0.0" } + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} get-pkg-repo@4.2.1: - resolution: - { - integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==, - } - engines: { node: ">=6.9.0" } + resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} + engines: {node: '>=6.9.0'} hasBin: true get-port@5.1.1: - resolution: - { - integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} get-stream@6.0.0: - resolution: - { - integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==} + engines: {node: '>=10'} get-stream@6.0.1: - resolution: - { - integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} git-raw-commits@3.0.0: - resolution: - { - integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} + engines: {node: '>=14'} deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. hasBin: true git-remote-origin-url@2.0.0: - resolution: - { - integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==} + engines: {node: '>=4'} git-semver-tags@5.0.1: - resolution: - { - integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} + engines: {node: '>=14'} deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. hasBin: true git-up@7.0.0: - resolution: - { - integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==, - } + resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} git-url-parse@14.0.0: - resolution: - { - integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==, - } + resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==} gitconfiglocal@1.0.0: - resolution: - { - integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==, - } + resolution: {integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==} glob-parent@5.1.2: - resolution: - { - integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} glob@10.5.0: - resolution: - { - integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==, - } + resolution: {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 hasBin: true glob@11.1.0: - resolution: - { - integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} 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 hasBin: true glob@13.0.0: - resolution: - { - integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} glob@7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, - } + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 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 glob@9.3.5: - resolution: - { - integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} 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 globals@14.0.0: - resolution: - { - integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} globby@15.0.0: - resolution: - { - integrity: sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==, - } - engines: { node: ">=20" } + resolution: {integrity: sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==} + engines: {node: '>=20'} gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: - resolution: - { - integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, - } + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} handlebars@4.7.8: - resolution: - { - integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==, - } - engines: { node: ">=0.4.7" } + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} hasBin: true hard-rejection@2.1.0: - resolution: - { - integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} has-tostringtag@1.0.2: - resolution: - { - integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} has-unicode@2.0.1: - resolution: - { - integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==, - } + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} hasown@2.0.2: - resolution: - { - integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} hosted-git-info@2.8.9: - resolution: - { - integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==, - } + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} hosted-git-info@4.1.0: - resolution: - { - integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} hosted-git-info@7.0.2: - resolution: - { - integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} html-escaper@2.0.2: - resolution: - { - integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, - } + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} http-cache-semantics@4.2.0: - resolution: - { - integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, - } + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} http-proxy-agent@7.0.2: - resolution: - { - integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} https-proxy-agent@7.0.6: - resolution: - { - integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} human-signals@2.1.0: - resolution: - { - integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, - } - engines: { node: ">=10.17.0" } + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} iconv-lite@0.6.3: - resolution: - { - integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} iconv-lite@0.7.0: - resolution: - { - integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + engines: {node: '>=0.10.0'} ieee754@1.2.1: - resolution: - { - integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, - } + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} ignore-walk@6.0.5: - resolution: - { - integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} ignore@5.3.2: - resolution: - { - integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} ignore@7.0.5: - resolution: - { - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} import-fresh@3.3.1: - resolution: - { - integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} import-local@3.1.0: - resolution: - { - integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} hasBin: true import-local@3.2.0: - resolution: - { - integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} hasBin: true imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} indent-string@4.0.0: - resolution: - { - integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} inflection@3.0.2: - resolution: - { - integrity: sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==, - } - engines: { node: ">=18.0.0" } + resolution: {integrity: sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==} + engines: {node: '>=18.0.0'} inflight@1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} ini@1.3.8: - resolution: - { - integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==, - } + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} ini@4.1.3: - resolution: - { - integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} init-package-json@6.0.3: - resolution: - { - integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==} + engines: {node: ^16.14.0 || >=18.0.0} inquirer@8.2.7: - resolution: - { - integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==} + engines: {node: '>=12.0.0'} ip-address@10.1.0: - resolution: - { - integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==, - } - engines: { node: ">= 12" } + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} is-arrayish@0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-ci@3.0.1: - resolution: - { - integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==, - } + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true is-core-module@2.16.1: - resolution: - { - integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} is-docker@2.2.1: - resolution: - { - integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} hasBin: true is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} is-generator-fn@2.1.0: - resolution: - { - integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-interactive@1.0.0: - resolution: - { - integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} is-lambda@1.0.1: - resolution: - { - integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==, - } + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} is-number@7.0.0: - resolution: - { - integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, - } - engines: { node: ">=0.12.0" } + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} is-obj@2.0.0: - resolution: - { - integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} is-plain-obj@1.1.0: - resolution: - { - integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} is-plain-object@2.0.4: - resolution: - { - integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} is-ssh@1.4.1: - resolution: - { - integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==, - } + resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} is-stream@2.0.0: - resolution: - { - integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==} + engines: {node: '>=8'} is-stream@2.0.1: - resolution: - { - integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} is-text-path@1.0.1: - resolution: - { - integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} is-unicode-supported@0.1.0: - resolution: - { - integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} is-wsl@2.2.0: - resolution: - { - integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} isarray@0.0.1: - resolution: - { - integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==, - } + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} isarray@1.0.0: - resolution: - { - integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, - } + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} isexe@3.1.1: - resolution: - { - integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} isobject@3.0.1: - resolution: - { - integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} isomorphic-fetch@3.0.0: - resolution: - { - integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==, - } + resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} istanbul-lib-coverage@3.2.2: - resolution: - { - integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} istanbul-lib-instrument@6.0.3: - resolution: - { - integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} istanbul-lib-report@3.0.1: - resolution: - { - integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} istanbul-lib-source-maps@5.0.6: - resolution: - { - integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} istanbul-reports@3.2.0: - resolution: - { - integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} jackspeak@3.4.3: - resolution: - { - integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, - } + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} jackspeak@4.1.1: - resolution: - { - integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} jake@10.9.4: - resolution: - { - integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} hasBin: true jest-changed-files@30.2.0: - resolution: - { - integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-circus@30.2.0: - resolution: - { - integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-cli@30.2.0: - resolution: - { - integrity: sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -4046,17 +2549,14 @@ packages: optional: true jest-config@30.2.0: - resolution: - { - integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: - "@types/node": "*" - esbuild-register: ">=3.4.0" - ts-node: ">=9.0.0" + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' peerDependenciesMeta: - "@types/node": + '@types/node': optional: true esbuild-register: optional: true @@ -4064,170 +2564,101 @@ packages: optional: true jest-diff@29.7.0: - resolution: - { - integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jest-diff@30.2.0: - resolution: - { - integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-docblock@30.2.0: - resolution: - { - integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-each@30.2.0: - resolution: - { - integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-environment-node@30.2.0: - resolution: - { - integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-get-type@29.6.3: - resolution: - { - integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jest-haste-map@30.2.0: - resolution: - { - integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-leak-detector@30.2.0: - resolution: - { - integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-matcher-utils@30.2.0: - resolution: - { - integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-message-util@30.2.0: - resolution: - { - integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-mock@30.2.0: - resolution: - { - integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-pnp-resolver@1.2.3: - resolution: - { - integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} peerDependencies: - jest-resolve: "*" + jest-resolve: '*' peerDependenciesMeta: jest-resolve: optional: true jest-regex-util@30.0.1: - resolution: - { - integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-resolve-dependencies@30.2.0: - resolution: - { - integrity: sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-resolve@30.2.0: - resolution: - { - integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-runner@30.2.0: - resolution: - { - integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-runtime@30.2.0: - resolution: - { - integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-snapshot@30.2.0: - resolution: - { - integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-util@30.2.0: - resolution: - { - integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-validate@30.2.0: - resolution: - { - integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-watcher@30.2.0: - resolution: - { - integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-worker@30.2.0: - resolution: - { - integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest@30.2.0: - resolution: - { - integrity: sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -4236,628 +2667,349 @@ packages: optional: true js-tokens@4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} js-yaml@3.14.2: - resolution: - { - integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==, - } + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true js-yaml@4.1.0: - resolution: - { - integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, - } + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsesc@3.1.0: - resolution: - { - integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} hasBin: true json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, - } + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-better-errors@1.0.2: - resolution: - { - integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==, - } + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} json-parse-even-better-errors@2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} json-parse-even-better-errors@3.0.2: - resolution: - { - integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} json-stringify-nice@1.1.4: - resolution: - { - integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==, - } + resolution: {integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==} json-stringify-safe@5.0.1: - resolution: - { - integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, - } + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} json5@2.2.3: - resolution: - { - integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} hasBin: true jsonc-parser@3.2.0: - resolution: - { - integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==, - } + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} jsonfile@6.2.0: - resolution: - { - integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==, - } + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} jsonparse@1.3.1: - resolution: - { - integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==, - } - engines: { "0": node >= 0.2.0 } + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} junk@4.0.1: - resolution: - { - integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==, - } - engines: { node: ">=12.20" } + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} just-diff-apply@5.5.0: - resolution: - { - integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==, - } + resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} just-diff@6.0.2: - resolution: - { - integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==, - } + resolution: {integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==} keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} kind-of@6.0.3: - resolution: - { - integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} kubernetesjs@0.7.6: - resolution: - { - integrity: sha512-swqDZZ7AJQSUgDI6FcIE1o6w1+5046wv4WfHkuz6E80bUY5SFVuKchQN6ivLJAPLdRlMnpTGc0WKB+MJo9LVOQ==, - } + resolution: {integrity: sha512-swqDZZ7AJQSUgDI6FcIE1o6w1+5046wv4WfHkuz6E80bUY5SFVuKchQN6ivLJAPLdRlMnpTGc0WKB+MJo9LVOQ==} lerna@8.2.4: - resolution: - { - integrity: sha512-0gaVWDIVT7fLfprfwpYcQajb7dBJv3EGavjG7zvJ+TmGx3/wovl5GklnSwM2/WeE0Z2wrIz7ndWhBcDUHVjOcQ==, - } - engines: { node: ">=18.0.0" } + resolution: {integrity: sha512-0gaVWDIVT7fLfprfwpYcQajb7dBJv3EGavjG7zvJ+TmGx3/wovl5GklnSwM2/WeE0Z2wrIz7ndWhBcDUHVjOcQ==} + engines: {node: '>=18.0.0'} hasBin: true leven@3.1.0: - resolution: - { - integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} libnpmaccess@8.0.6: - resolution: - { - integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==} + engines: {node: ^16.14.0 || >=18.0.0} libnpmpublish@9.0.9: - resolution: - { - integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==} + engines: {node: ^16.14.0 || >=18.0.0} lines-and-columns@1.2.4: - resolution: - { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, - } + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} lines-and-columns@2.0.3: - resolution: - { - integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} load-json-file@4.0.0: - resolution: - { - integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} load-json-file@6.2.0: - resolution: - { - integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==} + engines: {node: '>=8'} locate-path@2.0.0: - resolution: - { - integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} locate-path@5.0.0: - resolution: - { - integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} locate-path@6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} lodash.ismatch@4.4.0: - resolution: - { - integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==, - } + resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} lodash.memoize@4.1.2: - resolution: - { - integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==, - } + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} lodash.merge@4.6.2: - resolution: - { - integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, - } + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} lodash@4.17.21: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} log-symbols@4.1.0: - resolution: - { - integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} long@5.3.2: - resolution: - { - integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==, - } + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} lru-cache@10.4.3: - resolution: - { - integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, - } + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@11.2.2: - resolution: - { - integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} lru-cache@5.1.1: - resolution: - { - integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, - } + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} lru-cache@6.0.0: - resolution: - { - integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} makage@0.1.10: - resolution: - { - integrity: sha512-IQKuRbHOrDgVNlydle+XRO5iMyaozBq4Bb9vhEzwxtvzyk08JkQo5qpfFRep0dSum53gECdX2gBoTmkWDHIfJA==, - } + resolution: {integrity: sha512-IQKuRbHOrDgVNlydle+XRO5iMyaozBq4Bb9vhEzwxtvzyk08JkQo5qpfFRep0dSum53gECdX2gBoTmkWDHIfJA==} hasBin: true make-dir@2.1.0: - resolution: - { - integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} make-dir@4.0.0: - resolution: - { - integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} make-error@1.3.6: - resolution: - { - integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, - } + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} make-fetch-happen@13.0.1: - resolution: - { - integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} + engines: {node: ^16.14.0 || >=18.0.0} makeerror@1.0.12: - resolution: - { - integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==, - } + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} map-obj@1.0.1: - resolution: - { - integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} map-obj@4.3.0: - resolution: - { - integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} meow@13.2.0: - resolution: - { - integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} meow@8.1.2: - resolution: - { - integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} merge-stream@2.0.0: - resolution: - { - integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, - } + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} merge2@1.4.1: - resolution: - { - integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} micromatch@4.0.8: - resolution: - { - integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, - } - engines: { node: ">=8.6" } + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} mime-db@1.52.0: - resolution: - { - integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} mime-types@2.1.35: - resolution: - { - integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} mimic-fn@2.1.0: - resolution: - { - integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} min-indent@1.0.1: - resolution: - { - integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} minimatch@10.1.1: - resolution: - { - integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} minimatch@3.0.5: - resolution: - { - integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==, - } + resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} minimatch@3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, - } + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} minimatch@5.1.6: - resolution: - { - integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} minimatch@8.0.4: - resolution: - { - integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} minimatch@9.0.3: - resolution: - { - integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} minimatch@9.0.5: - resolution: - { - integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} minimist-options@4.1.0: - resolution: - { - integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} minimist@1.2.8: - resolution: - { - integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, - } + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} minipass-collect@2.0.1: - resolution: - { - integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} minipass-fetch@3.0.5: - resolution: - { - integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} minipass-flush@1.0.5: - resolution: - { - integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} minipass-pipeline@1.2.4: - resolution: - { - integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} minipass-sized@1.0.3: - resolution: - { - integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} minipass@3.3.6: - resolution: - { - integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} minipass@4.2.8: - resolution: - { - integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} minipass@5.0.0: - resolution: - { - integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} minipass@7.1.2: - resolution: - { - integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} minizlib@2.1.2: - resolution: - { - integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} mkdirp@1.0.4: - resolution: - { - integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} hasBin: true modify-values@1.0.1: - resolution: - { - integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} + engines: {node: '>=0.10.0'} ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} multimatch@5.0.0: - resolution: - { - integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} + engines: {node: '>=10'} mute-stream@0.0.8: - resolution: - { - integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==, - } + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} mute-stream@1.0.0: - resolution: - { - integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} napi-postinstall@0.3.4: - resolution: - { - integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} negotiator@0.6.4: - resolution: - { - integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} neo-async@2.6.2: - resolution: - { - integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, - } + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} node-fetch@2.6.7: - resolution: - { - integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==, - } - engines: { node: 4.x || >=6.0.0 } + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -4865,1282 +3017,733 @@ packages: optional: true node-gyp@10.3.1: - resolution: - { - integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true node-int64@0.4.0: - resolution: - { - integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==, - } + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-machine-id@1.1.12: - resolution: - { - integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==, - } + resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} node-releases@2.0.27: - resolution: - { - integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==, - } + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} noms@0.0.0: - resolution: - { - integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==, - } + resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} nopt@7.2.1: - resolution: - { - integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true normalize-package-data@2.5.0: - resolution: - { - integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==, - } + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} normalize-package-data@3.0.3: - resolution: - { - integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} normalize-package-data@6.0.2: - resolution: - { - integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} normalize-path@3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} npm-bundled@3.0.1: - resolution: - { - integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-install-checks@6.3.0: - resolution: - { - integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-normalize-package-bin@3.0.1: - resolution: - { - integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-package-arg@11.0.2: - resolution: - { - integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==} + engines: {node: ^16.14.0 || >=18.0.0} npm-packlist@8.0.2: - resolution: - { - integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-pick-manifest@9.1.0: - resolution: - { - integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==} + engines: {node: ^16.14.0 || >=18.0.0} npm-registry-fetch@17.1.0: - resolution: - { - integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==} + engines: {node: ^16.14.0 || >=18.0.0} npm-run-path@4.0.1: - resolution: - { - integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} nx@20.8.3: - resolution: - { - integrity: sha512-8w815WSMWar3A/LFzwtmEY+E8cVW62lMiFuPDXje+C8O8hFndfvscP56QHNMn2Zdhz3q0+BZUe+se4Em1BKYdA==, - } + resolution: {integrity: sha512-8w815WSMWar3A/LFzwtmEY+E8cVW62lMiFuPDXje+C8O8hFndfvscP56QHNMn2Zdhz3q0+BZUe+se4Em1BKYdA==} hasBin: true peerDependencies: - "@swc-node/register": ^1.8.0 - "@swc/core": ^1.3.85 + '@swc-node/register': ^1.8.0 + '@swc/core': ^1.3.85 peerDependenciesMeta: - "@swc-node/register": + '@swc-node/register': optional: true - "@swc/core": + '@swc/core': optional: true once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@5.1.2: - resolution: - { - integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} open@8.4.2: - resolution: - { - integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} optionator@0.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} ora@5.3.0: - resolution: - { - integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} ora@5.4.1: - resolution: - { - integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} p-event@6.0.1: - resolution: - { - integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==, - } - engines: { node: ">=16.17" } + resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==} + engines: {node: '>=16.17'} p-filter@4.1.0: - resolution: - { - integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} + engines: {node: '>=18'} p-finally@1.0.0: - resolution: - { - integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} p-limit@1.3.0: - resolution: - { - integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} p-limit@2.3.0: - resolution: - { - integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} p-locate@2.0.0: - resolution: - { - integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} p-locate@4.1.0: - resolution: - { - integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} p-map-series@2.1.0: - resolution: - { - integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==} + engines: {node: '>=8'} p-map@4.0.0: - resolution: - { - integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} p-map@7.0.4: - resolution: - { - integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} + engines: {node: '>=18'} p-pipe@3.1.0: - resolution: - { - integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} + engines: {node: '>=8'} p-queue@6.6.2: - resolution: - { - integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} p-reduce@2.1.0: - resolution: - { - integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} p-timeout@3.2.0: - resolution: - { - integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} p-timeout@6.1.4: - resolution: - { - integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==, - } - engines: { node: ">=14.16" } + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} p-try@1.0.0: - resolution: - { - integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} p-try@2.2.0: - resolution: - { - integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} p-waterfall@2.1.1: - resolution: - { - integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==} + engines: {node: '>=8'} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} pacote@18.0.6: - resolution: - { - integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true parent-module@1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} parse-conflict-json@3.0.1: - resolution: - { - integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} parse-json@4.0.0: - resolution: - { - integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} parse-json@5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} parse-path@7.1.0: - resolution: - { - integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==, - } + resolution: {integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==} parse-url@8.1.0: - resolution: - { - integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==, - } + resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} path-exists@3.0.0: - resolution: - { - integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} path-exists@4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} path-is-absolute@1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} path-parse@1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, - } + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} path-scurry@1.11.1: - resolution: - { - integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, - } - engines: { node: ">=16 || 14 >=14.18" } + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-scurry@2.0.1: - resolution: - { - integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} path-type@3.0.0: - resolution: - { - integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} path-type@6.0.0: - resolution: - { - integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: - resolution: - { - integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, - } - engines: { node: ">=8.6" } + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} picomatch@4.0.3: - resolution: - { - integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} pify@2.3.0: - resolution: - { - integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} pify@3.0.0: - resolution: - { - integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} pify@4.0.1: - resolution: - { - integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} pify@5.0.0: - resolution: - { - integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} pirates@4.0.7: - resolution: - { - integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} pkg-dir@4.2.0: - resolution: - { - integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} postcss-selector-parser@6.1.2: - resolution: - { - integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} prettier-linter-helpers@1.0.1: - resolution: - { - integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==, - } - engines: { node: ">=6.0.0" } + resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} + engines: {node: '>=6.0.0'} prettier@3.8.0: - resolution: - { - integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==} + engines: {node: '>=14'} hasBin: true pretty-format@29.7.0: - resolution: - { - integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} pretty-format@30.2.0: - resolution: - { - integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} proc-log@4.2.0: - resolution: - { - integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} process-nextick-args@2.0.1: - resolution: - { - integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, - } + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} proggy@2.0.0: - resolution: - { - integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} promise-all-reject-late@1.0.1: - resolution: - { - integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==, - } + resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} promise-call-limit@3.0.2: - resolution: - { - integrity: sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==, - } + resolution: {integrity: sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==} promise-inflight@1.0.1: - resolution: - { - integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==, - } + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: - bluebird: "*" + bluebird: '*' peerDependenciesMeta: bluebird: optional: true promise-retry@2.0.1: - resolution: - { - integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} promzard@1.0.2: - resolution: - { - integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} protocols@2.0.2: - resolution: - { - integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==, - } + resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} proxy-from-env@1.1.0: - resolution: - { - integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, - } + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} pure-rand@7.0.1: - resolution: - { - integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==, - } + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} queue-microtask@1.2.3: - resolution: - { - integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, - } + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} quick-lru@4.0.1: - resolution: - { - integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} react-is@18.3.1: - resolution: - { - integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==, - } + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} read-cmd-shim@4.0.0: - resolution: - { - integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-package-json-fast@3.0.2: - resolution: - { - integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-pkg-up@3.0.0: - resolution: - { - integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} + engines: {node: '>=4'} read-pkg-up@7.0.1: - resolution: - { - integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} read-pkg@3.0.0: - resolution: - { - integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} read-pkg@5.2.0: - resolution: - { - integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} read@3.0.1: - resolution: - { - integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} readable-stream@1.0.34: - resolution: - { - integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==, - } + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} readable-stream@2.3.8: - resolution: - { - integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, - } + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} readable-stream@3.6.2: - resolution: - { - integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} redent@3.0.0: - resolution: - { - integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} require-directory@2.1.1: - resolution: - { - integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} resolve-cwd@3.0.0: - resolution: - { - integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} resolve-from@4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} resolve-from@5.0.0: - resolution: - { - integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} resolve.exports@2.0.3: - resolution: - { - integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} resolve@1.22.11: - resolution: - { - integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} hasBin: true restore-cursor@3.1.0: - resolution: - { - integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} retry@0.12.0: - resolution: - { - integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} reusify@1.1.0: - resolution: - { - integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, - } - engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rimraf@4.4.1: - resolution: - { - integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} hasBin: true rimraf@6.1.2: - resolution: - { - integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + engines: {node: 20 || >=22} hasBin: true run-async@2.4.1: - resolution: - { - integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==, - } - engines: { node: ">=0.12.0" } + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} run-parallel@1.2.0: - resolution: - { - integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, - } + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} rxjs@7.8.2: - resolution: - { - integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, - } + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-buffer@5.1.2: - resolution: - { - integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, - } + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: - resolution: - { - integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, - } + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} semver@5.7.2: - resolution: - { - integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==, - } + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true semver@6.3.1: - resolution: - { - integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, - } + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true semver@7.7.3: - resolution: - { - integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} hasBin: true semver@7.7.4: - resolution: - { - integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} hasBin: true set-blocking@2.0.0: - resolution: - { - integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, - } + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} shallow-clone@3.0.1: - resolution: - { - integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} signal-exit@3.0.7: - resolution: - { - integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, - } + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} signal-exit@4.1.0: - resolution: - { - integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} sigstore@2.3.1: - resolution: - { - integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==} + engines: {node: ^16.14.0 || >=18.0.0} slash@3.0.0: - resolution: - { - integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} slash@5.1.0: - resolution: - { - integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==, - } - engines: { node: ">=14.16" } + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} smart-buffer@4.2.0: - resolution: - { - integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, - } - engines: { node: ">= 6.0.0", npm: ">= 3.0.0" } + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} socks-proxy-agent@8.0.5: - resolution: - { - integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} socks@2.8.7: - resolution: - { - integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==, - } - engines: { node: ">= 10.0.0", npm: ">= 3.0.0" } + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} sort-keys@2.0.0: - resolution: - { - integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} + engines: {node: '>=4'} source-map-support@0.5.13: - resolution: - { - integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==, - } + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} spdx-correct@3.2.0: - resolution: - { - integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==, - } + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} spdx-exceptions@2.5.0: - resolution: - { - integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==, - } + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} spdx-expression-parse@3.0.1: - resolution: - { - integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==, - } + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} spdx-license-ids@3.0.22: - resolution: - { - integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==, - } + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} split2@3.2.2: - resolution: - { - integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==, - } + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} split@1.0.1: - resolution: - { - integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==, - } + resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} sprintf-js@1.0.3: - resolution: - { - integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, - } + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} ssri@10.0.6: - resolution: - { - integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} stack-utils@2.0.6: - resolution: - { - integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} string-length@4.0.2: - resolution: - { - integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} string-width@5.1.2: - resolution: - { - integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} string_decoder@0.10.31: - resolution: - { - integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==, - } + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} string_decoder@1.1.1: - resolution: - { - integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, - } + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} string_decoder@1.3.0: - resolution: - { - integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, - } + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} strip-ansi@7.1.2: - resolution: - { - integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} strip-bom@3.0.0: - resolution: - { - integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} strip-bom@4.0.0: - resolution: - { - integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} strip-final-newline@2.0.0: - resolution: - { - integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} strip-indent@3.0.0: - resolution: - { - integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} strip-json-comments@3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} supports-color@8.1.1: - resolution: - { - integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} supports-preserve-symlinks-flag@1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} synckit@0.11.11: - resolution: - { - integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + engines: {node: ^14.18.0 || >=16.0.0} synckit@0.11.12: - resolution: - { - integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + engines: {node: ^14.18.0 || >=16.0.0} tar-stream@2.2.0: - resolution: - { - integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} tar@6.2.1: - resolution: - { - integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} deprecated: Old versions of tar 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 temp-dir@1.0.0: - resolution: - { - integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} + engines: {node: '>=4'} test-exclude@6.0.0: - resolution: - { - integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} text-extensions@1.9.0: - resolution: - { - integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==, - } - engines: { node: ">=0.10" } + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} through2@2.0.5: - resolution: - { - integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, - } + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} through@2.3.8: - resolution: - { - integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, - } + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} tinyglobby@0.2.12: - resolution: - { - integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} tinyglobby@0.2.15: - resolution: - { - integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} tmp@0.2.5: - resolution: - { - integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==, - } - engines: { node: ">=14.14" } + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} tmpl@1.0.5: - resolution: - { - integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==, - } + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} to-regex-range@5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: ">=8.0" } + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} treeverse@3.0.0: - resolution: - { - integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} trim-newlines@3.0.1: - resolution: - { - integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} ts-api-utils@2.4.0: - resolution: - { - integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==, - } - engines: { node: ">=18.12" } + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} peerDependencies: - typescript: ">=4.8.4" + typescript: '>=4.8.4' ts-jest@29.4.6: - resolution: - { - integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==, - } - engines: { node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0 } + resolution: {integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - "@babel/core": ">=7.0.0-beta.0 <8" - "@jest/transform": ^29.0.0 || ^30.0.0 - "@jest/types": ^29.0.0 || ^30.0.0 + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 || ^30.0.0 + '@jest/types': ^29.0.0 || ^30.0.0 babel-jest: ^29.0.0 || ^30.0.0 - esbuild: "*" + esbuild: '*' jest: ^29.0.0 || ^30.0.0 jest-util: ^29.0.0 || ^30.0.0 - typescript: ">=4.3 <6" + typescript: '>=4.3 <6' peerDependenciesMeta: - "@babel/core": + '@babel/core': optional: true - "@jest/transform": + '@jest/transform': optional: true - "@jest/types": + '@jest/types': optional: true babel-jest: optional: true @@ -6150,470 +3753,282 @@ packages: optional: true ts-node@10.9.2: - resolution: - { - integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, - } + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: - "@swc/core": ">=1.2.50" - "@swc/wasm": ">=1.2.50" - "@types/node": "*" - typescript: ">=2.7" + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' peerDependenciesMeta: - "@swc/core": + '@swc/core': optional: true - "@swc/wasm": + '@swc/wasm': optional: true tsconfig-paths@4.2.0: - resolution: - { - integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} tuf-js@2.2.1: - resolution: - { - integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} + engines: {node: ^16.14.0 || >=18.0.0} type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} type-detect@4.0.8: - resolution: - { - integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} type-fest@0.18.1: - resolution: - { - integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} type-fest@0.21.3: - resolution: - { - integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} type-fest@0.4.1: - resolution: - { - integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==} + engines: {node: '>=6'} type-fest@0.6.0: - resolution: - { - integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} type-fest@0.8.1: - resolution: - { - integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} type-fest@4.41.0: - resolution: - { - integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} typedarray@0.0.6: - resolution: - { - integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==, - } + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true uglify-js@3.19.3: - resolution: - { - integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==, - } - engines: { node: ">=0.8.0" } + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} hasBin: true undici-types@6.21.0: - resolution: - { - integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, - } + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} unicorn-magic@0.3.0: - resolution: - { - integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} unique-filename@3.0.0: - resolution: - { - integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} unique-slug@4.0.0: - resolution: - { - integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} universal-user-agent@6.0.1: - resolution: - { - integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, - } + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: ">= 10.0.0" } + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} unrs-resolver@1.11.1: - resolution: - { - integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==, - } + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} untildify@4.0.0: - resolution: - { - integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} upath@2.0.1: - resolution: - { - integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} + engines: {node: '>=4'} update-browserslist-db@1.1.4: - resolution: - { - integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==, - } + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: - browserslist: ">= 4.21.0" + browserslist: '>= 4.21.0' uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} util-deprecate@1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} uuid@10.0.0: - resolution: - { - integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==, - } + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true v8-compile-cache-lib@3.0.1: - resolution: - { - integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, - } + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} v8-to-istanbul@9.3.0: - resolution: - { - integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==, - } - engines: { node: ">=10.12.0" } + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} validate-npm-package-license@3.0.4: - resolution: - { - integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==, - } + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} validate-npm-package-name@5.0.1: - resolution: - { - integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} walk-up-path@3.0.1: - resolution: - { - integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==, - } + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} walker@1.0.8: - resolution: - { - integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==, - } + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} wcwidth@1.0.1: - resolution: - { - integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, - } + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} whatwg-fetch@3.6.20: - resolution: - { - integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==, - } + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true which@4.0.0: - resolution: - { - integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==, - } - engines: { node: ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} hasBin: true wide-align@1.1.5: - resolution: - { - integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==, - } + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} wordwrap@1.0.0: - resolution: - { - integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==, - } + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} wrap-ansi@6.2.0: - resolution: - { - integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: - { - integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} write-file-atomic@2.4.3: - resolution: - { - integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==, - } + resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} write-file-atomic@5.0.1: - resolution: - { - integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} write-json-file@3.2.0: - resolution: - { - integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==} + engines: {node: '>=6'} write-pkg@4.0.0: - resolution: - { - integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==} + engines: {node: '>=8'} xtend@4.0.2: - resolution: - { - integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, - } - engines: { node: ">=0.4" } + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} yallist@3.1.1: - resolution: - { - integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, - } + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} yallist@4.0.0: - resolution: - { - integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, - } + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} yaml@2.8.1: - resolution: - { - integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==, - } - engines: { node: ">= 14.6" } + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} hasBin: true yaml@2.8.2: - resolution: - { - integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==, - } - engines: { node: ">= 14.6" } + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} hasBin: true yargs-parser@20.2.9: - resolution: - { - integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} yargs@16.2.0: - resolution: - { - integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} yargs@17.7.2: - resolution: - { - integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} yn@3.1.1: - resolution: - { - integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} yocto-queue@0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} snapshots: - "@babel/code-frame@7.27.1": + + '@babel/code-frame@7.27.1': dependencies: - "@babel/helper-validator-identifier": 7.28.5 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - "@babel/code-frame@7.28.6": + '@babel/code-frame@7.28.6': dependencies: - "@babel/helper-validator-identifier": 7.28.5 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - "@babel/compat-data@7.28.5": {} + '@babel/compat-data@7.28.5': {} - "@babel/core@7.28.5": + '@babel/core@7.28.5': dependencies: - "@babel/code-frame": 7.27.1 - "@babel/generator": 7.28.6 - "@babel/helper-compilation-targets": 7.27.2 - "@babel/helper-module-transforms": 7.28.3(@babel/core@7.28.5) - "@babel/helpers": 7.28.4 - "@babel/parser": 7.28.6 - "@babel/template": 7.27.2 - "@babel/traverse": 7.28.6 - "@babel/types": 7.28.6 - "@jridgewell/remapping": 2.3.5 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.6 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 @@ -6622,214 +4037,214 @@ snapshots: transitivePeerDependencies: - supports-color - "@babel/generator@7.28.6": + '@babel/generator@7.28.6': dependencies: - "@babel/parser": 7.28.6 - "@babel/types": 7.28.6 - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - "@babel/helper-compilation-targets@7.27.2": + '@babel/helper-compilation-targets@7.27.2': dependencies: - "@babel/compat-data": 7.28.5 - "@babel/helper-validator-option": 7.27.1 + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 browserslist: 4.28.0 lru-cache: 5.1.1 semver: 6.3.1 - "@babel/helper-globals@7.28.0": {} + '@babel/helper-globals@7.28.0': {} - "@babel/helper-module-imports@7.27.1": + '@babel/helper-module-imports@7.27.1': dependencies: - "@babel/traverse": 7.28.6 - "@babel/types": 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)": + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-module-imports": 7.27.1 - "@babel/helper-validator-identifier": 7.28.5 - "@babel/traverse": 7.28.6 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/helper-plugin-utils@7.27.1": {} + '@babel/helper-plugin-utils@7.27.1': {} - "@babel/helper-string-parser@7.27.1": {} + '@babel/helper-string-parser@7.27.1': {} - "@babel/helper-validator-identifier@7.28.5": {} + '@babel/helper-validator-identifier@7.28.5': {} - "@babel/helper-validator-option@7.27.1": {} + '@babel/helper-validator-option@7.27.1': {} - "@babel/helpers@7.28.4": + '@babel/helpers@7.28.4': dependencies: - "@babel/template": 7.27.2 - "@babel/types": 7.28.6 + '@babel/template': 7.27.2 + '@babel/types': 7.28.6 - "@babel/parser@7.28.6": + '@babel/parser@7.28.6': dependencies: - "@babel/types": 7.28.6 + '@babel/types': 7.28.6 - "@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)": + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)": + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)": + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)": + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)": + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)": + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)": + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)": + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)": + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)": + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)": + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)": + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)': dependencies: - "@babel/core": 7.28.5 - "@babel/helper-plugin-utils": 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - "@babel/template@7.27.2": + '@babel/template@7.27.2': dependencies: - "@babel/code-frame": 7.27.1 - "@babel/parser": 7.28.6 - "@babel/types": 7.28.6 + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 - "@babel/template@7.28.6": + '@babel/template@7.28.6': dependencies: - "@babel/code-frame": 7.28.6 - "@babel/parser": 7.28.6 - "@babel/types": 7.28.6 + '@babel/code-frame': 7.28.6 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 - "@babel/traverse@7.28.6": + '@babel/traverse@7.28.6': dependencies: - "@babel/code-frame": 7.28.6 - "@babel/generator": 7.28.6 - "@babel/helper-globals": 7.28.0 - "@babel/parser": 7.28.6 - "@babel/template": 7.28.6 - "@babel/types": 7.28.6 + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 debug: 4.4.3 transitivePeerDependencies: - supports-color - "@babel/types@7.28.6": + '@babel/types@7.28.6': dependencies: - "@babel/helper-string-parser": 7.27.1 - "@babel/helper-validator-identifier": 7.28.5 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - "@bcoe/v8-coverage@0.2.3": {} + '@bcoe/v8-coverage@0.2.3': {} - "@cspotcode/source-map-support@0.8.1": + '@cspotcode/source-map-support@0.8.1': dependencies: - "@jridgewell/trace-mapping": 0.3.9 + '@jridgewell/trace-mapping': 0.3.9 - "@emnapi/core@1.7.1": + '@emnapi/core@1.7.1': dependencies: - "@emnapi/wasi-threads": 1.1.0 + '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 - "@emnapi/runtime@1.7.1": + '@emnapi/runtime@1.7.1': dependencies: tslib: 2.8.1 - "@emnapi/wasi-threads@1.1.0": + '@emnapi/wasi-threads@1.1.0': dependencies: tslib: 2.8.1 - "@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)": + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)': dependencies: eslint: 9.39.2 eslint-visitor-keys: 3.4.3 - "@eslint-community/regexpp@4.12.2": {} + '@eslint-community/regexpp@4.12.2': {} - "@eslint/config-array@0.21.1": + '@eslint/config-array@0.21.1': dependencies: - "@eslint/object-schema": 2.1.7 + '@eslint/object-schema': 2.1.7 debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - "@eslint/config-helpers@0.4.2": + '@eslint/config-helpers@0.4.2': dependencies: - "@eslint/core": 0.17.0 + '@eslint/core': 0.17.0 - "@eslint/core@0.17.0": + '@eslint/core@0.17.0': dependencies: - "@types/json-schema": 7.0.15 + '@types/json-schema': 7.0.15 - "@eslint/eslintrc@3.3.3": + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -6843,42 +4258,42 @@ snapshots: transitivePeerDependencies: - supports-color - "@eslint/js@9.39.2": {} + '@eslint/js@9.39.2': {} - "@eslint/object-schema@2.1.7": {} + '@eslint/object-schema@2.1.7': {} - "@eslint/plugin-kit@0.4.1": + '@eslint/plugin-kit@0.4.1': dependencies: - "@eslint/core": 0.17.0 + '@eslint/core': 0.17.0 levn: 0.4.1 - "@humanfs/core@0.19.1": {} + '@humanfs/core@0.19.1': {} - "@humanfs/node@0.16.7": + '@humanfs/node@0.16.7': dependencies: - "@humanfs/core": 0.19.1 - "@humanwhocodes/retry": 0.4.3 + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 - "@humanwhocodes/module-importer@1.0.1": {} + '@humanwhocodes/module-importer@1.0.1': {} - "@humanwhocodes/retry@0.4.3": {} + '@humanwhocodes/retry@0.4.3': {} - "@hutson/parse-repository-url@3.0.2": {} + '@hutson/parse-repository-url@3.0.2': {} - "@inquirer/external-editor@1.0.3(@types/node@22.19.1)": + '@inquirer/external-editor@1.0.3(@types/node@22.19.1)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.0 optionalDependencies: - "@types/node": 22.19.1 + '@types/node': 22.19.1 - "@isaacs/balanced-match@4.0.1": {} + '@isaacs/balanced-match@4.0.1': {} - "@isaacs/brace-expansion@5.0.0": + '@isaacs/brace-expansion@5.0.0': dependencies: - "@isaacs/balanced-match": 4.0.1 + '@isaacs/balanced-match': 4.0.1 - "@isaacs/cliui@8.0.2": + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 @@ -6887,9 +4302,9 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - "@isaacs/string-locale-compare@1.1.0": {} + '@isaacs/string-locale-compare@1.1.0': {} - "@istanbuljs/load-nyc-config@1.1.0": + '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 find-up: 4.1.0 @@ -6897,26 +4312,26 @@ snapshots: js-yaml: 3.14.2 resolve-from: 5.0.0 - "@istanbuljs/schema@0.1.3": {} + '@istanbuljs/schema@0.1.3': {} - "@jest/console@30.2.0": + '@jest/console@30.2.0': dependencies: - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 chalk: 4.1.2 jest-message-util: 30.2.0 jest-util: 30.2.0 slash: 3.0.0 - "@jest/core@30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))": + '@jest/core@30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))': dependencies: - "@jest/console": 30.2.0 - "@jest/pattern": 30.0.1 - "@jest/reporters": 30.2.0 - "@jest/test-result": 30.2.0 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/console': 30.2.0 + '@jest/pattern': 30.0.1 + '@jest/reporters': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 4.3.1 @@ -6944,60 +4359,60 @@ snapshots: - supports-color - ts-node - "@jest/diff-sequences@30.0.1": {} + '@jest/diff-sequences@30.0.1': {} - "@jest/environment@30.2.0": + '@jest/environment@30.2.0': dependencies: - "@jest/fake-timers": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 jest-mock: 30.2.0 - "@jest/expect-utils@30.2.0": + '@jest/expect-utils@30.2.0': dependencies: - "@jest/get-type": 30.1.0 + '@jest/get-type': 30.1.0 - "@jest/expect@30.2.0": + '@jest/expect@30.2.0': dependencies: expect: 30.2.0 jest-snapshot: 30.2.0 transitivePeerDependencies: - supports-color - "@jest/fake-timers@30.2.0": + '@jest/fake-timers@30.2.0': dependencies: - "@jest/types": 30.2.0 - "@sinonjs/fake-timers": 13.0.5 - "@types/node": 22.19.1 + '@jest/types': 30.2.0 + '@sinonjs/fake-timers': 13.0.5 + '@types/node': 22.19.1 jest-message-util: 30.2.0 jest-mock: 30.2.0 jest-util: 30.2.0 - "@jest/get-type@30.1.0": {} + '@jest/get-type@30.1.0': {} - "@jest/globals@30.2.0": + '@jest/globals@30.2.0': dependencies: - "@jest/environment": 30.2.0 - "@jest/expect": 30.2.0 - "@jest/types": 30.2.0 + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/types': 30.2.0 jest-mock: 30.2.0 transitivePeerDependencies: - supports-color - "@jest/pattern@30.0.1": + '@jest/pattern@30.0.1': dependencies: - "@types/node": 22.19.1 + '@types/node': 22.19.1 jest-regex-util: 30.0.1 - "@jest/reporters@30.2.0": + '@jest/reporters@30.2.0': dependencies: - "@bcoe/v8-coverage": 0.2.3 - "@jest/console": 30.2.0 - "@jest/test-result": 30.2.0 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 - "@jridgewell/trace-mapping": 0.3.31 - "@types/node": 22.19.1 + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 22.19.1 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit-x: 0.2.2 @@ -7017,46 +4432,46 @@ snapshots: transitivePeerDependencies: - supports-color - "@jest/schemas@29.6.3": + '@jest/schemas@29.6.3': dependencies: - "@sinclair/typebox": 0.27.8 + '@sinclair/typebox': 0.27.8 - "@jest/schemas@30.0.5": + '@jest/schemas@30.0.5': dependencies: - "@sinclair/typebox": 0.34.41 + '@sinclair/typebox': 0.34.41 - "@jest/snapshot-utils@30.2.0": + '@jest/snapshot-utils@30.2.0': dependencies: - "@jest/types": 30.2.0 + '@jest/types': 30.2.0 chalk: 4.1.2 graceful-fs: 4.2.11 natural-compare: 1.4.0 - "@jest/source-map@30.0.1": + '@jest/source-map@30.0.1': dependencies: - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/trace-mapping': 0.3.31 callsites: 3.1.0 graceful-fs: 4.2.11 - "@jest/test-result@30.2.0": + '@jest/test-result@30.2.0': dependencies: - "@jest/console": 30.2.0 - "@jest/types": 30.2.0 - "@types/istanbul-lib-coverage": 2.0.6 + '@jest/console': 30.2.0 + '@jest/types': 30.2.0 + '@types/istanbul-lib-coverage': 2.0.6 collect-v8-coverage: 1.0.3 - "@jest/test-sequencer@30.2.0": + '@jest/test-sequencer@30.2.0': dependencies: - "@jest/test-result": 30.2.0 + '@jest/test-result': 30.2.0 graceful-fs: 4.2.11 jest-haste-map: 30.2.0 slash: 3.0.0 - "@jest/transform@30.2.0": + '@jest/transform@30.2.0': dependencies: - "@babel/core": 7.28.5 - "@jest/types": 30.2.0 - "@jridgewell/trace-mapping": 0.3.31 + '@babel/core': 7.28.5 + '@jest/types': 30.2.0 + '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 7.0.1 chalk: 4.1.2 convert-source-map: 2.0.0 @@ -7072,63 +4487,63 @@ snapshots: transitivePeerDependencies: - supports-color - "@jest/types@30.2.0": + '@jest/types@30.2.0': dependencies: - "@jest/pattern": 30.0.1 - "@jest/schemas": 30.0.5 - "@types/istanbul-lib-coverage": 2.0.6 - "@types/istanbul-reports": 3.0.4 - "@types/node": 22.19.1 - "@types/yargs": 17.0.35 + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.19.1 + '@types/yargs': 17.0.35 chalk: 4.1.2 - "@jridgewell/gen-mapping@0.3.13": + '@jridgewell/gen-mapping@0.3.13': dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - "@jridgewell/remapping@2.3.5": + '@jridgewell/remapping@2.3.5': dependencies: - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - "@jridgewell/resolve-uri@3.1.2": {} + '@jridgewell/resolve-uri@3.1.2': {} - "@jridgewell/sourcemap-codec@1.5.5": {} + '@jridgewell/sourcemap-codec@1.5.5': {} - "@jridgewell/trace-mapping@0.3.31": + '@jridgewell/trace-mapping@0.3.31': dependencies: - "@jridgewell/resolve-uri": 3.1.2 - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - "@jridgewell/trace-mapping@0.3.9": + '@jridgewell/trace-mapping@0.3.9': dependencies: - "@jridgewell/resolve-uri": 3.1.2 - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - "@launchql/protobufjs@7.2.6": + '@launchql/protobufjs@7.2.6': dependencies: - "@protobufjs/aspromise": 1.1.2 - "@protobufjs/base64": 1.1.2 - "@protobufjs/codegen": 2.0.4 - "@protobufjs/eventemitter": 1.1.0 - "@protobufjs/fetch": 1.1.0 - "@protobufjs/float": 1.0.2 - "@protobufjs/inquire": 1.1.0 - "@protobufjs/path": 1.1.2 - "@protobufjs/pool": 1.1.0 - "@protobufjs/utf8": 1.1.0 - "@types/node": 22.19.1 + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.19.1 long: 5.3.2 - "@lerna/create@8.2.4(@types/node@22.19.1)(encoding@0.1.13)(typescript@5.9.3)": + '@lerna/create@8.2.4(@types/node@22.19.1)(encoding@0.1.13)(typescript@5.9.3)': dependencies: - "@npmcli/arborist": 7.5.4 - "@npmcli/package-json": 5.2.0 - "@npmcli/run-script": 8.1.0 - "@nx/devkit": 20.8.3(nx@20.8.3) - "@octokit/plugin-enterprise-rest": 6.0.1 - "@octokit/rest": 20.1.2 + '@npmcli/arborist': 7.5.4 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 + '@nx/devkit': 20.8.3(nx@20.8.3) + '@octokit/plugin-enterprise-rest': 6.0.1 + '@octokit/rest': 20.1.2 aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 @@ -7193,9 +4608,9 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 transitivePeerDependencies: - - "@swc-node/register" - - "@swc/core" - - "@types/node" + - '@swc-node/register' + - '@swc/core' + - '@types/node' - babel-plugin-macros - bluebird - debug @@ -7203,34 +4618,34 @@ snapshots: - supports-color - typescript - "@marcbachmann/cel-js@7.1.0": {} + '@marcbachmann/cel-js@7.1.0': {} - "@napi-rs/wasm-runtime@0.2.12": + '@napi-rs/wasm-runtime@0.2.12': dependencies: - "@emnapi/core": 1.7.1 - "@emnapi/runtime": 1.7.1 - "@tybys/wasm-util": 0.10.1 + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 optional: true - "@napi-rs/wasm-runtime@0.2.4": + '@napi-rs/wasm-runtime@0.2.4': dependencies: - "@emnapi/core": 1.7.1 - "@emnapi/runtime": 1.7.1 - "@tybys/wasm-util": 0.9.0 + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.9.0 - "@nodelib/fs.scandir@2.1.5": + '@nodelib/fs.scandir@2.1.5': dependencies: - "@nodelib/fs.stat": 2.0.5 + '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - "@nodelib/fs.stat@2.0.5": {} + '@nodelib/fs.stat@2.0.5': {} - "@nodelib/fs.walk@1.2.8": + '@nodelib/fs.walk@1.2.8': dependencies: - "@nodelib/fs.scandir": 2.1.5 + '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - "@npmcli/agent@2.2.2": + '@npmcli/agent@2.2.2': dependencies: agent-base: 7.1.4 http-proxy-agent: 7.0.2 @@ -7240,19 +4655,19 @@ snapshots: transitivePeerDependencies: - supports-color - "@npmcli/arborist@7.5.4": - dependencies: - "@isaacs/string-locale-compare": 1.1.0 - "@npmcli/fs": 3.1.1 - "@npmcli/installed-package-contents": 2.1.0 - "@npmcli/map-workspaces": 3.0.6 - "@npmcli/metavuln-calculator": 7.1.1 - "@npmcli/name-from-folder": 2.0.0 - "@npmcli/node-gyp": 3.0.0 - "@npmcli/package-json": 5.2.0 - "@npmcli/query": 3.1.0 - "@npmcli/redact": 2.0.1 - "@npmcli/run-script": 8.1.0 + '@npmcli/arborist@7.5.4': + dependencies: + '@isaacs/string-locale-compare': 1.1.0 + '@npmcli/fs': 3.1.1 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/map-workspaces': 3.0.6 + '@npmcli/metavuln-calculator': 7.1.1 + '@npmcli/name-from-folder': 2.0.0 + '@npmcli/node-gyp': 3.0.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/query': 3.1.0 + '@npmcli/redact': 2.0.1 + '@npmcli/run-script': 8.1.0 bin-links: 4.0.4 cacache: 18.0.4 common-ancestor-path: 1.0.1 @@ -7281,13 +4696,13 @@ snapshots: - bluebird - supports-color - "@npmcli/fs@3.1.1": + '@npmcli/fs@3.1.1': dependencies: semver: 7.7.3 - "@npmcli/git@5.0.8": + '@npmcli/git@5.0.8': dependencies: - "@npmcli/promise-spawn": 7.0.2 + '@npmcli/promise-spawn': 7.0.2 ini: 4.1.3 lru-cache: 10.4.3 npm-pick-manifest: 9.1.0 @@ -7299,19 +4714,19 @@ snapshots: transitivePeerDependencies: - bluebird - "@npmcli/installed-package-contents@2.1.0": + '@npmcli/installed-package-contents@2.1.0': dependencies: npm-bundled: 3.0.1 npm-normalize-package-bin: 3.0.1 - "@npmcli/map-workspaces@3.0.6": + '@npmcli/map-workspaces@3.0.6': dependencies: - "@npmcli/name-from-folder": 2.0.0 + '@npmcli/name-from-folder': 2.0.0 glob: 10.5.0 minimatch: 9.0.5 read-package-json-fast: 3.0.2 - "@npmcli/metavuln-calculator@7.1.1": + '@npmcli/metavuln-calculator@7.1.1': dependencies: cacache: 18.0.4 json-parse-even-better-errors: 3.0.2 @@ -7322,13 +4737,13 @@ snapshots: - bluebird - supports-color - "@npmcli/name-from-folder@2.0.0": {} + '@npmcli/name-from-folder@2.0.0': {} - "@npmcli/node-gyp@3.0.0": {} + '@npmcli/node-gyp@3.0.0': {} - "@npmcli/package-json@5.2.0": + '@npmcli/package-json@5.2.0': dependencies: - "@npmcli/git": 5.0.8 + '@npmcli/git': 5.0.8 glob: 10.5.0 hosted-git-info: 7.0.2 json-parse-even-better-errors: 3.0.2 @@ -7338,21 +4753,21 @@ snapshots: transitivePeerDependencies: - bluebird - "@npmcli/promise-spawn@7.0.2": + '@npmcli/promise-spawn@7.0.2': dependencies: which: 4.0.0 - "@npmcli/query@3.1.0": + '@npmcli/query@3.1.0': dependencies: postcss-selector-parser: 6.1.2 - "@npmcli/redact@2.0.1": {} + '@npmcli/redact@2.0.1': {} - "@npmcli/run-script@8.1.0": + '@npmcli/run-script@8.1.0': dependencies: - "@npmcli/node-gyp": 3.0.0 - "@npmcli/package-json": 5.2.0 - "@npmcli/promise-spawn": 7.0.2 + '@npmcli/node-gyp': 3.0.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/promise-spawn': 7.0.2 node-gyp: 10.3.1 proc-log: 4.2.0 which: 4.0.0 @@ -7360,7 +4775,7 @@ snapshots: - bluebird - supports-color - "@nx/devkit@20.8.3(nx@20.8.3)": + '@nx/devkit@20.8.3(nx@20.8.3)': dependencies: ejs: 3.1.10 enquirer: 2.3.6 @@ -7372,269 +4787,269 @@ snapshots: tslib: 2.8.1 yargs-parser: 21.1.1 - "@nx/nx-darwin-arm64@20.8.3": + '@nx/nx-darwin-arm64@20.8.3': optional: true - "@nx/nx-darwin-x64@20.8.3": + '@nx/nx-darwin-x64@20.8.3': optional: true - "@nx/nx-freebsd-x64@20.8.3": + '@nx/nx-freebsd-x64@20.8.3': optional: true - "@nx/nx-linux-arm-gnueabihf@20.8.3": + '@nx/nx-linux-arm-gnueabihf@20.8.3': optional: true - "@nx/nx-linux-arm64-gnu@20.8.3": + '@nx/nx-linux-arm64-gnu@20.8.3': optional: true - "@nx/nx-linux-arm64-musl@20.8.3": + '@nx/nx-linux-arm64-musl@20.8.3': optional: true - "@nx/nx-linux-x64-gnu@20.8.3": + '@nx/nx-linux-x64-gnu@20.8.3': optional: true - "@nx/nx-linux-x64-musl@20.8.3": + '@nx/nx-linux-x64-musl@20.8.3': optional: true - "@nx/nx-win32-arm64-msvc@20.8.3": + '@nx/nx-win32-arm64-msvc@20.8.3': optional: true - "@nx/nx-win32-x64-msvc@20.8.3": + '@nx/nx-win32-x64-msvc@20.8.3': optional: true - "@octokit/auth-token@4.0.0": {} + '@octokit/auth-token@4.0.0': {} - "@octokit/core@5.2.2": + '@octokit/core@5.2.2': dependencies: - "@octokit/auth-token": 4.0.0 - "@octokit/graphql": 7.1.1 - "@octokit/request": 8.4.1 - "@octokit/request-error": 5.1.1 - "@octokit/types": 13.10.0 + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.1 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 before-after-hook: 2.2.3 universal-user-agent: 6.0.1 - "@octokit/endpoint@9.0.6": + '@octokit/endpoint@9.0.6': dependencies: - "@octokit/types": 13.10.0 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/graphql@7.1.1": + '@octokit/graphql@7.1.1': dependencies: - "@octokit/request": 8.4.1 - "@octokit/types": 13.10.0 + '@octokit/request': 8.4.1 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/openapi-types@24.2.0": {} + '@octokit/openapi-types@24.2.0': {} - "@octokit/plugin-enterprise-rest@6.0.1": {} + '@octokit/plugin-enterprise-rest@6.0.1': {} - "@octokit/plugin-paginate-rest@11.4.4-cjs.2(@octokit/core@5.2.2)": + '@octokit/plugin-paginate-rest@11.4.4-cjs.2(@octokit/core@5.2.2)': dependencies: - "@octokit/core": 5.2.2 - "@octokit/types": 13.10.0 + '@octokit/core': 5.2.2 + '@octokit/types': 13.10.0 - "@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.2)": + '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.2)': dependencies: - "@octokit/core": 5.2.2 + '@octokit/core': 5.2.2 - "@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1(@octokit/core@5.2.2)": + '@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1(@octokit/core@5.2.2)': dependencies: - "@octokit/core": 5.2.2 - "@octokit/types": 13.10.0 + '@octokit/core': 5.2.2 + '@octokit/types': 13.10.0 - "@octokit/request-error@5.1.1": + '@octokit/request-error@5.1.1': dependencies: - "@octokit/types": 13.10.0 + '@octokit/types': 13.10.0 deprecation: 2.3.1 once: 1.4.0 - "@octokit/request@8.4.1": + '@octokit/request@8.4.1': dependencies: - "@octokit/endpoint": 9.0.6 - "@octokit/request-error": 5.1.1 - "@octokit/types": 13.10.0 + '@octokit/endpoint': 9.0.6 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/rest@20.1.2": + '@octokit/rest@20.1.2': dependencies: - "@octokit/core": 5.2.2 - "@octokit/plugin-paginate-rest": 11.4.4-cjs.2(@octokit/core@5.2.2) - "@octokit/plugin-request-log": 4.0.1(@octokit/core@5.2.2) - "@octokit/plugin-rest-endpoint-methods": 13.3.2-cjs.1(@octokit/core@5.2.2) + '@octokit/core': 5.2.2 + '@octokit/plugin-paginate-rest': 11.4.4-cjs.2(@octokit/core@5.2.2) + '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.2) + '@octokit/plugin-rest-endpoint-methods': 13.3.2-cjs.1(@octokit/core@5.2.2) - "@octokit/types@13.10.0": + '@octokit/types@13.10.0': dependencies: - "@octokit/openapi-types": 24.2.0 + '@octokit/openapi-types': 24.2.0 - "@pkgjs/parseargs@0.11.0": + '@pkgjs/parseargs@0.11.0': optional: true - "@pkgr/core@0.2.9": {} + '@pkgr/core@0.2.9': {} - "@protobufjs/aspromise@1.1.2": {} + '@protobufjs/aspromise@1.1.2': {} - "@protobufjs/base64@1.1.2": {} + '@protobufjs/base64@1.1.2': {} - "@protobufjs/codegen@2.0.4": {} + '@protobufjs/codegen@2.0.4': {} - "@protobufjs/eventemitter@1.1.0": {} + '@protobufjs/eventemitter@1.1.0': {} - "@protobufjs/fetch@1.1.0": + '@protobufjs/fetch@1.1.0': dependencies: - "@protobufjs/aspromise": 1.1.2 - "@protobufjs/inquire": 1.1.0 + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 - "@protobufjs/float@1.0.2": {} + '@protobufjs/float@1.0.2': {} - "@protobufjs/inquire@1.1.0": {} + '@protobufjs/inquire@1.1.0': {} - "@protobufjs/path@1.1.2": {} + '@protobufjs/path@1.1.2': {} - "@protobufjs/pool@1.1.0": {} + '@protobufjs/pool@1.1.0': {} - "@protobufjs/utf8@1.1.0": {} + '@protobufjs/utf8@1.1.0': {} - "@sigstore/bundle@2.3.2": + '@sigstore/bundle@2.3.2': dependencies: - "@sigstore/protobuf-specs": 0.3.3 + '@sigstore/protobuf-specs': 0.3.3 - "@sigstore/core@1.1.0": {} + '@sigstore/core@1.1.0': {} - "@sigstore/protobuf-specs@0.3.3": {} + '@sigstore/protobuf-specs@0.3.3': {} - "@sigstore/sign@2.3.2": + '@sigstore/sign@2.3.2': dependencies: - "@sigstore/bundle": 2.3.2 - "@sigstore/core": 1.1.0 - "@sigstore/protobuf-specs": 0.3.3 + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 make-fetch-happen: 13.0.1 proc-log: 4.2.0 promise-retry: 2.0.1 transitivePeerDependencies: - supports-color - "@sigstore/tuf@2.3.4": + '@sigstore/tuf@2.3.4': dependencies: - "@sigstore/protobuf-specs": 0.3.3 + '@sigstore/protobuf-specs': 0.3.3 tuf-js: 2.2.1 transitivePeerDependencies: - supports-color - "@sigstore/verify@1.2.1": + '@sigstore/verify@1.2.1': dependencies: - "@sigstore/bundle": 2.3.2 - "@sigstore/core": 1.1.0 - "@sigstore/protobuf-specs": 0.3.3 + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 - "@sinclair/typebox@0.27.8": {} + '@sinclair/typebox@0.27.8': {} - "@sinclair/typebox@0.34.41": {} + '@sinclair/typebox@0.34.41': {} - "@sindresorhus/merge-streams@4.0.0": {} + '@sindresorhus/merge-streams@4.0.0': {} - "@sinonjs/commons@3.0.1": + '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 - "@sinonjs/fake-timers@13.0.5": + '@sinonjs/fake-timers@13.0.5': dependencies: - "@sinonjs/commons": 3.0.1 + '@sinonjs/commons': 3.0.1 - "@tsconfig/node10@1.0.12": {} + '@tsconfig/node10@1.0.12': {} - "@tsconfig/node12@1.0.11": {} + '@tsconfig/node12@1.0.11': {} - "@tsconfig/node14@1.0.3": {} + '@tsconfig/node14@1.0.3': {} - "@tsconfig/node16@1.0.4": {} + '@tsconfig/node16@1.0.4': {} - "@tufjs/canonical-json@2.0.0": {} + '@tufjs/canonical-json@2.0.0': {} - "@tufjs/models@2.0.1": + '@tufjs/models@2.0.1': dependencies: - "@tufjs/canonical-json": 2.0.0 + '@tufjs/canonical-json': 2.0.0 minimatch: 9.0.5 - "@tybys/wasm-util@0.10.1": + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true - "@tybys/wasm-util@0.9.0": + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 - "@types/babel__core@7.20.5": + '@types/babel__core@7.20.5': dependencies: - "@babel/parser": 7.28.6 - "@babel/types": 7.28.6 - "@types/babel__generator": 7.27.0 - "@types/babel__template": 7.4.4 - "@types/babel__traverse": 7.28.0 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 - "@types/babel__generator@7.27.0": + '@types/babel__generator@7.27.0': dependencies: - "@babel/types": 7.28.6 + '@babel/types': 7.28.6 - "@types/babel__template@7.4.4": + '@types/babel__template@7.4.4': dependencies: - "@babel/parser": 7.28.6 - "@babel/types": 7.28.6 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 - "@types/babel__traverse@7.28.0": + '@types/babel__traverse@7.28.0': dependencies: - "@babel/types": 7.28.6 + '@babel/types': 7.28.6 - "@types/estree@1.0.8": {} + '@types/estree@1.0.8': {} - "@types/isomorphic-fetch@0.0.39": {} + '@types/isomorphic-fetch@0.0.39': {} - "@types/istanbul-lib-coverage@2.0.6": {} + '@types/istanbul-lib-coverage@2.0.6': {} - "@types/istanbul-lib-report@3.0.3": + '@types/istanbul-lib-report@3.0.3': dependencies: - "@types/istanbul-lib-coverage": 2.0.6 + '@types/istanbul-lib-coverage': 2.0.6 - "@types/istanbul-reports@3.0.4": + '@types/istanbul-reports@3.0.4': dependencies: - "@types/istanbul-lib-report": 3.0.3 + '@types/istanbul-lib-report': 3.0.3 - "@types/jest@30.0.0": + '@types/jest@30.0.0': dependencies: expect: 30.2.0 pretty-format: 30.2.0 - "@types/json-schema@7.0.15": {} + '@types/json-schema@7.0.15': {} - "@types/minimatch@3.0.5": {} + '@types/minimatch@3.0.5': {} - "@types/minimist@1.2.5": {} + '@types/minimist@1.2.5': {} - "@types/node@22.19.1": + '@types/node@22.19.1': dependencies: undici-types: 6.21.0 - "@types/normalize-package-data@2.4.4": {} + '@types/normalize-package-data@2.4.4': {} - "@types/semver@7.7.1": {} + '@types/semver@7.7.1': {} - "@types/stack-utils@2.0.3": {} + '@types/stack-utils@2.0.3': {} - "@types/yargs-parser@21.0.3": {} + '@types/yargs-parser@21.0.3': {} - "@types/yargs@17.0.35": + '@types/yargs@17.0.35': dependencies: - "@types/yargs-parser": 21.0.3 + '@types/yargs-parser': 21.0.3 - "@typescript-eslint/eslint-plugin@8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)": + '@typescript-eslint/eslint-plugin@8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: - "@eslint-community/regexpp": 4.12.2 - "@typescript-eslint/parser": 8.53.1(eslint@9.39.2)(typescript@5.9.3) - "@typescript-eslint/scope-manager": 8.53.1 - "@typescript-eslint/type-utils": 8.53.1(eslint@9.39.2)(typescript@5.9.3) - "@typescript-eslint/utils": 8.53.1(eslint@9.39.2)(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.53.1 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.53.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/type-utils': 8.53.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.53.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.53.1 eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 @@ -7643,41 +5058,41 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3)": + '@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - "@typescript-eslint/scope-manager": 8.53.1 - "@typescript-eslint/types": 8.53.1 - "@typescript-eslint/typescript-estree": 8.53.1(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.53.1 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/project-service@8.53.1(typescript@5.9.3)": + '@typescript-eslint/project-service@8.53.1(typescript@5.9.3)': dependencies: - "@typescript-eslint/tsconfig-utils": 8.53.1(typescript@5.9.3) - "@typescript-eslint/types": 8.53.1 + '@typescript-eslint/tsconfig-utils': 8.53.1(typescript@5.9.3) + '@typescript-eslint/types': 8.53.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/scope-manager@8.53.1": + '@typescript-eslint/scope-manager@8.53.1': dependencies: - "@typescript-eslint/types": 8.53.1 - "@typescript-eslint/visitor-keys": 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 - "@typescript-eslint/tsconfig-utils@8.53.1(typescript@5.9.3)": + '@typescript-eslint/tsconfig-utils@8.53.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - "@typescript-eslint/type-utils@8.53.1(eslint@9.39.2)(typescript@5.9.3)": + '@typescript-eslint/type-utils@8.53.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - "@typescript-eslint/types": 8.53.1 - "@typescript-eslint/typescript-estree": 8.53.1(typescript@5.9.3) - "@typescript-eslint/utils": 8.53.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.53.1(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3 eslint: 9.39.2 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -7685,14 +5100,14 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/types@8.53.1": {} + '@typescript-eslint/types@8.53.1': {} - "@typescript-eslint/typescript-estree@8.53.1(typescript@5.9.3)": + '@typescript-eslint/typescript-estree@8.53.1(typescript@5.9.3)': dependencies: - "@typescript-eslint/project-service": 8.53.1(typescript@5.9.3) - "@typescript-eslint/tsconfig-utils": 8.53.1(typescript@5.9.3) - "@typescript-eslint/types": 8.53.1 - "@typescript-eslint/visitor-keys": 8.53.1 + '@typescript-eslint/project-service': 8.53.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.53.1(typescript@5.9.3) + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -7702,91 +5117,91 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3)": + '@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@9.39.2) - "@typescript-eslint/scope-manager": 8.53.1 - "@typescript-eslint/types": 8.53.1 - "@typescript-eslint/typescript-estree": 8.53.1(typescript@5.9.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/visitor-keys@8.53.1": + '@typescript-eslint/visitor-keys@8.53.1': dependencies: - "@typescript-eslint/types": 8.53.1 + '@typescript-eslint/types': 8.53.1 eslint-visitor-keys: 4.2.1 - "@ungap/structured-clone@1.3.0": {} + '@ungap/structured-clone@1.3.0': {} - "@unrs/resolver-binding-android-arm-eabi@1.11.1": + '@unrs/resolver-binding-android-arm-eabi@1.11.1': optional: true - "@unrs/resolver-binding-android-arm64@1.11.1": + '@unrs/resolver-binding-android-arm64@1.11.1': optional: true - "@unrs/resolver-binding-darwin-arm64@1.11.1": + '@unrs/resolver-binding-darwin-arm64@1.11.1': optional: true - "@unrs/resolver-binding-darwin-x64@1.11.1": + '@unrs/resolver-binding-darwin-x64@1.11.1': optional: true - "@unrs/resolver-binding-freebsd-x64@1.11.1": + '@unrs/resolver-binding-freebsd-x64@1.11.1': optional: true - "@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': optional: true - "@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': optional: true - "@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': optional: true - "@unrs/resolver-binding-linux-arm64-musl@1.11.1": + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': optional: true - "@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': optional: true - "@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': optional: true - "@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': optional: true - "@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': optional: true - "@unrs/resolver-binding-linux-x64-gnu@1.11.1": + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': optional: true - "@unrs/resolver-binding-linux-x64-musl@1.11.1": + '@unrs/resolver-binding-linux-x64-musl@1.11.1': optional: true - "@unrs/resolver-binding-wasm32-wasi@1.11.1": + '@unrs/resolver-binding-wasm32-wasi@1.11.1': dependencies: - "@napi-rs/wasm-runtime": 0.2.12 + '@napi-rs/wasm-runtime': 0.2.12 optional: true - "@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': optional: true - "@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': optional: true - "@unrs/resolver-binding-win32-x64-msvc@1.11.1": + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - "@yarnpkg/lockfile@1.1.0": {} + '@yarnpkg/lockfile@1.1.0': {} - "@yarnpkg/parsers@3.0.2": + '@yarnpkg/parsers@3.0.2': dependencies: js-yaml: 3.14.2 tslib: 2.8.1 - "@zkochan/js-yaml@0.0.7": + '@zkochan/js-yaml@0.0.7': dependencies: argparse: 2.0.1 @@ -7880,9 +5295,9 @@ snapshots: babel-jest@30.2.0(@babel/core@7.28.5): dependencies: - "@babel/core": 7.28.5 - "@jest/transform": 30.2.0 - "@types/babel__core": 7.20.5 + '@babel/core': 7.28.5 + '@jest/transform': 30.2.0 + '@types/babel__core': 7.20.5 babel-plugin-istanbul: 7.0.1 babel-preset-jest: 30.2.0(@babel/core@7.28.5) chalk: 4.1.2 @@ -7893,9 +5308,9 @@ snapshots: babel-plugin-istanbul@7.0.1: dependencies: - "@babel/helper-plugin-utils": 7.27.1 - "@istanbuljs/load-nyc-config": 1.1.0 - "@istanbuljs/schema": 0.1.3 + '@babel/helper-plugin-utils': 7.27.1 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 6.0.3 test-exclude: 6.0.0 transitivePeerDependencies: @@ -7903,30 +5318,30 @@ snapshots: babel-plugin-jest-hoist@30.2.0: dependencies: - "@types/babel__core": 7.20.5 + '@types/babel__core': 7.20.5 babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.5): dependencies: - "@babel/core": 7.28.5 - "@babel/plugin-syntax-async-generators": 7.8.4(@babel/core@7.28.5) - "@babel/plugin-syntax-bigint": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-class-properties": 7.12.13(@babel/core@7.28.5) - "@babel/plugin-syntax-class-static-block": 7.14.5(@babel/core@7.28.5) - "@babel/plugin-syntax-import-attributes": 7.27.1(@babel/core@7.28.5) - "@babel/plugin-syntax-import-meta": 7.10.4(@babel/core@7.28.5) - "@babel/plugin-syntax-json-strings": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-logical-assignment-operators": 7.10.4(@babel/core@7.28.5) - "@babel/plugin-syntax-nullish-coalescing-operator": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-numeric-separator": 7.10.4(@babel/core@7.28.5) - "@babel/plugin-syntax-object-rest-spread": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-optional-catch-binding": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-optional-chaining": 7.8.3(@babel/core@7.28.5) - "@babel/plugin-syntax-private-property-in-object": 7.14.5(@babel/core@7.28.5) - "@babel/plugin-syntax-top-level-await": 7.14.5(@babel/core@7.28.5) + '@babel/core': 7.28.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.5) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) babel-preset-jest@30.2.0(@babel/core@7.28.5): dependencies: - "@babel/core": 7.28.5 + '@babel/core': 7.28.5 babel-plugin-jest-hoist: 30.2.0 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) @@ -7991,7 +5406,7 @@ snapshots: cacache@18.0.4: dependencies: - "@npmcli/fs": 3.1.1 + '@npmcli/fs': 3.1.1 fs-minipass: 3.0.3 glob: 10.5.0 lru-cache: 10.4.3 @@ -8360,7 +5775,7 @@ snapshots: dependencies: eslint: 9.39.2 optionalDependencies: - "@typescript-eslint/eslint-plugin": 8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) eslint-scope@8.4.0: dependencies: @@ -8373,18 +5788,18 @@ snapshots: eslint@9.39.2: dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@9.39.2) - "@eslint-community/regexpp": 4.12.2 - "@eslint/config-array": 0.21.1 - "@eslint/config-helpers": 0.4.2 - "@eslint/core": 0.17.0 - "@eslint/eslintrc": 3.3.3 - "@eslint/js": 9.39.2 - "@eslint/plugin-kit": 0.4.1 - "@humanfs/node": 0.16.7 - "@humanwhocodes/module-importer": 1.0.1 - "@humanwhocodes/retry": 0.4.3 - "@types/estree": 1.0.8 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 @@ -8460,8 +5875,8 @@ snapshots: expect@30.2.0: dependencies: - "@jest/expect-utils": 30.2.0 - "@jest/get-type": 30.1.0 + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 jest-matcher-utils: 30.2.0 jest-message-util: 30.2.0 jest-mock: 30.2.0 @@ -8475,8 +5890,8 @@ snapshots: fast-glob@3.3.3: dependencies: - "@nodelib/fs.stat": 2.0.5 - "@nodelib/fs.walk": 1.2.8 + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.8 @@ -8601,7 +6016,7 @@ snapshots: get-pkg-repo@4.2.1: dependencies: - "@hutson/parse-repository-url": 3.0.2 + '@hutson/parse-repository-url': 3.0.2 hosted-git-info: 4.1.0 through2: 2.0.5 yargs: 16.2.0 @@ -8698,7 +6113,7 @@ snapshots: globby@15.0.0: dependencies: - "@sindresorhus/merge-streams": 4.0.0 + '@sindresorhus/merge-streams': 4.0.0 fast-glob: 3.3.3 ignore: 7.0.5 path-type: 6.0.0 @@ -8817,7 +6232,7 @@ snapshots: init-package-json@6.0.3: dependencies: - "@npmcli/package-json": 5.2.0 + '@npmcli/package-json': 5.2.0 npm-package-arg: 11.0.2 promzard: 1.0.2 read: 3.0.1 @@ -8829,7 +6244,7 @@ snapshots: inquirer@8.2.7(@types/node@22.19.1): dependencies: - "@inquirer/external-editor": 1.0.3(@types/node@22.19.1) + '@inquirer/external-editor': 1.0.3(@types/node@22.19.1) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -8845,7 +6260,7 @@ snapshots: through: 2.3.8 wrap-ansi: 6.2.0 transitivePeerDependencies: - - "@types/node" + - '@types/node' ip-address@10.1.0: {} @@ -8924,9 +6339,9 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - "@babel/core": 7.28.5 - "@babel/parser": 7.28.6 - "@istanbuljs/schema": 0.1.3 + '@babel/core': 7.28.5 + '@babel/parser': 7.28.6 + '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.7.3 transitivePeerDependencies: @@ -8940,7 +6355,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/trace-mapping': 0.3.31 debug: 4.4.3 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: @@ -8953,13 +6368,13 @@ snapshots: jackspeak@3.4.3: dependencies: - "@isaacs/cliui": 8.0.2 + '@isaacs/cliui': 8.0.2 optionalDependencies: - "@pkgjs/parseargs": 0.11.0 + '@pkgjs/parseargs': 0.11.0 jackspeak@4.1.1: dependencies: - "@isaacs/cliui": 8.0.2 + '@isaacs/cliui': 8.0.2 jake@10.9.4: dependencies: @@ -8975,11 +6390,11 @@ snapshots: jest-circus@30.2.0: dependencies: - "@jest/environment": 30.2.0 - "@jest/expect": 30.2.0 - "@jest/test-result": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/environment': 30.2.0 + '@jest/expect': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0 @@ -9001,9 +6416,9 @@ snapshots: jest-cli@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: - "@jest/core": 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) - "@jest/test-result": 30.2.0 - "@jest/types": 30.2.0 + '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 @@ -9012,7 +6427,7 @@ snapshots: jest-validate: 30.2.0 yargs: 17.7.2 transitivePeerDependencies: - - "@types/node" + - '@types/node' - babel-plugin-macros - esbuild-register - supports-color @@ -9020,11 +6435,11 @@ snapshots: jest-config@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: - "@babel/core": 7.28.5 - "@jest/get-type": 30.1.0 - "@jest/pattern": 30.0.1 - "@jest/test-sequencer": 30.2.0 - "@jest/types": 30.2.0 + '@babel/core': 7.28.5 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.2.0 + '@jest/types': 30.2.0 babel-jest: 30.2.0(@babel/core@7.28.5) chalk: 4.1.2 ci-info: 4.3.1 @@ -9045,7 +6460,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - "@types/node": 22.19.1 + '@types/node': 22.19.1 ts-node: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros @@ -9060,8 +6475,8 @@ snapshots: jest-diff@30.2.0: dependencies: - "@jest/diff-sequences": 30.0.1 - "@jest/get-type": 30.1.0 + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.1.0 chalk: 4.1.2 pretty-format: 30.2.0 @@ -9071,18 +6486,18 @@ snapshots: jest-each@30.2.0: dependencies: - "@jest/get-type": 30.1.0 - "@jest/types": 30.2.0 + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 chalk: 4.1.2 jest-util: 30.2.0 pretty-format: 30.2.0 jest-environment-node@30.2.0: dependencies: - "@jest/environment": 30.2.0 - "@jest/fake-timers": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 jest-mock: 30.2.0 jest-util: 30.2.0 jest-validate: 30.2.0 @@ -9091,8 +6506,8 @@ snapshots: jest-haste-map@30.2.0: dependencies: - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -9106,21 +6521,21 @@ snapshots: jest-leak-detector@30.2.0: dependencies: - "@jest/get-type": 30.1.0 + '@jest/get-type': 30.1.0 pretty-format: 30.2.0 jest-matcher-utils@30.2.0: dependencies: - "@jest/get-type": 30.1.0 + '@jest/get-type': 30.1.0 chalk: 4.1.2 jest-diff: 30.2.0 pretty-format: 30.2.0 jest-message-util@30.2.0: dependencies: - "@babel/code-frame": 7.27.1 - "@jest/types": 30.2.0 - "@types/stack-utils": 2.0.3 + '@babel/code-frame': 7.27.1 + '@jest/types': 30.2.0 + '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 micromatch: 4.0.8 @@ -9130,8 +6545,8 @@ snapshots: jest-mock@30.2.0: dependencies: - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 jest-util: 30.2.0 jest-pnp-resolver@1.2.3(jest-resolve@30.2.0): @@ -9160,12 +6575,12 @@ snapshots: jest-runner@30.2.0: dependencies: - "@jest/console": 30.2.0 - "@jest/environment": 30.2.0 - "@jest/test-result": 30.2.0 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/console': 30.2.0 + '@jest/environment': 30.2.0 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 chalk: 4.1.2 emittery: 0.13.1 exit-x: 0.2.2 @@ -9187,14 +6602,14 @@ snapshots: jest-runtime@30.2.0: dependencies: - "@jest/environment": 30.2.0 - "@jest/fake-timers": 30.2.0 - "@jest/globals": 30.2.0 - "@jest/source-map": 30.0.1 - "@jest/test-result": 30.2.0 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/globals': 30.2.0 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 chalk: 4.1.2 cjs-module-lexer: 2.1.1 collect-v8-coverage: 1.0.3 @@ -9214,16 +6629,16 @@ snapshots: jest-snapshot@30.2.0: dependencies: - "@babel/core": 7.28.5 - "@babel/generator": 7.28.6 - "@babel/plugin-syntax-jsx": 7.27.1(@babel/core@7.28.5) - "@babel/plugin-syntax-typescript": 7.27.1(@babel/core@7.28.5) - "@babel/types": 7.28.6 - "@jest/expect-utils": 30.2.0 - "@jest/get-type": 30.1.0 - "@jest/snapshot-utils": 30.2.0 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 + '@babel/core': 7.28.5 + '@babel/generator': 7.28.6 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/types': 7.28.6 + '@jest/expect-utils': 30.2.0 + '@jest/get-type': 30.1.0 + '@jest/snapshot-utils': 30.2.0 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) chalk: 4.1.2 expect: 30.2.0 @@ -9240,8 +6655,8 @@ snapshots: jest-util@30.2.0: dependencies: - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 chalk: 4.1.2 ci-info: 4.3.1 graceful-fs: 4.2.11 @@ -9249,8 +6664,8 @@ snapshots: jest-validate@30.2.0: dependencies: - "@jest/get-type": 30.1.0 - "@jest/types": 30.2.0 + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 camelcase: 6.3.0 chalk: 4.1.2 leven: 3.1.0 @@ -9258,9 +6673,9 @@ snapshots: jest-watcher@30.2.0: dependencies: - "@jest/test-result": 30.2.0 - "@jest/types": 30.2.0 - "@types/node": 22.19.1 + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.19.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -9269,20 +6684,20 @@ snapshots: jest-worker@30.2.0: dependencies: - "@types/node": 22.19.1 - "@ungap/structured-clone": 1.3.0 + '@types/node': 22.19.1 + '@ungap/structured-clone': 1.3.0 jest-util: 30.2.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: - "@jest/core": 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) - "@jest/types": 30.2.0 + '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) + '@jest/types': 30.2.0 import-local: 3.2.0 jest-cli: 30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) transitivePeerDependencies: - - "@types/node" + - '@types/node' - babel-plugin-macros - esbuild-register - supports-color @@ -9349,13 +6764,13 @@ snapshots: lerna@8.2.4(@types/node@22.19.1)(encoding@0.1.13): dependencies: - "@lerna/create": 8.2.4(@types/node@22.19.1)(encoding@0.1.13)(typescript@5.9.3) - "@npmcli/arborist": 7.5.4 - "@npmcli/package-json": 5.2.0 - "@npmcli/run-script": 8.1.0 - "@nx/devkit": 20.8.3(nx@20.8.3) - "@octokit/plugin-enterprise-rest": 6.0.1 - "@octokit/rest": 20.1.2 + '@lerna/create': 8.2.4(@types/node@22.19.1)(encoding@0.1.13)(typescript@5.9.3) + '@npmcli/arborist': 7.5.4 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 + '@nx/devkit': 20.8.3(nx@20.8.3) + '@octokit/plugin-enterprise-rest': 6.0.1 + '@octokit/rest': 20.1.2 aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 @@ -9429,9 +6844,9 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 transitivePeerDependencies: - - "@swc-node/register" - - "@swc/core" - - "@types/node" + - '@swc-node/register' + - '@swc/core' + - '@types/node' - babel-plugin-macros - bluebird - debug @@ -9541,7 +6956,7 @@ snapshots: make-fetch-happen@13.0.1: dependencies: - "@npmcli/agent": 2.2.2 + '@npmcli/agent': 2.2.2 cacache: 18.0.4 http-cache-semantics: 4.2.0 is-lambda: 1.0.1 @@ -9570,7 +6985,7 @@ snapshots: meow@8.1.2: dependencies: - "@types/minimist": 1.2.5 + '@types/minimist': 1.2.5 camelcase-keys: 6.2.2 decamelize-keys: 1.1.1 hard-rejection: 2.1.0 @@ -9603,7 +7018,7 @@ snapshots: minimatch@10.1.1: dependencies: - "@isaacs/brace-expansion": 5.0.0 + '@isaacs/brace-expansion': 5.0.0 minimatch@3.0.5: dependencies: @@ -9684,7 +7099,7 @@ snapshots: multimatch@5.0.0: dependencies: - "@types/minimatch": 3.0.5 + '@types/minimatch': 3.0.5 array-differ: 3.0.0 array-union: 2.1.0 arrify: 2.0.1 @@ -9790,7 +7205,7 @@ snapshots: npm-registry-fetch@17.1.0: dependencies: - "@npmcli/redact": 2.0.1 + '@npmcli/redact': 2.0.1 jsonparse: 1.3.1 make-fetch-happen: 13.0.1 minipass: 7.1.2 @@ -9807,10 +7222,10 @@ snapshots: nx@20.8.3: dependencies: - "@napi-rs/wasm-runtime": 0.2.4 - "@yarnpkg/lockfile": 1.1.0 - "@yarnpkg/parsers": 3.0.2 - "@zkochan/js-yaml": 0.0.7 + '@napi-rs/wasm-runtime': 0.2.4 + '@yarnpkg/lockfile': 1.1.0 + '@yarnpkg/parsers': 3.0.2 + '@zkochan/js-yaml': 0.0.7 axios: 1.13.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -9842,16 +7257,16 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - "@nx/nx-darwin-arm64": 20.8.3 - "@nx/nx-darwin-x64": 20.8.3 - "@nx/nx-freebsd-x64": 20.8.3 - "@nx/nx-linux-arm-gnueabihf": 20.8.3 - "@nx/nx-linux-arm64-gnu": 20.8.3 - "@nx/nx-linux-arm64-musl": 20.8.3 - "@nx/nx-linux-x64-gnu": 20.8.3 - "@nx/nx-linux-x64-musl": 20.8.3 - "@nx/nx-win32-arm64-msvc": 20.8.3 - "@nx/nx-win32-x64-msvc": 20.8.3 + '@nx/nx-darwin-arm64': 20.8.3 + '@nx/nx-darwin-x64': 20.8.3 + '@nx/nx-freebsd-x64': 20.8.3 + '@nx/nx-linux-arm-gnueabihf': 20.8.3 + '@nx/nx-linux-arm64-gnu': 20.8.3 + '@nx/nx-linux-arm64-musl': 20.8.3 + '@nx/nx-linux-x64-gnu': 20.8.3 + '@nx/nx-linux-x64-musl': 20.8.3 + '@nx/nx-win32-arm64-msvc': 20.8.3 + '@nx/nx-win32-x64-msvc': 20.8.3 transitivePeerDependencies: - debug @@ -9970,11 +7385,11 @@ snapshots: pacote@18.0.6: dependencies: - "@npmcli/git": 5.0.8 - "@npmcli/installed-package-contents": 2.1.0 - "@npmcli/package-json": 5.2.0 - "@npmcli/promise-spawn": 7.0.2 - "@npmcli/run-script": 8.1.0 + '@npmcli/git': 5.0.8 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/promise-spawn': 7.0.2 + '@npmcli/run-script': 8.1.0 cacache: 18.0.4 fs-minipass: 3.0.3 minipass: 7.1.2 @@ -10008,7 +7423,7 @@ snapshots: parse-json@5.2.0: dependencies: - "@babel/code-frame": 7.27.1 + '@babel/code-frame': 7.27.1 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -10082,13 +7497,13 @@ snapshots: pretty-format@29.7.0: dependencies: - "@jest/schemas": 29.6.3 + '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 react-is: 18.3.1 pretty-format@30.2.0: dependencies: - "@jest/schemas": 30.0.5 + '@jest/schemas': 30.0.5 ansi-styles: 5.2.0 react-is: 18.3.1 @@ -10153,7 +7568,7 @@ snapshots: read-pkg@5.2.0: dependencies: - "@types/normalize-package-data": 2.4.4 + '@types/normalize-package-data': 2.4.4 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 @@ -10268,12 +7683,12 @@ snapshots: sigstore@2.3.1: dependencies: - "@sigstore/bundle": 2.3.2 - "@sigstore/core": 1.1.0 - "@sigstore/protobuf-specs": 0.3.3 - "@sigstore/sign": 2.3.2 - "@sigstore/tuf": 2.3.4 - "@sigstore/verify": 1.2.1 + '@sigstore/bundle': 2.3.2 + '@sigstore/core': 1.1.0 + '@sigstore/protobuf-specs': 0.3.3 + '@sigstore/sign': 2.3.2 + '@sigstore/tuf': 2.3.4 + '@sigstore/verify': 1.2.1 transitivePeerDependencies: - supports-color @@ -10398,11 +7813,11 @@ snapshots: synckit@0.11.11: dependencies: - "@pkgr/core": 0.2.9 + '@pkgr/core': 0.2.9 synckit@0.11.12: dependencies: - "@pkgr/core": 0.2.9 + '@pkgr/core': 0.2.9 tar-stream@2.2.0: dependencies: @@ -10425,7 +7840,7 @@ snapshots: test-exclude@6.0.0: dependencies: - "@istanbuljs/schema": 0.1.3 + '@istanbuljs/schema': 0.1.3 glob: 7.2.3 minimatch: 3.1.2 @@ -10480,20 +7895,20 @@ snapshots: typescript: 5.9.3 yargs-parser: 21.1.1 optionalDependencies: - "@babel/core": 7.28.5 - "@jest/transform": 30.2.0 - "@jest/types": 30.2.0 + '@babel/core': 7.28.5 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 babel-jest: 30.2.0(@babel/core@7.28.5) jest-util: 30.2.0 ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3): dependencies: - "@cspotcode/source-map-support": 0.8.1 - "@tsconfig/node10": 1.0.12 - "@tsconfig/node12": 1.0.11 - "@tsconfig/node14": 1.0.3 - "@tsconfig/node16": 1.0.4 - "@types/node": 22.19.1 + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.19.1 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -10514,7 +7929,7 @@ snapshots: tuf-js@2.2.1: dependencies: - "@tufjs/models": 2.0.1 + '@tufjs/models': 2.0.1 debug: 4.4.3 make-fetch-happen: 13.0.1 transitivePeerDependencies: @@ -10565,25 +7980,25 @@ snapshots: dependencies: napi-postinstall: 0.3.4 optionalDependencies: - "@unrs/resolver-binding-android-arm-eabi": 1.11.1 - "@unrs/resolver-binding-android-arm64": 1.11.1 - "@unrs/resolver-binding-darwin-arm64": 1.11.1 - "@unrs/resolver-binding-darwin-x64": 1.11.1 - "@unrs/resolver-binding-freebsd-x64": 1.11.1 - "@unrs/resolver-binding-linux-arm-gnueabihf": 1.11.1 - "@unrs/resolver-binding-linux-arm-musleabihf": 1.11.1 - "@unrs/resolver-binding-linux-arm64-gnu": 1.11.1 - "@unrs/resolver-binding-linux-arm64-musl": 1.11.1 - "@unrs/resolver-binding-linux-ppc64-gnu": 1.11.1 - "@unrs/resolver-binding-linux-riscv64-gnu": 1.11.1 - "@unrs/resolver-binding-linux-riscv64-musl": 1.11.1 - "@unrs/resolver-binding-linux-s390x-gnu": 1.11.1 - "@unrs/resolver-binding-linux-x64-gnu": 1.11.1 - "@unrs/resolver-binding-linux-x64-musl": 1.11.1 - "@unrs/resolver-binding-wasm32-wasi": 1.11.1 - "@unrs/resolver-binding-win32-arm64-msvc": 1.11.1 - "@unrs/resolver-binding-win32-ia32-msvc": 1.11.1 - "@unrs/resolver-binding-win32-x64-msvc": 1.11.1 + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 untildify@4.0.0: {} @@ -10607,8 +8022,8 @@ snapshots: v8-to-istanbul@9.3.0: dependencies: - "@jridgewell/trace-mapping": 0.3.31 - "@types/istanbul-lib-coverage": 2.0.6 + '@jridgewell/trace-mapping': 0.3.31 + '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 validate-npm-package-license@3.0.4: