diff --git a/skills/commit-workflow/SKILL.md b/.agents/skills/commit-workflow/SKILL.md similarity index 100% rename from skills/commit-workflow/SKILL.md rename to .agents/skills/commit-workflow/SKILL.md diff --git a/skills/coverage-recovery/SKILL.md b/.agents/skills/coverage-recovery/SKILL.md similarity index 98% rename from skills/coverage-recovery/SKILL.md rename to .agents/skills/coverage-recovery/SKILL.md index 9130be1..926f9fe 100644 --- a/skills/coverage-recovery/SKILL.md +++ b/.agents/skills/coverage-recovery/SKILL.md @@ -28,7 +28,7 @@ Use this skill when the user asks to: ## Workflow 1. Collect facts: ```bash -yarn test:coverage +yarn test ``` 2. Read uncovered details, not only percentages. Use: @@ -48,7 +48,7 @@ Use: ```bash yarn lint yarn typecheck -yarn test:coverage +yarn test ``` ## Controlled Failure Patterns diff --git a/skills/yarn-lock-conflict-resolution/SKILL.md b/.agents/skills/yarn-lock-conflict-resolution/SKILL.md similarity index 100% rename from skills/yarn-lock-conflict-resolution/SKILL.md rename to .agents/skills/yarn-lock-conflict-resolution/SKILL.md diff --git a/.github/actions/setup-node-deps/action.yml b/.github/actions/setup-node-deps/action.yml index d12fa61..d40a7b3 100644 --- a/.github/actions/setup-node-deps/action.yml +++ b/.github/actions/setup-node-deps/action.yml @@ -18,9 +18,13 @@ inputs: runs: using: composite steps: + - name: Enable Corepack + shell: bash + run: corepack enable + - name: Setup Node.js if: ${{ inputs.registry-url == '' }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ inputs.node-version }} cache: yarn @@ -28,7 +32,7 @@ runs: - name: Setup Node.js with registry if: ${{ inputs.registry-url != '' }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ inputs.node-version }} registry-url: ${{ inputs.registry-url }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a8c2365..c229807 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,9 +4,9 @@ on: workflow_dispatch: inputs: release: - description: "Release type" + description: Release type required: true - default: "auto" + default: auto type: choice options: - auto @@ -14,9 +14,9 @@ on: - minor - major prerelease: - description: "Prerelease channel" + description: Prerelease channel required: true - default: "none" + default: none type: choice options: - none @@ -24,43 +24,69 @@ on: - beta - rc npm_tag: - description: "npm dist-tag for publication" + description: npm dist-tag (auto selects latest or the prerelease channel) required: true - default: "latest" + default: auto type: string permissions: - contents: write - id-token: write + contents: read concurrency: - group: release-${{ github.ref }} + group: release cancel-in-progress: false jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 + timeout-minutes: 15 + permissions: + contents: write + outputs: + tag: ${{ steps.version.outputs.tag }} + npm_tag: ${{ steps.validate.outputs.npm_tag }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Validate release branch and npm tag + id: validate env: NPM_TAG: ${{ inputs.npm_tag }} + PRERELEASE: ${{ inputs.prerelease }} run: | - if [ "$NPM_TAG" = "latest" ] && [ "$GITHUB_REF" != "refs/heads/main" ]; then - echo "Release to npm tag 'latest' must be started from the main branch." + if [ "$GITHUB_REF_TYPE" != branch ]; then + echo "Release must run from a branch." + exit 1 + fi + if [ "$PRERELEASE" = none ] && [ "$GITHUB_REF_NAME" != main ]; then + echo "Stable releases must run from main." + exit 1 + fi + if [ "$NPM_TAG" = auto ]; then + if [ "$PRERELEASE" = none ]; then + NPM_TAG=latest + else + NPM_TAG="$PRERELEASE" + fi + fi + if [[ ! "$NPM_TAG" =~ ^[a-z][a-z0-9._-]*$ ]]; then + echo "Invalid npm dist-tag: $NPM_TAG" exit 1 fi + if [ "$PRERELEASE" != none ] && [ "$NPM_TAG" = latest ]; then + echo "Prereleases cannot be published to latest." + exit 1 + fi + echo "npm_tag=$NPM_TAG" >> "$GITHUB_OUTPUT" - name: Setup Node.js and dependencies uses: ./.github/actions/setup-node-deps with: node-version: 24.x - registry-url: https://registry.npmjs.org - name: Configure git user run: | @@ -72,45 +98,105 @@ jobs: yarn lint yarn typecheck yarn test + yarn test:d + yarn test:package - - name: Run release script + - name: Create release commit and tag + id: version env: RELEASE_TYPE: ${{ inputs.release }} PRERELEASE: ${{ inputs.prerelease }} + YARN_ENABLE_IMMUTABLE_INSTALLS: 'false' run: | - case "$RELEASE_TYPE" in - auto) - RELEASE_SCRIPT="release" - ;; - patch) - RELEASE_SCRIPT="release:patch" - ;; - minor) - RELEASE_SCRIPT="release:minor" - ;; - major) - RELEASE_SCRIPT="release:major" - ;; - *) - echo "Unknown release type: $RELEASE_TYPE" - exit 1 - ;; - esac - - CMD=(yarn run "$RELEASE_SCRIPT") - if [ "$PRERELEASE" != "none" ]; then + PREVIOUS_VERSION=$(node -p "require('./package.json').version") + CMD=(yarn release) + if [ "$RELEASE_TYPE" != auto ]; then + CMD+=(--release-as "$RELEASE_TYPE") + fi + if [ "$PRERELEASE" != none ]; then CMD+=(--prerelease "$PRERELEASE") fi - "${CMD[@]}" - - name: Build package - run: yarn build + VERSION=$(node -p "require('./package.json').version") + if [ "$VERSION" = "$PREVIOUS_VERSION" ]; then + echo "No new release was created." + exit 1 + fi + TAG="v$VERSION" + test "$(git rev-parse "refs/tags/$TAG^{commit}")" = "$(git rev-parse HEAD)" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: Push release commit and tag + run: git push --atomic origin "HEAD:$GITHUB_REF_NAME" "refs/tags/${{ steps.version.outputs.tag }}" + + publish: + needs: release + runs-on: ubuntu-24.04 + timeout-minutes: 15 + permissions: + contents: read + id-token: write + + steps: + - name: Checkout release tag + uses: actions/checkout@v6 + with: + ref: refs/tags/${{ needs.release.outputs.tag }} + persist-credentials: false + + - name: Setup Node.js and dependencies + uses: ./.github/actions/setup-node-deps + with: + node-version: 24.x + registry-url: https://registry.npmjs.org + + - name: Verify npm supports trusted publishing + run: | + node -e "const [major, minor, patch] = process.argv[1].split('.').map(Number); if (major < 11 || (major === 11 && (minor < 5 || (minor === 5 && patch < 1)))) process.exit(1)" "$(npm --version)" - - name: Push release commit and tags - run: git push origin "HEAD:${GITHUB_REF_NAME}" --follow-tags + - name: Check released package + run: | + yarn lint + yarn typecheck + yarn test + yarn test:d + yarn test:package + + - name: Check published version + id: published + run: | + NAME=$(node -p "require('./package.json').name") + VERSION=$(node -p "require('./package.json').version") + npm view "$NAME" versions --json > "$RUNNER_TEMP/published-versions.json" + PUBLISHED=$(node -e "const fs = require('node:fs'); const versions = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); console.log([].concat(versions).includes(process.argv[2]))" "$RUNNER_TEMP/published-versions.json" "$VERSION") + echo "published=$PUBLISHED" >> "$GITHUB_OUTPUT" - - name: Publish to npm + - name: Publish to npm with trusted publishing + if: steps.published.outputs.published == 'false' env: - NPM_TAG: ${{ inputs.npm_tag }} - run: npm publish --access public --tag "$NPM_TAG" + NPM_TAG: ${{ needs.release.outputs.npm_tag }} + run: | + unset NODE_AUTH_TOKEN NPM_TOKEN + npm publish --access public --tag "$NPM_TAG" + + github-release: + needs: [release, publish] + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - name: Create GitHub Release + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ needs.release.outputs.tag }} + PRERELEASE: ${{ inputs.prerelease }} + run: | + if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" > /dev/null 2>&1; then + exit 0 + fi + CMD=(gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag --generate-notes --title "$TAG") + if [ "$PRERELEASE" != none ]; then + CMD+=(--prerelease --latest=false) + fi + "${CMD[@]}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7fc541d..ad9f341 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Using branch ${{ github.ref }} for repository ${{ github.repository }}. - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Run actionlint run: make actionlint @@ -30,7 +30,7 @@ jobs: steps: - name: Using branch ${{ github.ref }} for repository ${{ github.repository }}. - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node.js and dependencies uses: ./.github/actions/setup-node-deps @@ -51,21 +51,27 @@ jobs: steps: - name: Using branch ${{ github.ref }} for repository ${{ github.repository }}. - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node.js and dependencies uses: ./.github/actions/setup-node-deps with: node-version: ${{ matrix.node-version }} + - name: Check TypeScript + run: yarn typecheck + - name: Run tests - run: yarn test:coverage + run: yarn test - name: Run type tests run: yarn test:d + - name: Check packed package consumers + run: yarn test:package + - name: Upload coverage to GitHub Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: coverage-${{ matrix.node-version }} path: coverage/ diff --git a/.versionrc.json b/.versionrc.json deleted file mode 100644 index e2dffca..0000000 --- a/.versionrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "types": [ - {"type": "feat", "section": "Features"}, - {"type": "fix", "section": "Fixes"}, - {"type": "chore", "hidden": true}, - {"type": "docs", "hidden": true}, - {"type": "style", "hidden": true}, - {"type": "refactor", "hidden": true}, - {"type": "perf", "hidden": true}, - {"type": "test", "hidden": true} - ] -} diff --git a/.yarnrc.yml b/.yarnrc.yml index 7b11830..5ef5b89 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -3,3 +3,14 @@ enableGlobalCache: false nodeLinker: node-modules yarnPath: .yarn/releases/yarn-4.12.0.cjs + +# The TypeScript config loader needs peers forwarded through @commitlint/load. +packageExtensions: + "@commitlint/load@21.2.3": + peerDependencies: + "@types/node": "*" + typescript: ">=5" + "@commitlint/cli@21.2.3": + peerDependencies: + "@types/node": "*" + typescript: ">=5" diff --git a/AGENTS.md b/AGENTS.md index 39eb7fc..ad79e96 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,14 +50,10 @@ yarn lint ```bash yarn typecheck ``` -- Test: +- Test (coverage is enabled by default; reports are written to `coverage/`): ```bash yarn test ``` -- Coverage: -```bash -yarn test:coverage -``` - Build: ```bash yarn build @@ -73,10 +69,10 @@ yarn build ## Important Project Rules - Commit messages follow Conventional Commits. -- Before creating any commit, always reread `skills/commit-workflow/SKILL.md` and follow it as the source of truth for commit splitting, wording, scopes, and lockfile policy. +- Before creating any commit, always reread `.agents/skills/commit-workflow/SKILL.md` and follow it as the source of truth for commit splitting, wording, scopes, and lockfile policy. - Getter/helper functions must be free of side effects. Side effects are allowed only by prior agreement and only when there are strong, explicit reasons. ## Local Skills -- `skills/commit-workflow/SKILL.md` - rules for splitting changes into commits and writing changelog-friendly Conventional Commit messages. -- `skills/coverage-recovery/SKILL.md` - workflow for analyzing uncovered code paths and improving test coverage without adding artificial tests. -- `skills/yarn-lock-conflict-resolution/SKILL.md` - safe procedure for resolving `yarn.lock` conflicts during merge or rebase. +- `.agents/skills/commit-workflow/SKILL.md` - rules for splitting changes into commits and writing changelog-friendly Conventional Commit messages. +- `.agents/skills/coverage-recovery/SKILL.md` - workflow for analyzing uncovered code paths and improving test coverage without adding artificial tests. +- `.agents/skills/yarn-lock-conflict-resolution/SKILL.md` - safe procedure for resolving `yarn.lock` conflicts during merge or rebase. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dafbb6..33aaf98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +All notable changes to this project will be documented in this file. Release notes are generated by [@modulify/conventional-release](https://github.com/modulify/conventional/tree/main/packages/conventional-release) from Conventional Commits. ### [0.2.1](https://github.com/modulify/validator/compare/v0.2.0...v0.2.1) (2026-03-09) diff --git a/Makefile b/Makefile index bae922a..b9d14ec 100644 --- a/Makefile +++ b/Makefile @@ -32,11 +32,6 @@ test: node_modules ## Runs autotests $(TARGET_HEADER) $(YARN) test -.PHONY: test-coverage -test-coverage: node_modules ## Runs autotests with --coverage - $(TARGET_HEADER) - $(YARN) test:coverage - .PHONY: release release: ## Bumps version and creates tag $(TARGET_HEADER) diff --git a/README.md b/README.md index b16c9ea..f191d71 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ if (ok) { ## Shape API -`shape(...)` is the reusable object-shape API. It validates nested record-like objects and exposes small immutable helpers such as `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, `refine()`, and `fieldsMatch(...)`. +`shape(...)` is the reusable object-shape API. It validates nested record-like objects and exposes small immutable helpers such as `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, async-first `refine()`, explicit `refine.sync()`, and `fieldsMatch(...)`. ```typescript import { @@ -270,11 +270,17 @@ A practical way to think about the library is: In the current API this usually looks like: -- leaf checks with assertions such as `isString`, `isDefined`, `hasLength`, `oneOf`; +- guard assertions such as `isString`, `isNumber`, `isDefined`, `oneOf(...)` establish the base domain for a value; +- refinement assertions such as `hasLength(...)`, `hasPattern(...)`, `startsWith(...)`, `hasValue(...)`, `multipleOf(...)` validate properties inside that domain; - schema composition with combinators such as `exact`, `optional`, `nullable`, `nullish`, `shape(...)`, `each(...)`; - typed validation through `validate(...)` or `validate.sync(...)`; - narrowing of the original sync variable through `matches.sync(...)`. +Sequential assertion arrays are stage-aware. A tuple like `[isString, hasLength({ min: 3 })]` is valid, while incompatible combinations like `[isNumber, hasLength({ min: 3 })]` are rejected by TypeScript. +Refinement assertions are not meant to be passed to `validate(...)` or `matches.sync(...)` on their own. + +`validate(...)` is the default async-first validation entrypoint. `validate.sync(...)` and `matches.sync(...)` are specialized sync APIs and will throw if they encounter async validators or async object-level `shape(...).refine(...)` rules. + ## Violations `validate(...)` returns machine-readable `Violation[]`, and `collection(...)` can wrap that list into a small helper API for exact path lookups and tree traversal. @@ -354,6 +360,8 @@ Two additional guides are useful when you want faster practical navigation inste - [Common Recipes](./docs/en/06-common-recipes.md) - task-oriented examples for payload validation, wrapper choice, reusable shapes, form error mapping, and JSON Schema export. - [AI Reference](./docs/en/07-ai-reference.md) - compact contract summary for agents, tooling, and quick semantic lookup. +- [Migration From 0.2.1](./docs/en/09-migration.md) + ## Notes - Assertions return structured metadata instead of messages. @@ -366,3 +374,5 @@ Two additional guides are useful when you want faster practical navigation inste ## Translations - [Russian](./docs/ru/README.md) + +Release workflow and npm OIDC setup: [Releasing](docs/RELEASING.md). diff --git a/docs/RELEASING.md b/docs/RELEASING.md new file mode 100644 index 0000000..9c2d03f --- /dev/null +++ b/docs/RELEASING.md @@ -0,0 +1,66 @@ +# Releasing @modulify/validator + +Use Node.js 22.14+ or 24+ and the Yarn version pinned in `package.json`. +Install dependencies with `yarn install --immutable`. + +The repository uses `@modulify/conventional-release` to calculate the version, +update `package.json` and `CHANGELOG.md`, and create a release commit with an +annotated `v` tag. npm publication and GitHub Releases belong to CI. + +Preview a release without changing files, commits, or tags: + +```sh +yarn release:dry +yarn release:dry --prerelease rc +yarn release:dry --release-as minor +``` + +Automatic version recommendations below 1.0 follow pre-major semantics: +breaking changes advance the minor version; features and fixes advance the patch. +Explicit `--release-as major` produces 1.0.0. Release configuration lives in +`release.config.mjs`; dependencies are installed before releasing, so the version +bump does not rerun installation or update the lockfile. + +## GitHub Actions + +Start the `Release` workflow manually: + +- `release`: `auto`, `patch`, `minor`, or `major`; +- `prerelease`: `none`, `alpha`, `beta`, or `rc`; +- `npm_tag`: `auto` selects `latest` for stable releases and the prerelease channel + otherwise; an explicit dist-tag can override it. + +Stable releases run only from `main`. Prereleases may run from other branches, +but cannot publish to `latest`. Releases are serialized across branches. + +CI runs lint, strict type checks, runtime and type tests, and packed consumer +checks before creating the release. It atomically pushes the release commit and +its tag. A separate job checks out that exact tag, repeats the checks, builds the +package, and publishes through npm OIDC. A GitHub Release is created after npm +publication succeeds; prereleases are marked accordingly. + +If publication or GitHub Release creation fails after the tag was pushed, use +GitHub Actions **Re-run failed jobs** on the original run. Publication checks the +registry for the exact version and skips a version already published. Registry +lookup errors stop the job. Starting a new workflow run prepares another release. + +## npm Trusted Publisher + +The package already has this trusted publisher configured (verified 2026-09-26): + +| Field | Value | +| --- | --- | +| Provider | GitHub Actions | +| Organization | `modulify` | +| Repository | `validator` | +| Workflow filename | `release.yml` | +| Allowed actions | `npm publish`, `npm stage publish` | + +Keep the workflow filename aligned with this package-level configuration. +The publishing job uses a GitHub-hosted runner, Node.js 24, npm 11.5.1 or newer, +and `id-token: write`. No `NPM_TOKEN` or `NODE_AUTH_TOKEN` secret is used for +publication. npm generates provenance automatically for this public package +and repository. See [npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers/). + +A local authenticated npm session is separate from CI OIDC. Release previews +and repository-local versioning do not require npm authentication. diff --git a/docs/en/00-index.md b/docs/en/00-index.md index 7b3eb21..da6d042 100644 --- a/docs/en/00-index.md +++ b/docs/en/00-index.md @@ -9,6 +9,8 @@ - [AI Reference](./07-ai-reference.md) - Compact contract summary for AI agents, tooling, and quick lookup of stable library semantics. - [Violation Code Types](./08-violation-code-types.md) - Detailed guide to `ViolationCodeRegistry`, `ViolationCode`, literal code preservation in descriptors, and external registry augmentation. +- [Migration From 0.2.1](./09-migration.md) - Breaking changes, renamed types, and updated validation contracts. + ## Translations - [Russian](../ru/00-index.md) diff --git a/docs/en/01-shape-api.md b/docs/en/01-shape-api.md index 0905269..2deab34 100644 --- a/docs/en/01-shape-api.md +++ b/docs/en/01-shape-api.md @@ -49,6 +49,8 @@ Each field in the descriptor may contain: - an array of constraints that run sequentially; - another structural validator such as `shape(...)`, `each(...)`, `tuple(...)`, `record(...)`, `union(...)`, or `discriminatedUnion(...)`. +For assertion arrays, sequencing is stage-aware: guard assertions establish the field domain first, and refinement assertions must be compatible with that domain. + That means object validation stays aligned with the rest of the library: - field-level checks reuse the same assertions and combinators; @@ -79,6 +81,11 @@ Runtime behavior: - nested violations are reported on the field path; - unknown keys are allowed by default. +Type-level behavior: + +- `[isString, hasLength({ min: 8 })]` is valid; +- `[isNumber, hasLength({ min: 8 })]` is rejected by TypeScript before runtime. + ## Unknown Keys Shapes have two unknown-key modes: @@ -190,13 +197,36 @@ Shapes can express cross-field invariants without introducing a second schema la ### `refine(...)` -`refine(...)` adds a synchronous object-level rule that runs only after the base shape has already validated successfully as an object. +`refine(...)` adds an async-first object-level rule that runs only after the base shape has already validated successfully as an object. + +```typescript +const registration = shape({ + email: isString, +}).refine(async value => { + const taken = await users.has(value.email) + + return taken + ? [{ path: ['email'], code: 'user.email.taken' }] + : [] +}) +``` + +`refine(...)` is intentionally thin: + +- it accepts sync or async callbacks; +- it returns `[]`, `null`, or `undefined` when the rule passes; +- it returns one issue or an array of issues when it fails; +- `path` is relative to the current shape and defaults to `[]`; +- `value` is optional and defaults to the object value at that relative path; +- `code` stays machine-readable. + +If you need an explicitly sync-safe object rule for `validate.sync(...)`, use `refine.sync(...)`: ```typescript const registration = shape({ password: isString, confirmPassword: isString, -}).refine(value => { +}).refine.sync(value => { return value.password === value.confirmPassword ? [] : [{ @@ -207,14 +237,7 @@ const registration = shape({ }) ``` -`refine(...)` is intentionally thin: - -- it is sync-only; -- it returns `[]`, `null`, or `undefined` when the rule passes; -- it returns one issue or an array of issues when it fails; -- `path` is relative to the current shape and defaults to `[]`; -- `value` is optional and defaults to the object value at that relative path; -- `code` stays machine-readable. +`validate.sync(...)`, `matches.sync(...)`, and `shape.check(...)` throw explicitly if they encounter an async `refine(...)` callback. Produced violations use: @@ -243,6 +266,8 @@ const registration = shape({ This shows up later in `describe(...)` under the shape `rules` array. +Rules registered through async-first `refine(...)` are marked with `async: true` in that descriptor array. + ### `fieldsMatch(...)` `fieldsMatch(...)` is a small helper for the common confirmation-field case. diff --git a/docs/en/02-metadata-and-introspection.md b/docs/en/02-metadata-and-introspection.md index 18a1a49..4c274c6 100644 --- a/docs/en/02-metadata-and-introspection.md +++ b/docs/en/02-metadata-and-introspection.md @@ -182,7 +182,8 @@ Instead, shapes keep lightweight rule descriptors in `rules`. Built-in examples: - `fieldsMatch(...)` produces a compact `fieldsMatch` rule descriptor; -- `refine(...)` can accept a custom compact rule descriptor object. +- `refine(...)` can accept a custom compact rule descriptor object; +- async-first `refine(...)` rules are marked with `async: true`. This keeps the public descriptor tree stable and serializable enough for tooling, while avoiding the impossible task of serializing arbitrary callbacks. diff --git a/docs/en/03-violations.md b/docs/en/03-violations.md index ea9dd77..223c761 100644 --- a/docs/en/03-violations.md +++ b/docs/en/03-violations.md @@ -120,7 +120,7 @@ This is one of the reasons the library can stay adapter-friendly without stringi `validate(...)` and `validate.sync(...)` return: ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` diff --git a/docs/en/04-json-schema-export.md b/docs/en/04-json-schema-export.md index 97137a1..0ccdf02 100644 --- a/docs/en/04-json-schema-export.md +++ b/docs/en/04-json-schema-export.md @@ -69,6 +69,9 @@ Supported practical mappings include: - `isString` -> `type: 'string'` - `isNumber` -> `type: 'number'` +- `isFiniteNumber` -> `type: 'number'` +- `isInteger` -> `type: 'integer'` +- `isSafeInteger` -> `type: 'integer'`, `minimum: Number.MIN_SAFE_INTEGER`, `maximum: Number.MAX_SAFE_INTEGER` - `isBoolean` -> `type: 'boolean'` - `isNull` -> `type: 'null'` - `isEmail` -> `type: 'string'` plus `format: 'email'` @@ -202,6 +205,8 @@ Important examples: The exporter keeps these boundaries explicit instead of guessing. +`isValidDate`, `isError`, `isRegExp`, and `isPromiseLike` describe runtime values without a faithful JSON Schema representation. Strict mode throws `JsonSchemaExportError`; best-effort mode emits an unconstrained node. JSON numeric values are finite, so `isFiniteNumber` needs no additional schema keyword. + ## Relationship To `describe(...)` `toJsonSchema(...)` is downstream from `describe(...)`. diff --git a/docs/en/05-public-api.md b/docs/en/05-public-api.md index 05113f9..51fa069 100644 --- a/docs/en/05-public-api.md +++ b/docs/en/05-public-api.md @@ -19,6 +19,8 @@ The root package exports: - `validate` - `validate.sync` - `matches.sync` +- `Guard` +- `Refinement` - `meta` - `describe` - `custom` @@ -33,8 +35,9 @@ Use the root package when you need the main validation API, composed validators, The root package includes: -- low-level assertion construction through `assert(...)` -- built-in assertions such as `isString`, `isNumber`, `isBoolean`, `isNull`, `isEmail`, `hasLength(...)`, `oneOf(...)` +- low-level assertion construction through `assert(...)` and `refine(...)` +- built-in guard assertions such as `isString`, `isNumber`, `isBoolean`, `isNull`, `isEmail`, `oneOf(...)` +- built-in refinement assertions such as `hasLength(...)`, `hasSize(...)`, `hasPattern(...)`, `startsWith(...)`, `hasValue(...)`, `multipleOf(...)` - structural combinators such as `shape(...)`, `each(...)`, `tuple(...)`, `record(...)` - wrapper combinators such as `optional(...)`, `nullable(...)`, `nullish(...)` - branching combinators such as `union(...)` and `discriminatedUnion(...)` @@ -42,6 +45,27 @@ The root package includes: This is the main runtime-facing API surface of the library. +Sequential assertion arrays are stage-aware: a compatible tuple such as `[isString, hasLength({ min: 3 })]` is supported directly, while incompatible combinations are rejected by the type system. +Refinement assertions are staged helpers, so `validate(...)` and `matches.sync(...)` expect them to appear after a compatible guard instead of being passed on their own. + +Structural validators such as `each(...)` reset the assertion stage. Use a new compatible guard before subsequent refinements, for example `[each(isString), isDefined, hasLength({ min: 2 })]`. + +### Built-in value guards + +These checks are available as assertions from the root and `./assertions`, and as boolean type guards from `./predicates`. + +| Check | Accepted values | Violation code | +| --- | --- | --- | +| `isFiniteNumber` | Numbers excluding `NaN` and infinities | `number.finite` | +| `isInteger` | Integer numbers | `number.integer` | +| `isSafeInteger` | Integers within JavaScript's safe integer bounds | `number.safe-integer` | +| `isValidDate` | `Date` instances with a valid timestamp | `date.valid` | +| `isError` | `Error` instances, including subclasses | `type.error` | +| `isRegExp` | `RegExp` instances | `type.regexp` | +| `isPromiseLike` | Objects or functions with a callable `then` property | `type.promise-like` | + +`isNumber` still accepts infinities; `isDate` still accepts invalid `Date` instances. Use the stricter checks when those values must be rejected. `isPromiseLike` checks the presence of a callable `then`, without executing it or inspecting the resolved value. + ## Metadata And Introspection The same root package also includes: @@ -67,7 +91,7 @@ These are the main utilities for post-processing machine-readable validation fai `validate(...)` and `validate.sync(...)` return: ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` @@ -77,6 +101,8 @@ Practical meaning: - `ok` tells whether validation succeeded; - `validated` becomes strongly typed only in the success branch; - `violations` is empty on success and contains structured failures on error. +- `validate(...)` is the default async-first entrypoint; +- `validate.sync(...)` throws explicitly when it encounters async validators or async object-level `shape(...).refine(...)` rules. ## Predicates Subpath @@ -97,6 +123,12 @@ This subpath contains reusable runtime/type-guard helpers and predicate combinat Use this subpath when you want guard-style runtime checks without pulling in the higher-level validation layer. +In `isShape({ name: [isString, false] })`, an optional field may be absent, +but a present value is always checked by its predicate. This includes explicit +`undefined`: use `Or(isString, isUndefined)` to allow it. +The shorthand `name: isString` and the tuple `[isString, true]` define required fields. +Field presence is checked with `in`, including properties in the prototype chain. + ## JSON Schema Export Subpath JSON Schema export is available from: diff --git a/docs/en/06-common-recipes.md b/docs/en/06-common-recipes.md index 6743370..616436d 100644 --- a/docs/en/06-common-recipes.md +++ b/docs/en/06-common-recipes.md @@ -14,7 +14,7 @@ It is intentionally recipe-oriented. Use it when you already understand the proj Use this quick rule of thumb: - use `@modulify/validator/predicates` when you only need runtime checks and type guards; -- use built-in assertions such as `isString`, `isDefined`, `hasLength(...)`, `oneOf(...)` when you want machine-readable failures; +- use built-in guard/refinement assertions such as `isString`, `isDefined`, `hasLength(...)`, `oneOf(...)` when you want machine-readable failures; - use combinators such as `shape(...)`, `each(...)`, `tuple(...)`, `record(...)`, `union(...)`, `discriminatedUnion(...)` when validation becomes structural; - use `meta(...)` and `describe(...)` when another layer needs stable machine-readable descriptors; - use `toJsonSchema(...)` only when you need an interoperability/export view, not as the source of runtime truth. @@ -44,6 +44,7 @@ Practical pattern: - use `.strict()` for request payloads when unknown keys should be rejected; - keep leaf checks small and composable; +- when you use an assertion array, start with a compatible guard such as `isString` before string refinements like `hasLength(...)`; - use the `validated` tuple item inside the success branch; - use `violations` as structured data for API responses, logs, or UI mapping. diff --git a/docs/en/07-ai-reference.md b/docs/en/07-ai-reference.md index 862811e..61c04b5 100644 --- a/docs/en/07-ai-reference.md +++ b/docs/en/07-ai-reference.md @@ -43,7 +43,7 @@ Use `@modulify/validator/json-schema` for: ## Validation Result Contract ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` @@ -53,7 +53,8 @@ Important consequences: - `validate(...)` narrows the `validated` tuple item in the success branch; - `validate(...)` does not narrow the original input variable; - `matches.sync(...)` is the API that narrows the original variable; -- `violations` is always empty on success. +- `violations` is always empty on success; +- `validate(...)` is async-first, while `validate.sync(...)` and `matches.sync(...)` are specialized sync APIs. ## Wrapper Semantics @@ -90,6 +91,8 @@ Important rule: - structural derivations intentionally drop object-level rules; - mode switches intentionally keep object-level rules. +- `.refine(...)` is async-first and may return a promise; +- `.refine.sync(...)` is the explicitly sync-safe object-level rule API. ## Violations Contract diff --git a/docs/en/08-violation-code-types.md b/docs/en/08-violation-code-types.md index eb6dfe8..c1617f0 100644 --- a/docs/en/08-violation-code-types.md +++ b/docs/en/08-violation-code-types.md @@ -58,6 +58,32 @@ In TypeScript this means: This is useful when adapters inspect descriptors and want code-aware branching without hand-written casts. +The same precision now flows into `validate(...)` for parameterized built-ins. + +```typescript +import { + collection, + hasLength, + isString, + validate, +} from '@modulify/validator' + +const [ok, , violations] = validate.sync('ab', [isString, hasLength({ min: 3 })]) + +if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.string': + return violation.violates.name + case 'length.min': + return violation.violates.args[0] + } + }) +} +``` + +For staged calls like `[isString, hasLength({ min: 3 })]`, impossible branches such as `'length.max'` or `'length.range'` are no longer carried into the violation union, and the unsupported-type branch stays on the descriptor side instead of leaking into staged validation. + ## What The Global Registry Solves Exact literals on individual values are good for local introspection. @@ -158,7 +184,7 @@ This part does not depend on the global union extraction. The literal is preserv The same idea applies to object-level refinement issues. ```typescript -import type { ObjectShapeRefinementIssue } from '@modulify/validator' +import type { ShapeRefinementViolationInput } from '@modulify/validator' import { isEmail, isString, @@ -180,7 +206,7 @@ const signUpForm = shape({ path: ['confirmation', 'password'], code: 'profile.password.mismatch', args: [], - }] satisfies ObjectShapeRefinementIssue<'profile.password.mismatch'> + }] satisfies ShapeRefinementViolationInput<'profile.password.mismatch'> }) ``` diff --git a/docs/en/09-migration.md b/docs/en/09-migration.md new file mode 100644 index 0000000..791094c --- /dev/null +++ b/docs/en/09-migration.md @@ -0,0 +1,75 @@ +# Migrating From 0.2.1 + +[Documentation index](./00-index.md) +[Russian translation](../ru/09-migration.md) + +This guide describes the unreleased changes after `0.2.1`. + +## Object-Level Refinements + +`shape(...).refine(...)` is async-first even when its callback returns a plain value. +Use `shape(...).refine.sync(...)` for rules used by `validate.sync(...)`, +`matches.sync(...)`, or `shape.check(...)`. + +```typescript +const profile = shape({ password: isString, confirmation: isString }) + .refine.sync(value => value.password === value.confirmation ? null : { + code: 'profile.password.mismatch', + }) +``` + +Use `.refine(...)` with `await validate(...)` for asynchronous rules. + +## Staged Assertions + +Guard assertions establish a domain; refinements check properties inside it: + +```typescript +validate.sync('name', [isString, hasLength({ min: 3 })]) +validate.sync(4, [isInteger, multipleOf(2)]) +``` + +Replace standalone refinements such as `validate.sync(value, hasLength(...))` +with a compatible guard followed by the refinement. Incompatible combinations, +such as `[isNumber, hasLength(...)]`, are rejected by TypeScript. + +Structural validators reset the assertion stage. To refine the outer array after +checking its elements, use `[each(isString), isDefined, hasLength({ min: 2 })]`. + +## Public Type Names + +The old names have no compatibility aliases. Update imports and annotations: + +| Old name | Current name | +| --- | --- | +| `ValidationTuple` | `ValidationResult` | +| `InferMaybeManyViolations` | `InferViolations` | +| `ObjectDescriptor` | `ShapeDescriptor` | +| `InferObjectDescriptor` | `InferShape` | +| `PartialObjectDescriptor` | `PartialShapeDescriptor` | +| `MergeObjectDescriptors` | `MergeShapeDescriptors` | +| `ObjectShapeFieldSelector` | `ShapeFieldSelector` | +| `ObjectShapeRefinement` / `ObjectShapeAsyncRefinement` | `ShapeRefinement` | +| `ObjectShapeRefinementSync` / `ObjectShapeSyncRefinement` | `SyncShapeRefinement` | +| `ObjectShapeRefinementIssue` | `ShapeRefinementViolationInput` | +| `ObjectShapeRefineMethod` | `ShapeRefineMethod` | +| `ObjectShapeRefineMethodSync` | `ShapeRefineMethodSync` | +| `DescribeMaybeMany` | `DescribeConstraints` | +| `DescribeObjectDescriptor` | `DescribeShapeDescriptor` | +| `AssertionDescriptorConstraint` | `AssertionConstraintDescriptor` | +| `ConstraintDescriptorBase` | `BaseConstraintDescriptor` | +| `ValidatorDescriptor` | `OpaqueValidatorDescriptor` | +| `GenericObjectShapeRuleDescriptor` | `SyncObjectShapeRuleDescriptor` | + +## Optional Predicate Fields + +`isShape({ name: [isString, false] })` permits an absent `name`, but rejects +`{ name: 2 }` and `{ name: undefined }`. To allow explicit `undefined`, use +`[Or(isString, isUndefined), false]`. Required fields must be present even when +their predicate accepts `undefined`. + +## Package Consumers + +The public root and subpath exports support ESM, CommonJS, and strict TypeScript +with NodeNext or Bundler resolution. Import from package entrypoints rather than +internal files in `dist/`. diff --git a/docs/ru/00-index.md b/docs/ru/00-index.md index 5dabe3f..f8855b2 100644 --- a/docs/ru/00-index.md +++ b/docs/ru/00-index.md @@ -10,6 +10,8 @@ - [Справка для AI](./07-ai-reference.md) - Краткое описание контракта для AI agents, инструментов и быстрого поиска стабильной семантики библиотеки. - [Типы кодов нарушений](./08-violation-code-types.md) - Подробное руководство по `ViolationCodeRegistry`, `ViolationCode`, сохранению literal-кодов в descriptors и внешнему расширению реестра. +- [Миграция с 0.2.1](./09-migration.md) - Breaking changes, переименованные типы и обновлённые контракты валидации. + ## Переводы - [English](../en/00-index.md) diff --git a/docs/ru/01-shape-api.md b/docs/ru/01-shape-api.md index d6fc4cb..ed8a31a 100644 --- a/docs/ru/01-shape-api.md +++ b/docs/ru/01-shape-api.md @@ -49,6 +49,8 @@ Shape по-прежнему остаётся validator-ом. Дополните - массив constraint-ов, которые выполняются последовательно; - другой structural validator вроде `shape(...)`, `each(...)`, `tuple(...)`, `record(...)`, `union(...)` или `discriminatedUnion(...)`. +Для массивов assertions эта последовательность теперь stage-aware: сначала guard assertions задают домен поля, а refinement assertions обязаны быть совместимы с этим доменом. + Поэтому object validation остаётся согласованной с остальной библиотекой: - field-level checks переиспользуют те же assertions и combinators; @@ -79,6 +81,11 @@ Runtime behavior: - вложенные violations возвращаются на пути поля; - unknown keys по умолчанию разрешены. +Type-level behavior: + +- `[isString, hasLength({ min: 8 })]` типизируется корректно; +- `[isNumber, hasLength({ min: 8 })]` TypeScript отсекает ещё до runtime. + ## Неизвестные ключи У shape есть два режима работы с неизвестными ключами: @@ -190,13 +197,36 @@ Shapes позволяют выражать cross-field invariants без вне ### `refine(...)` -`refine(...)` добавляет синхронное object-level rule, которое запускается только после того, как базовая shape уже успешно провалидировалась как объект. +`refine(...)` добавляет async-first object-level rule, которое запускается только после того, как базовая shape уже успешно провалидировалась как объект. + +```typescript +const registration = shape({ + email: isString, +}).refine(async value => { + const taken = await users.has(value.email) + + return taken + ? [{ path: ['email'], code: 'user.email.taken' }] + : [] +}) +``` + +`refine(...)` специально остаётся тонким: + +- он принимает sync- и async-callbacks; +- при успехе возвращает `[]`, `null` или `undefined`; +- при ошибке возвращает один issue или массив issue; +- `path` задаётся относительно текущей shape и по умолчанию равен `[]`; +- `value` необязателен и по умолчанию берётся из значения объекта по этому относительному пути; +- `code` остаётся machine-readable. + +Если нужен явно sync-safe object rule для `validate.sync(...)`, используйте `refine.sync(...)`: ```typescript const registration = shape({ password: isString, confirmPassword: isString, -}).refine(value => { +}).refine.sync(value => { return value.password === value.confirmPassword ? [] : [{ @@ -207,14 +237,7 @@ const registration = shape({ }) ``` -`refine(...)` специально остаётся тонким: - -- он только sync; -- при успехе возвращает `[]`, `null` или `undefined`; -- при ошибке возвращает один issue или массив issue; -- `path` задаётся относительно текущей shape и по умолчанию равен `[]`; -- `value` необязателен и по умолчанию берётся из значения объекта по этому относительному пути; -- `code` остаётся machine-readable. +`validate.sync(...)`, `matches.sync(...)` и `shape.check(...)` выбрасывают явную ошибку, если встречают async-callback в `refine(...)`. Сгенерированные violations используют: @@ -243,6 +266,8 @@ const registration = shape({ Позже это попадает в `describe(...)` в массив `rules`. +Rules, зарегистрированные через async-first `refine(...)`, получают в этом массиве признак `async: true`. + ### `fieldsMatch(...)` `fieldsMatch(...)` — небольшой helper для частого случая с полем подтверждения. diff --git a/docs/ru/02-metadata-and-introspection.md b/docs/ru/02-metadata-and-introspection.md index 9ec3033..62f5314 100644 --- a/docs/ru/02-metadata-and-introspection.md +++ b/docs/ru/02-metadata-and-introspection.md @@ -182,7 +182,8 @@ const descriptor = describe(shape({ Built-in примеры: - `fieldsMatch(...)` создаёт компактный `fieldsMatch` rule descriptor; -- `refine(...)` может принимать собственный компактный rule descriptor object. +- `refine(...)` может принимать собственный компактный rule descriptor object; +- async-first rules из `refine(...)` помечаются через `async: true`. Так публичное descriptor tree остаётся стабильным и достаточно сериализуемым для tooling, при этом библиотека не пытается сериализовать произвольные callbacks. diff --git a/docs/ru/03-violations.md b/docs/ru/03-violations.md index 0acf809..1a4a2d4 100644 --- a/docs/ru/03-violations.md +++ b/docs/ru/03-violations.md @@ -120,7 +120,7 @@ const violation: Violation = { `validate(...)` и `validate.sync(...)` возвращают: ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` diff --git a/docs/ru/04-json-schema-export.md b/docs/ru/04-json-schema-export.md index 0d47d5f..f2a3d96 100644 --- a/docs/ru/04-json-schema-export.md +++ b/docs/ru/04-json-schema-export.md @@ -69,6 +69,9 @@ Exporter покрывает built-in descriptor set, который уже уч - `isString` -> `type: 'string'` - `isNumber` -> `type: 'number'` +- `isFiniteNumber` -> `type: 'number'` +- `isInteger` -> `type: 'integer'` +- `isSafeInteger` -> `type: 'integer'`, `minimum: Number.MIN_SAFE_INTEGER`, `maximum: Number.MAX_SAFE_INTEGER` - `isBoolean` -> `type: 'boolean'` - `isNull` -> `type: 'null'` - `isEmail` -> `type: 'string'` и `format: 'email'` @@ -202,6 +205,8 @@ Strict режим полезен, когда silent fallback был бы вво Exporter фиксирует эти границы явно и не пытается гадать. +`isValidDate`, `isError`, `isRegExp` и `isPromiseLike` описывают runtime-значения без точного представления в JSON Schema. Strict mode бросает `JsonSchemaExportError`, а best-effort mode выдаёт узел без ограничений. Числа JSON конечны, поэтому для `isFiniteNumber` дополнительный schema keyword не нужен. + ## Связь с `describe(...)` `toJsonSchema(...)` находится downstream от `describe(...)`. diff --git a/docs/ru/05-public-api.md b/docs/ru/05-public-api.md index 0f1ae08..c77fed6 100644 --- a/docs/ru/05-public-api.md +++ b/docs/ru/05-public-api.md @@ -19,6 +19,8 @@ Root package экспортирует: - `validate` - `validate.sync` - `matches.sync` +- `Guard` +- `Refinement` - `meta` - `describe` - `custom` @@ -33,8 +35,9 @@ Root package экспортирует: Root package включает: -- низкоуровневое создание assertions через `assert(...)` -- built-in assertions вроде `isString`, `isNumber`, `isBoolean`, `isNull`, `isEmail`, `hasLength(...)`, `oneOf(...)` +- низкоуровневое создание assertions через `assert(...)` и `refine(...)` +- built-in guard assertions вроде `isString`, `isNumber`, `isBoolean`, `isNull`, `isEmail`, `oneOf(...)` +- built-in refinement assertions вроде `hasLength(...)`, `hasSize(...)`, `hasPattern(...)`, `startsWith(...)`, `hasValue(...)`, `multipleOf(...)` - structural combinators вроде `shape(...)`, `each(...)`, `tuple(...)`, `record(...)` - wrappers вроде `optional(...)`, `nullable(...)`, `nullish(...)` - branching combinators вроде `union(...)` и `discriminatedUnion(...)` @@ -42,6 +45,27 @@ Root package включает: Это основной runtime-facing API surface библиотеки. +Последовательные массивы assertions теперь stage-aware: совместимый кортеж вроде `[isString, hasLength({ min: 3 })]` поддерживается напрямую, а несовместимые комбинации отсекаются типовой системой. +Refinement assertions в этой модели являются staged-helper'ами, поэтому `validate(...)` и `matches.sync(...)` ожидают их после совместимого guard-а, а не в одиночку. + +Структурные validators вроде `each(...)` сбрасывают assertion stage. Перед следующим refinement нужен новый совместимый guard, например `[each(isString), isDefined, hasLength({ min: 2 })]`. + +### Встроенные проверки значений + +Эти проверки доступны как assertions из root и `./assertions`, а как boolean type guards — из `./predicates`. + +| Проверка | Допустимые значения | Код нарушения | +| --- | --- | --- | +| `isFiniteNumber` | Числа без `NaN` и бесконечностей | `number.finite` | +| `isInteger` | Целые числа | `number.integer` | +| `isSafeInteger` | Целые числа в безопасном диапазоне JavaScript | `number.safe-integer` | +| `isValidDate` | Экземпляры `Date` с корректным timestamp | `date.valid` | +| `isError` | Экземпляры `Error`, включая подклассы | `type.error` | +| `isRegExp` | Экземпляры `RegExp` | `type.regexp` | +| `isPromiseLike` | Объекты или функции с вызываемым свойством `then` | `type.promise-like` | + +`isNumber` по-прежнему принимает бесконечности, а `isDate` — невалидные экземпляры `Date`. Для их отклонения используйте более строгие проверки. `isPromiseLike` проверяет наличие вызываемого `then`, не вызывая его и не проверяя тип результата. + ## Метаданные и интроспекция Тот же root package также включает: @@ -67,7 +91,7 @@ Root package также содержит: `validate(...)` и `validate.sync(...)` возвращают: ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` @@ -77,6 +101,8 @@ type ValidationTuple = - `ok` показывает, прошла ли валидация; - `validated` становится строго типизированным только в успешной ветке; - `violations` пуст при успехе и содержит структурированные ошибки при неуспехе. +- `validate(...)` остаётся основным async-first entrypoint; +- `validate.sync(...)` явно выбрасывает ошибку при async validators и async object-level rules из `shape(...).refine(...)`. ## Subpath predicates @@ -97,6 +123,12 @@ Predicates доступны из: Используйте этот subpath, когда нужны guard-style runtime checks без более высокого validation layer. +В `isShape({ name: [isString, false] })` optional-поле может отсутствовать, +но присутствующее значение всегда проверяется предикатом. Это относится и к +явному `undefined`: чтобы разрешить его, используйте `Or(isString, isUndefined)`. +Shorthand `name: isString` и кортеж `[isString, true]` задают обязательное поле. +Наличие поля проверяется через `in`, включая свойства из цепочки прототипов. + ## Subpath экспорта JSON Schema JSON Schema export доступен из: diff --git a/docs/ru/06-common-recipes.md b/docs/ru/06-common-recipes.md index 0ee8231..a61b17b 100644 --- a/docs/ru/06-common-recipes.md +++ b/docs/ru/06-common-recipes.md @@ -14,7 +14,7 @@ Быстрое правило выбора: - используйте `@modulify/validator/predicates`, когда нужны только runtime checks и type guards; -- используйте built-in assertions вроде `isString`, `isDefined`, `hasLength(...)`, `oneOf(...)`, когда нужны машиночитаемые ошибки; +- используйте built-in guard/refinement assertions вроде `isString`, `isDefined`, `hasLength(...)`, `oneOf(...)`, когда нужны машиночитаемые ошибки; - используйте combinators вроде `shape(...)`, `each(...)`, `tuple(...)`, `record(...)`, `union(...)`, `discriminatedUnion(...)`, когда валидация становится структурной; - используйте `meta(...)` и `describe(...)`, когда другой слой нуждается в стабильных машиночитаемых descriptors; - используйте `toJsonSchema(...)` только тогда, когда нужно представление для interoperability или экспорта, а не источник runtime truth. @@ -44,6 +44,7 @@ const [ok, validated, violations] = validate.sync(input, createUser) - используйте `.strict()` для request payload, если неизвестные ключи должны отклоняться; - держите leaf checks маленькими и хорошо сочетаемыми друг с другом; +- если используете массив assertions, начинайте его с совместимого guard-а вроде `isString` перед строковыми refinement-проверками вроде `hasLength(...)`; - используйте элемент кортежа `validated` внутри успешной ветки; - используйте `violations` как структурированные данные для ответов API, логов или сопоставления с UI. diff --git a/docs/ru/07-ai-reference.md b/docs/ru/07-ai-reference.md index 283a48c..46ed0b5 100644 --- a/docs/ru/07-ai-reference.md +++ b/docs/ru/07-ai-reference.md @@ -43,7 +43,7 @@ Violations — это прежде всего структурированные ## Контракт результата валидации ```typescript -type ValidationTuple = +type ValidationResult = | [ok: true, validated: T, violations: []] | [ok: false, validated: unknown, violations: Violation[]] ``` @@ -53,7 +53,8 @@ type ValidationTuple = - `validate(...)` сужает `validated` в успешной ветке; - `validate(...)` не сужает исходную входную переменную; - `matches.sync(...)` — это API для сужения исходной переменной; -- `violations` при успехе всегда пуст. +- `violations` при успехе всегда пуст; +- `validate(...)` — async-first API, а `validate.sync(...)` и `matches.sync(...)` остаются специализированными sync API. ## Семантика wrappers @@ -90,6 +91,8 @@ type ValidationTuple = - structural derivations намеренно сбрасывают object-level rules; - mode switches намеренно сохраняют object-level rules. +- `.refine(...)` — async-first и может возвращать promise; +- `.refine.sync(...)` — явно sync-safe API для object-level rules. ## Контракт violations diff --git a/docs/ru/08-violation-code-types.md b/docs/ru/08-violation-code-types.md index 5d1235d..872f497 100644 --- a/docs/ru/08-violation-code-types.md +++ b/docs/ru/08-violation-code-types.md @@ -58,6 +58,32 @@ const lengthDescriptor = describe(hasLength({ min: 3 })) Это удобно для адаптеров и tooling-кода, который читает descriptors и хочет ветвиться по коду без ручных cast. +Та же точность теперь протекает и в `validate(...)` для параметризованных built-in assertions. + +```typescript +import { + collection, + hasLength, + isString, + validate, +} from '@modulify/validator' + +const [ok, , violations] = validate.sync('ab', [isString, hasLength({ min: 3 })]) + +if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.string': + return violation.violates.name + case 'length.min': + return violation.violates.args[0] + } + }) +} +``` + +Для staged-вызовов вроде `[isString, hasLength({ min: 3 })]` невозможные ветки, например `'length.max'` или `'length.range'`, больше не попадают в union violations, а unsupported-type остаётся только на стороне descriptor-а и не протекает в staged-валидацию. + ## Зачем нужен глобальный реестр Точные literals на отдельных значениях полезны для локальной интроспекции. @@ -158,7 +184,7 @@ const isAvailableEmail = assert( Та же идея работает и для object-level refinement issues. ```typescript -import type { ObjectShapeRefinementIssue } from '@modulify/validator' +import type { ShapeRefinementViolationInput } from '@modulify/validator' import { isEmail, isString, @@ -180,7 +206,7 @@ const signUpForm = shape({ path: ['confirmation', 'password'], code: 'profile.password.mismatch', args: [], - }] satisfies ObjectShapeRefinementIssue<'profile.password.mismatch'> + }] satisfies ShapeRefinementViolationInput<'profile.password.mismatch'> }) ``` diff --git a/docs/ru/09-migration.md b/docs/ru/09-migration.md new file mode 100644 index 0000000..4be6e3b --- /dev/null +++ b/docs/ru/09-migration.md @@ -0,0 +1,76 @@ +# Миграция с 0.2.1 + +[Индекс документации](./00-index.md) +[English](../en/09-migration.md) + +Здесь описаны ещё не выпущенные изменения после `0.2.1`. + +## Правила уровня объекта + +`shape(...).refine(...)` стал async-first, даже если callback возвращает обычное +значение. Для правил, используемых через `validate.sync(...)`, `matches.sync(...)` +или `shape.check(...)`, нужен `shape(...).refine.sync(...)`. + +```typescript +const profile = shape({ password: isString, confirmation: isString }) + .refine.sync(value => value.password === value.confirmation ? null : { + code: 'profile.password.mismatch', + }) +``` + +Асинхронные правила `.refine(...)` используются с `await validate(...)`. + +## Последовательные assertions + +Guard задаёт область допустимых значений, refinement проверяет свойства внутри неё: + +```typescript +validate.sync('name', [isString, hasLength({ min: 3 })]) +validate.sync(4, [isInteger, multipleOf(2)]) +``` + +Замените самостоятельные refinements вроде `validate.sync(value, hasLength(...))` +на совместимый guard и refinement после него. Несовместимые сочетания, например +`[isNumber, hasLength(...)]`, отклоняются TypeScript. + +Структурные validators сбрасывают assertion stage. Для проверки длины внешнего +массива после проверки элементов используйте +`[each(isString), isDefined, hasLength({ min: 2 })]`. + +## Имена публичных типов + +Совместимых aliases для прежних имён нет. Обновите imports и аннотации: + +| Прежнее имя | Новое имя | +| --- | --- | +| `ValidationTuple` | `ValidationResult` | +| `InferMaybeManyViolations` | `InferViolations` | +| `ObjectDescriptor` | `ShapeDescriptor` | +| `InferObjectDescriptor` | `InferShape` | +| `PartialObjectDescriptor` | `PartialShapeDescriptor` | +| `MergeObjectDescriptors` | `MergeShapeDescriptors` | +| `ObjectShapeFieldSelector` | `ShapeFieldSelector` | +| `ObjectShapeRefinement` / `ObjectShapeAsyncRefinement` | `ShapeRefinement` | +| `ObjectShapeRefinementSync` / `ObjectShapeSyncRefinement` | `SyncShapeRefinement` | +| `ObjectShapeRefinementIssue` | `ShapeRefinementViolationInput` | +| `ObjectShapeRefineMethod` | `ShapeRefineMethod` | +| `ObjectShapeRefineMethodSync` | `ShapeRefineMethodSync` | +| `DescribeMaybeMany` | `DescribeConstraints` | +| `DescribeObjectDescriptor` | `DescribeShapeDescriptor` | +| `AssertionDescriptorConstraint` | `AssertionConstraintDescriptor` | +| `ConstraintDescriptorBase` | `BaseConstraintDescriptor` | +| `ValidatorDescriptor` | `OpaqueValidatorDescriptor` | +| `GenericObjectShapeRuleDescriptor` | `SyncObjectShapeRuleDescriptor` | + +## Optional-поля в predicates + +`isShape({ name: [isString, false] })` разрешает отсутствие `name`, но отклоняет +`{ name: 2 }` и `{ name: undefined }`. Для явного `undefined` используйте +`[Or(isString, isUndefined), false]`. Обязательное поле должно присутствовать, +даже если его предикат принимает `undefined`. + +## Потребители пакета + +Публичные root и subpath exports поддерживают ESM, CommonJS и strict TypeScript +с разрешением модулей NodeNext или Bundler. Используйте package entrypoints, +а не внутренние файлы `dist/`. diff --git a/docs/ru/README.md b/docs/ru/README.md index c8f770b..c22e254 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -207,7 +207,7 @@ if (ok) { ## API объектных схем -`shape(...)` — это переиспользуемый API объектных схем. Он валидирует вложенные record-like objects и предоставляет небольшой неизменяемый API вроде `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, `refine()` и `fieldsMatch(...)`. +`shape(...)` — это переиспользуемый API объектных схем. Он валидирует вложенные record-like objects и предоставляет небольшой неизменяемый API вроде `strict()`, `pick()`, `omit()`, `partial()`, `extend()`, `merge()`, async-first `refine()`, явного `refine.sync()` и `fieldsMatch(...)`. ```typescript import { @@ -273,11 +273,17 @@ const node = describe(registration) В текущем API это обычно выглядит так: -- leaf checks через assertions вроде `isString`, `isDefined`, `hasLength`, `oneOf`; +- guard assertions вроде `isString`, `isNumber`, `isDefined`, `oneOf(...)` задают базовый домен значения; +- refinement assertions вроде `hasLength(...)`, `hasPattern(...)`, `startsWith(...)`, `hasValue(...)`, `multipleOf(...)` проверяют свойства уже внутри этого домена; - композиция схем через combinators вроде `exact`, `optional`, `nullable`, `nullish`, `shape(...)`, `each(...)`; - типизированная валидация через `validate(...)` или `validate.sync(...)`; - narrowing исходной переменной в sync-коде через `matches.sync(...)`. +Последовательные массивы assertions теперь stage-aware. Кортеж вроде `[isString, hasLength({ min: 3 })]` типизируется, а несовместимые комбинации вроде `[isNumber, hasLength({ min: 3 })]` TypeScript отсекает. +Refinement assertions не предполагаются для одиночной передачи в `validate(...)` или `matches.sync(...)`. + +`validate(...)` — основной async-first entrypoint. `validate.sync(...)` и `matches.sync(...)` остаются специализированными sync API и выбрасывают ошибку, если встречают async validators или async object-level rules из `shape(...).refine(...)`. + ## Нарушения `validate(...)` возвращает машиночитаемый список `Violation[]`, а `collection(...)` может обернуть его в небольшой helper API для точного поиска по path и обхода дерева. @@ -357,6 +363,8 @@ const jsonSchema = toJsonSchema(profile) - [Практические рецепты](./06-common-recipes.md) - практические примеры для валидации payload, выбора wrappers, переиспользуемых shape, сопоставления ошибок формы и экспорта JSON Schema. - [Справка для AI](./07-ai-reference.md) - компактное описание контракта для agents, инструментов и быстрого поиска семантики библиотеки. +- [Миграция с 0.2.1](./09-migration.md) + ## Заметки - Assertions возвращают структурированные метаданные вместо сообщений. diff --git a/package.json b/package.json index fa6ba89..bf52b02 100644 --- a/package.json +++ b/package.json @@ -6,37 +6,63 @@ "version": "0.2.1", "exports": { ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.cjs", + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + }, "default": "./dist/index.mjs" }, "./assertions": { - "types": "./dist/assertions.d.ts", - "import": "./dist/assertions.mjs", - "require": "./dist/assertions.cjs", + "import": { + "types": "./dist/assertions.d.mts", + "default": "./dist/assertions.mjs" + }, + "require": { + "types": "./dist/assertions.d.cts", + "default": "./dist/assertions.cjs" + }, "default": "./dist/assertions.mjs" }, "./combinators": { - "types": "./dist/combinators.d.ts", - "import": "./dist/combinators.mjs", - "require": "./dist/combinators.cjs", + "import": { + "types": "./dist/combinators.d.mts", + "default": "./dist/combinators.mjs" + }, + "require": { + "types": "./dist/combinators.d.cts", + "default": "./dist/combinators.cjs" + }, "default": "./dist/combinators.mjs" }, "./json-schema": { - "types": "./dist/json-schema.d.ts", - "import": "./dist/json-schema.mjs", - "require": "./dist/json-schema.cjs", + "import": { + "types": "./dist/json-schema.d.mts", + "default": "./dist/json-schema.mjs" + }, + "require": { + "types": "./dist/json-schema.d.cts", + "default": "./dist/json-schema.cjs" + }, "default": "./dist/json-schema.mjs" }, "./predicates": { - "types": "./dist/predicates.d.ts", - "import": "./dist/predicates.mjs", - "require": "./dist/predicates.cjs", + "import": { + "types": "./dist/predicates.d.mts", + "default": "./dist/predicates.mjs" + }, + "require": { + "types": "./dist/predicates.d.cts", + "default": "./dist/predicates.cjs" + }, "default": "./dist/predicates.mjs" } }, "types": "dist/index.d.ts", + "sideEffects": false, "typesVersions": { "*": { "assertions": [ @@ -55,36 +81,36 @@ }, "scripts": { "build": "vite build", - "lint": "eslint src tests types", + "lint": "eslint src tests types scripts vite.config.ts release.config.mjs", "prepare": "husky", - "release": "npx --yes standard-version", - "release:minor": "npx --yes standard-version --release-as minor", - "release:patch": "npx --yes standard-version --release-as patch", - "release:major": "npx --yes standard-version --release-as major", + "release": "conventional-release --tags", + "release:dry": "conventional-release --dry --verbose --tags", + "release:minor": "conventional-release --tags --release-as minor", + "release:patch": "conventional-release --tags --release-as patch", + "release:major": "conventional-release --tags --release-as major", "stats": "gzip -c ./dist/index.mjs | wc -c", "test": "vitest run", - "test:d": "vitest run --typecheck.only", - "test:coverage": "vitest run --coverage", - "test:coverage:html": "vitest run --coverage --reporter=html --outputFile.html=./reports/html/report.html", + "test:d": "vitest run --typecheck.only --coverage.enabled=false", + "test:package": "yarn build && node scripts/check-package.mjs", "typecheck": "tsc --noEmit" }, "devDependencies": { - "@commitlint/cli": "^20.4.3", - "@commitlint/config-conventional": "^20.4.3", + "@commitlint/cli": "^21.2.3", + "@commitlint/config-conventional": "^21.2.3", "@eslint/js": "^10.0.1", - "@types/node": "^25.3.5", - "@vitest/coverage-v8": "4.0.18", - "@vitest/ui": "4.0.18", - "eslint": "^10.0.3", - "globals": "^17.4.0", + "@modulify/conventional-release": "^0.1.3", + "@types/node": "^24.19.0", + "@vitest/coverage-v8": "5.0.2", + "@vitest/ui": "5.0.2", + "eslint": "^10.11.0", + "globals": "^17.12.0", "husky": "^9.1.7", - "ts-node": "^10.9.2", "tslib": "^2.8.1", - "typescript": "^5.5.4", - "typescript-eslint": "^8.56.1", - "vite": "^7.3.1", - "vite-plugin-dts": "^4.5.4", - "vitest": "^4.0.18" + "typescript": "~6.0.3", + "typescript-eslint": "^8.70.1", + "unplugin-dts": "^1.1.1", + "vite": "^8.3.1", + "vitest": "5.0.2" }, "resolutions": { "minimatch@npm:10.2.1": "npm:10.2.4", diff --git a/release.config.mjs b/release.config.mjs new file mode 100644 index 0000000..6bab202 --- /dev/null +++ b/release.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('@modulify/conventional-release').Options} */ +export default { + mode: 'sync', + tagPrefix: 'v', + commitMessage: ({ tag }) => `chore: Released ${tag}`, + // Only the root version changes; the dependency graph and lockfile stay intact. + install: false, +} diff --git a/scripts/check-package.mjs b/scripts/check-package.mjs new file mode 100644 index 0000000..f84ce9b --- /dev/null +++ b/scripts/check-package.mjs @@ -0,0 +1,126 @@ +import assert from 'node:assert/strict' +import { execFileSync } from 'node:child_process' +import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { build } from 'vite' + +const projectRoot = dirname(dirname(fileURLToPath(import.meta.url))) +const consumerRoot = await mkdtemp(join(tmpdir(), 'validator-consumer-')) +const run = (command, args, cwd = consumerRoot) => execFileSync(command, args, { + cwd, + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], +}) + +const runtimeChecks = ` +assert.equal(root.isInteger, assertions.isInteger) +assert.equal(typeof combinators.shape, 'function') +assert.equal(predicates.isShape({ name: [predicates.isString, false] })({}), true) +assert.equal(predicates.isShape({ name: [predicates.isString, false] })({ name: 2 }), false) +assert.equal(root.isFiniteNumber.check(Infinity), false) +assert.equal(root.isInteger.check(1.5), false) +assert.equal(root.isSafeInteger.check(Number.MAX_SAFE_INTEGER + 1), false) +assert.equal(root.isValidDate.check(new Date('invalid')), false) +assert.equal(root.isError.check(new TypeError('error')), true) +assert.equal(root.isRegExp.check(/pattern/), true) +assert.equal(root.isPromiseLike.check({ then() {} }), true) +assert.equal(root.validate.sync(4, [root.isInteger, root.multipleOf(2)])[0], true) +assert.throws(() => root.validate.sync(['a'], [root.each(root.isString), root.hasLength({ min: 1 })]), /preceding guard/) +assert.deepEqual(jsonSchema.toJsonSchema(root.isSafeInteger), { + type: 'integer', minimum: Number.MIN_SAFE_INTEGER, maximum: Number.MAX_SAFE_INTEGER, +}) +assert.throws(() => jsonSchema.toJsonSchema(root.isRegExp, { mode: 'strict' }), jsonSchema.JsonSchemaExportError) +` + +const typeChecks = ` +import { each, hasLength, hasValue, isDefined, isInteger, isPromiseLike, isString, matches, multipleOf, shape, validate } from '@modulify/validator' +import type { InferConstraint, KnownViolationSubject, ValidationResult, ViolationCodeEntry } from '@modulify/validator' +import { isSafeInteger } from '@modulify/validator/assertions' +import { optional } from '@modulify/validator/combinators' +import { isShape, isString as isStringPredicate } from '@modulify/validator/predicates' +import { toJsonSchema } from '@modulify/validator/json-schema' + +declare module '@modulify/validator' { + interface ViolationCodeRegistry { + 'consumer.named': ViolationCodeEntry<'assertion', 'consumer', readonly [name: string]> + } +} +const named: KnownViolationSubject<'consumer.named'> = { kind: 'assertion', name: 'consumer', code: 'consumer.named', args: ['value'] } +// @ts-expect-error registry augmentation preserves the argument type +const invalidNamed: KnownViolationSubject<'consumer.named'> = { kind: 'assertion', name: 'consumer', code: 'consumer.named', args: [2] } + +const result: ValidationResult = validate.sync(4, [isInteger, multipleOf(2)]) +const safeResult: ValidationResult = validate.sync(4, [isSafeInteger, hasValue({ min: 0 })]) +const profile = shape({ name: [isDefined, isString], nickname: optional(isString) }) +const profileResult = validate.sync({}, profile) +if (profileResult[0]) profileResult[1].name.toUpperCase() +toJsonSchema(profile) +const predicate = isShape({ name: isStringPredicate, nickname: [isStringPredicate, false] }) +const value: unknown = {} +if (predicate(value)) { value.name.toUpperCase(); value.nickname?.toUpperCase() } +const promised: InferConstraint = Promise.resolve('value') +// @ts-expect-error validator does not establish an assertion domain +validate.sync(['a'], [each(isString), hasLength({ min: 1 })]) +// @ts-expect-error refinement input must match the preceding guard +matches.sync(4, [isInteger, hasLength({ min: 1 })]) +void result; void safeResult; void promised; void named; void invalidNamed +` + +try { + const packed = JSON.parse(run('npm', ['pack', '--ignore-scripts', '--json', '--cache', join(consumerRoot, 'cache'), '--pack-destination', consumerRoot], projectRoot)) + const archive = join(consumerRoot, packed[0].filename) + await writeFile(join(consumerRoot, 'package.json'), JSON.stringify({ private: true, type: 'module' })) + run('npm', ['install', '--offline', '--ignore-scripts', '--no-audit', '--no-fund', '--package-lock=false', '--cache', join(consumerRoot, 'cache'), archive]) + + for (const format of ['mjs', 'cjs']) { + const imports = format === 'mjs' + ? `import assert from 'node:assert/strict' +import * as root from '@modulify/validator' +import * as assertions from '@modulify/validator/assertions' +import * as combinators from '@modulify/validator/combinators' +import * as predicates from '@modulify/validator/predicates' +import * as jsonSchema from '@modulify/validator/json-schema'` + : `const assert = require('node:assert/strict') +const root = require('@modulify/validator') +const assertions = require('@modulify/validator/assertions') +const combinators = require('@modulify/validator/combinators') +const predicates = require('@modulify/validator/predicates') +const jsonSchema = require('@modulify/validator/json-schema')` + const file = join(consumerRoot, `runtime.${format}`) + await writeFile(file, imports + runtimeChecks) + run(process.execPath, [file]) + } + + const tsc = join(projectRoot, 'node_modules/typescript/bin/tsc') + for (const format of ['mts', 'cts']) { + const file = join(consumerRoot, `consumer.${format}`) + await writeFile(file, typeChecks) + run(process.execPath, [tsc, '--noEmit', '--strict', '--target', 'ES2022', '--module', 'NodeNext', '--moduleResolution', 'NodeNext', file]) + } + run(process.execPath, [tsc, '--noEmit', '--strict', '--target', 'ES2022', '--module', 'ESNext', '--moduleResolution', 'Bundler', join(consumerRoot, 'consumer.mts')]) + + await writeFile(join(consumerRoot, 'entry.mjs'), 'import { isInteger } from \'@modulify/validator\'; export const check = value => isInteger.check(value)\n') + await build({ + configFile: false, + root: consumerRoot, + logLevel: 'silent', + build: { + minify: false, + lib: { entry: join(consumerRoot, 'entry.mjs'), formats: ['es'], fileName: () => 'consumer.mjs' }, + }, + }) + const bundled = await readFile(join(consumerRoot, 'dist/consumer.mjs'), 'utf8') + for (const unused of ['isPromiseLike', 'collectViolations', 'shape.fields.mismatch', 'type.error']) { + assert.equal(bundled.includes(unused), false, `Unused ${unused} remained in the consumer bundle`) + } + await writeFile(join(consumerRoot, 'bundle-check.mjs'), 'import assert from \'node:assert/strict\'; import { check } from \'./dist/consumer.mjs\'; assert.equal(check(1), true); assert.equal(check(1.5), false)\n') + run(process.execPath, [join(consumerRoot, 'bundle-check.mjs')]) + console.log(`Packed consumer checks passed: ESM, CJS, strict NodeNext/Bundler, tree shaking (${Buffer.byteLength(bundled)} bytes).`) +} catch (error) { + console.error([error.message, error.stdout?.toString(), error.stderr?.toString()].filter(Boolean).join('\n')) + process.exitCode = 1 +} finally { + await rm(consumerRoot, { recursive: true, force: true }) +} diff --git a/src/assert.ts b/src/assert.ts index 064785d..dcc71bc 100644 --- a/src/assert.ts +++ b/src/assert.ts @@ -1,8 +1,12 @@ import type { Assertion, + AssertionStage, + Constraint, AssertionConstraintSubject, AssertionConstraint, + Guard, Predicate, + Refinement, } from '~types' import { attachConstraintDescriptor } from '@/metadata' @@ -17,15 +21,45 @@ type AssertMeta = { type ResolveAssertionCode = Code extends string ? Code : Name type ResolveAssertionArgs = Args extends readonly unknown[] ? Args : [] +type ConstraintInputFunction = C extends unknown + ? (value: Parameters[0]) => void + : never -export const assert = < +type ConstraintInput = C extends readonly [] + ? unknown + : ConstraintInputFunction extends (value: infer Input) => void + ? Input + : never + +type ConstraintArgs = C extends readonly [unknown, unknown, string, ...infer Args] + ? Args + : never + +type CompatibleAssertionConstraints = { + [K in keyof C]: AssertionConstraint, ConstraintArgs, C[K][2]>; +} + +type RuntimeAssertion = Assertion & { + [assertionStageSymbol]?: AssertionStage; + [runRefinementSymbol]?: (value: unknown) => ReturnType; + [checkRefinementSymbol]?: (value: unknown) => boolean; +} + +const assertionStageSymbol = Symbol('modulify.validator.assertion.stage') +const runRefinementSymbol = Symbol('modulify.validator.assertion.runRefinement') +const checkRefinementSymbol = Symbol('modulify.validator.assertion.checkRefinement') + +const createAssertion = < T, + const Stage extends AssertionStage, const Name extends string, const Bail extends boolean, const Code extends string | undefined = undefined, const Args extends readonly unknown[] | undefined = undefined, - const C extends readonly AssertionConstraint[] = [], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const C extends readonly AssertionConstraint[] = [], >( + stage: Stage, predicate: Predicate, meta: AssertMeta & { name: Name; @@ -34,7 +68,8 @@ export const assert = < args?: Args; }, constraints: C = [] as unknown as C -): Assertion, ResolveAssertionArgs, Name> => { +): Assertion, ResolveAssertionArgs, Name, Stage> => { + void stage const assertionCode = (meta.code ?? meta.name) as ResolveAssertionCode const assertionArgs = (meta.args ?? []) as ResolveAssertionArgs const violationSubject = { @@ -48,16 +83,7 @@ export const assert = < code: ResolveAssertionCode; args: ResolveAssertionArgs; } - const assertion = ((value: unknown): ReturnType< - Assertion, ResolveAssertionArgs, Name> - > => { - if (!predicate(value)) { - return { - value, - violates: violationSubject, - } - } - + const runConstraints = (value: T) => { for (const [extract, check, code, ...args] of constraints) { if (!check(extract(value), ...args)) { const constraintSubject = { @@ -75,7 +101,24 @@ export const assert = < } return null - }) as Assertion, ResolveAssertionArgs, Name> + } + const checkConstraints = (value: T) => ( + !constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args)) + ) + const assertion = ((value: unknown): ReturnType< + Assertion, ResolveAssertionArgs, Name, Stage> + > => { + if (!predicate(value)) { + return { + value, + violates: violationSubject, + } as ReturnType, ResolveAssertionArgs, Name, Stage>> + } + + return runConstraints(value) as ReturnType< + Assertion, ResolveAssertionArgs, Name, Stage> + > + }) as Assertion, ResolveAssertionArgs, Name, Stage> Object.defineProperties(assertion, { name: { @@ -92,13 +135,23 @@ export const assert = < }, check: { enumerable: true, - value: (value: unknown): value is T => predicate(value) && ( - !constraints.length || constraints.every(([extract, check, , ...args]) => check(extract(value), ...args)) - ), + value: (value: unknown): value is T => predicate(value) && checkConstraints(value), + }, + [assertionStageSymbol]: { + enumerable: false, + value: stage, + }, + [runRefinementSymbol]: { + enumerable: false, + value: (value: unknown) => runConstraints(value as T), + }, + [checkRefinementSymbol]: { + enumerable: false, + value: (value: unknown) => checkConstraints(value as T), }, }) - return attachConstraintDescriptor(assertion, () => ({ + return /* @__PURE__ */ attachConstraintDescriptor(assertion, () => ({ kind: 'assertion', name: meta.name, bail: meta.bail, @@ -110,3 +163,88 @@ export const assert = < })), })) } + +export const assert = < + T, + const Name extends string, + const Bail extends boolean, + const Code extends string | undefined = undefined, + const Args extends readonly unknown[] | undefined = undefined, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const C extends readonly AssertionConstraint[] = [], +>( + predicate: Predicate, + meta: AssertMeta & { + name: Name; + bail: Bail; + code?: Code; + args?: Args; + }, + constraints: C & CompatibleAssertionConstraints = [] as unknown as C & CompatibleAssertionConstraints +): Guard, ResolveAssertionArgs, Name> => { + return createAssertion('guard', predicate, meta, constraints) as Guard< + T, + C, + ResolveAssertionCode, + ResolveAssertionArgs, + Name + > +} + +export const isRefinementAssertion = (constraint: Constraint): constraint is Assertion => { + return typeof constraint === 'function' && (constraint as RuntimeAssertion)[assertionStageSymbol] === 'refinement' +} + +export const runRefinementAssertion = (constraint: Assertion, value: unknown): ReturnType => { + const runRefinement = (constraint as RuntimeAssertion)[runRefinementSymbol] + + return runRefinement ? runRefinement(value) : constraint(value) +} + +export const checkRefinementAssertion = (constraint: Assertion, value: unknown): boolean => { + const checkRefinement = (constraint as RuntimeAssertion)[checkRefinementSymbol] + + return checkRefinement ? checkRefinement(value) : constraint.check(value) +} + +export const createRefinement = < + const Name extends string, + const Bail extends boolean, + const Code extends string | undefined = undefined, + const Args extends readonly unknown[] | undefined = undefined, + const C extends readonly AssertionConstraint[] = [], +>( + meta: AssertMeta & { + name: Name; + bail: Bail; + code?: Code; + args?: Args; + }, + constraints: C = [] as unknown as C +): Refinement, C, ResolveAssertionCode, ResolveAssertionArgs, Name> => { + // Only refinement constraints inspect values; this predicate preserves the input type. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + return createAssertion('refinement', ((value: unknown): value is ConstraintInput => true), meta, constraints) as Refinement< + ConstraintInput, + C, + ResolveAssertionCode, + ResolveAssertionArgs, + Name + > +} + +export const refine: < + const Name extends string, + const Bail extends boolean, + const Code extends string | undefined = undefined, + const Args extends readonly unknown[] | undefined = undefined, + const C extends readonly AssertionConstraint[] = [], +>( + meta: AssertMeta & { + name: Name; + bail: Bail; + code?: Code; + args?: Args; + }, + constraints?: C & CompatibleAssertionConstraints, C> +) => Refinement, C, ResolveAssertionCode, ResolveAssertionArgs, Name> = createRefinement diff --git a/src/assertions.ts b/src/assertions.ts index a8591c3..ef3f9cf 100644 --- a/src/assertions.ts +++ b/src/assertions.ts @@ -1,6 +1,10 @@ import type { AssertionConstraint } from '~types' -import { assert } from './assert' +import { + assert, + createRefinement, + refine, +} from './assert' import { endsWith as _endsWith, @@ -23,73 +27,127 @@ import { isBlob as _isBlob, isDate as _isDate, isEmail as _isEmail, + isError as _isError, + isFiniteNumber as _isFiniteNumber, isFile as _isFile, isFunction as _isFunction, + isInteger as _isInteger, isMap as _isMap, isNaN as _isNaN, isNull as _isNull, isNumber as _isNumber, + isPromiseLike as _isPromiseLike, + isRegExp as _isRegExp, + isSafeInteger as _isSafeInteger, isSet as _isSet, isString as _isString, isSymbol as _isSymbol, + isValidDate as _isValidDate, } from '@/predicates' -export { assert } +export { + assert, + refine, +} // eslint-disable-next-line @typescript-eslint/no-empty-object-type type Defined = {} | null +type EmptyOptions = Record +type LengthExactConstraint = + AssertionConstraint +type LengthMaxConstraint = + AssertionConstraint +type LengthMinConstraint = + AssertionConstraint +type LengthRangeConstraint = + AssertionConstraint type LengthAssertionConstraint = - | AssertionConstraint - | AssertionConstraint - | AssertionConstraint - | AssertionConstraint + | LengthExactConstraint + | LengthMaxConstraint + | LengthMinConstraint + | LengthRangeConstraint +type SizeExactConstraint = + AssertionConstraint | Set, number, [exact: N], 'size.exact'> +type SizeMaxConstraint = + AssertionConstraint | Set, number, [max: N], 'size.max'> +type SizeMinConstraint = + AssertionConstraint | Set, number, [min: N], 'size.min'> +type SizeRangeConstraint = + AssertionConstraint | Set, number, [range: R], 'size.range'> type SizeAssertionConstraint = - | AssertionConstraint | Set, number, [exact: number], 'size.exact'> - | AssertionConstraint | Set, number, [max: number], 'size.max'> - | AssertionConstraint | Set, number, [min: number], 'size.min'> - | AssertionConstraint | Set, number, [range: [number, number]], 'size.range'> + | SizeExactConstraint + | SizeMaxConstraint + | SizeMinConstraint + | SizeRangeConstraint +type ValueExactConstraint = + AssertionConstraint +type ValueMaxConstraint = + AssertionConstraint +type ValueMinConstraint = + AssertionConstraint +type ValueRangeConstraint = + AssertionConstraint type ValueAssertionConstraint = - | AssertionConstraint - | AssertionConstraint - | AssertionConstraint - | AssertionConstraint - -export const isBoolean = assert(_isBoolean, { name: 'isBoolean', bail: true, code: 'type.boolean' }) -export const isBigInt = assert(_isBigInt, { name: 'isBigInt', bail: true, code: 'type.bigint' }) -export const isBlob = assert(_isBlob, { name: 'isBlob', bail: true, code: 'type.blob' }) -export const isDate = assert(_isDate, { name: 'isDate', bail: true, code: 'type.date' }) -export const isDefined = assert((value: unknown): value is Defined => value !== undefined, { - name: 'isDefined', - bail: true, - code: 'value.defined', -}) -export const isEmail = assert(_isEmail, { name: 'isEmail', bail: true, code: 'string.email' }) -export const isFile = assert(_isFile, { name: 'isFile', bail: true, code: 'type.file' }) -export const isFunction = assert(_isFunction, { name: 'isFunction', bail: true, code: 'type.function' }) -export const isMap = assert(_isMap, { name: 'isMap', bail: true, code: 'type.map' }) -export const isNaN = assert(_isNaN, { name: 'isNaN', bail: true, code: 'number.nan' }) -export const isNull = assert(_isNull, { name: 'isNull', bail: true, code: 'type.null' }) -export const isNumber = assert(_isNumber, { name: 'isNumber', bail: true, code: 'type.number' }) -export const isSet = assert(_isSet, { name: 'isSet', bail: true, code: 'type.set' }) -export const isString = assert(_isString, { name: 'isString', bail: true, code: 'type.string' }) -export const isSymbol = assert(_isSymbol, { name: 'isSymbol', bail: true, code: 'type.symbol' }) - -export const hasLength = ({ - exact = null, - max = null, - min = null, - range = null, - bail = false, -}: { + | ValueExactConstraint + | ValueMaxConstraint + | ValueMinConstraint + | ValueRangeConstraint + +type BoundedAssertionOptions = { exact?: number | null; max?: number | null; min?: number | null; - range?: [number, number] | null; + range?: readonly [number, number] | null; bail?: boolean; -} = {}) => { +} + +type OptionNumber = K extends keyof O ? Extract : never + +type OptionRange = + K extends keyof O + ? Extract extends infer R + ? R extends readonly [infer Min extends number, infer Max extends number] + ? readonly [Min, Max] + : never + : never + : never + +type IncludeConstraint< + Value, + C extends AssertionConstraint, +> = [Value] extends [never] ? [] : [C] + +type LengthConstraintTupleFromOptions = [ + ...IncludeConstraint, LengthExactConstraint>>, + ...IncludeConstraint, LengthMaxConstraint>>, + ...IncludeConstraint, LengthMinConstraint>>, + ...IncludeConstraint, LengthRangeConstraint>>, +] + +type SizeConstraintTupleFromOptions = [ + ...IncludeConstraint, SizeExactConstraint>>, + ...IncludeConstraint, SizeMaxConstraint>>, + ...IncludeConstraint, SizeMinConstraint>>, + ...IncludeConstraint, SizeRangeConstraint>>, +] + +type ValueConstraintTupleFromOptions = [ + ...IncludeConstraint, ValueExactConstraint>>, + ...IncludeConstraint, ValueMaxConstraint>>, + ...IncludeConstraint, ValueMinConstraint>>, + ...IncludeConstraint, ValueRangeConstraint>>, +] + +const buildLengthConstraints = (options: O): LengthConstraintTupleFromOptions => { + const { + exact = null, + max = null, + min = null, + range = null, + } = options const constraints: LengthAssertionConstraint[] = [] if (exact !== null) constraints.push([length, isEqual, 'length.exact', exact] as const) @@ -97,8 +155,93 @@ export const hasLength = ({ if (min !== null) constraints.push([length, isGte, 'length.min', min] as const) if (range !== null) constraints.push([length, inRange, 'length.range', range] as const) - return assert( - (value: unknown): value is string | unknown[] => isArray(value) || _isString(value), + return constraints as unknown as LengthConstraintTupleFromOptions +} + +const buildSizeConstraints = (options: O): SizeConstraintTupleFromOptions => { + const { + exact = null, + max = null, + min = null, + range = null, + } = options + const constraints: SizeAssertionConstraint[] = [] + + if (exact !== null) constraints.push([size, isEqual, 'size.exact', exact] as const) + if (max !== null) constraints.push([size, isLte, 'size.max', max] as const) + if (min !== null) constraints.push([size, isGte, 'size.min', min] as const) + if (range !== null) constraints.push([size, inRange, 'size.range', range] as const) + + return constraints as unknown as SizeConstraintTupleFromOptions +} + +const buildValueConstraints = (options: O): ValueConstraintTupleFromOptions => { + const { + exact = null, + max = null, + min = null, + range = null, + } = options + const constraints: ValueAssertionConstraint[] = [] + + if (exact !== null) constraints.push([(value: number) => value, isEqual, 'number.exact', exact] as const) + if (max !== null) constraints.push([(value: number) => value, isLte, 'number.max', max] as const) + if (min !== null) constraints.push([(value: number) => value, isGte, 'number.min', min] as const) + if (range !== null) constraints.push([(value: number) => value, inRange, 'number.range', range] as const) + + return constraints as unknown as ValueConstraintTupleFromOptions +} + +export const isBoolean = /* @__PURE__ */ assert(_isBoolean, { name: 'isBoolean', bail: true, code: 'type.boolean' }) +export const isBigInt = /* @__PURE__ */ assert(_isBigInt, { name: 'isBigInt', bail: true, code: 'type.bigint' }) +export const isBlob = /* @__PURE__ */ assert(_isBlob, { name: 'isBlob', bail: true, code: 'type.blob' }) +export const isDate = /* @__PURE__ */ assert(_isDate, { name: 'isDate', bail: true, code: 'type.date' }) +export const isDefined = /* @__PURE__ */ assert((value: unknown): value is Defined => value !== undefined, { + name: 'isDefined', + bail: true, + code: 'value.defined', +}) +export const isEmail = /* @__PURE__ */ assert(_isEmail, { name: 'isEmail', bail: true, code: 'string.email' }) +export const isError = /* @__PURE__ */ assert(_isError, { name: 'isError', bail: true, code: 'type.error' }) +export const isFiniteNumber = /* @__PURE__ */ assert(_isFiniteNumber, { + name: 'isFiniteNumber', + bail: true, + code: 'number.finite', +}) +export const isFile = /* @__PURE__ */ assert(_isFile, { name: 'isFile', bail: true, code: 'type.file' }) +export const isFunction = /* @__PURE__ */ assert(_isFunction, { name: 'isFunction', bail: true, code: 'type.function' }) +export const isInteger = /* @__PURE__ */ assert(_isInteger, { name: 'isInteger', bail: true, code: 'number.integer' }) +export const isMap = /* @__PURE__ */ assert(_isMap, { name: 'isMap', bail: true, code: 'type.map' }) +export const isNaN = /* @__PURE__ */ assert(_isNaN, { name: 'isNaN', bail: true, code: 'number.nan' }) +export const isNull = /* @__PURE__ */ assert(_isNull, { name: 'isNull', bail: true, code: 'type.null' }) +export const isNumber = /* @__PURE__ */ assert(_isNumber, { name: 'isNumber', bail: true, code: 'type.number' }) +export const isPromiseLike = /* @__PURE__ */ assert(_isPromiseLike, { + name: 'isPromiseLike', + bail: true, + code: 'type.promise-like', +}) +export const isRegExp = /* @__PURE__ */ assert(_isRegExp, { name: 'isRegExp', bail: true, code: 'type.regexp' }) +export const isSafeInteger = /* @__PURE__ */ assert(_isSafeInteger, { + name: 'isSafeInteger', + bail: true, + code: 'number.safe-integer', +}) +export const isSet = /* @__PURE__ */ assert(_isSet, { name: 'isSet', bail: true, code: 'type.set' }) +export const isString = /* @__PURE__ */ assert(_isString, { name: 'isString', bail: true, code: 'type.string' }) +export const isSymbol = /* @__PURE__ */ assert(_isSymbol, { name: 'isSymbol', bail: true, code: 'type.symbol' }) +export const isValidDate = /* @__PURE__ */ assert(_isValidDate, { + name: 'isValidDate', + bail: true, + code: 'date.valid', +}) + +export const hasLength = ( + options: O = {} as O +) => { + const { bail = false } = options + const constraints = buildLengthConstraints(options) + + return /* @__PURE__ */ createRefinement( { name: 'hasLength', bail, @@ -108,28 +251,13 @@ export const hasLength = ({ ) } -export const hasSize = ({ - exact = null, - max = null, - min = null, - range = null, - bail = false, -}: { - exact?: number | null; - max?: number | null; - min?: number | null; - range?: [number, number] | null; - bail?: boolean; -} = {}) => { - const constraints: SizeAssertionConstraint[] = [] - - if (exact !== null) constraints.push([size, isEqual, 'size.exact', exact] as const) - if (max !== null) constraints.push([size, isLte, 'size.max', max] as const) - if (min !== null) constraints.push([size, isGte, 'size.min', min] as const) - if (range !== null) constraints.push([size, inRange, 'size.range', range] as const) +export const hasSize = ( + options: O = {} as O +) => { + const { bail = false } = options + const constraints = buildSizeConstraints(options) - return assert( - (value: unknown): value is Map | Set => _isMap(value) || _isSet(value), + return /* @__PURE__ */ createRefinement( { name: 'hasSize', bail, @@ -146,8 +274,7 @@ export const hasPattern = ( }: { bail?: boolean; } = {} -) => assert( - _isString, +) => /* @__PURE__ */ createRefinement( { name: 'hasPattern', bail, @@ -168,8 +295,7 @@ export const startsWith = ( }: { bail?: boolean; } = {} -) => assert( - _isString, +) => /* @__PURE__ */ createRefinement( { name: 'startsWith', bail, @@ -190,8 +316,7 @@ export const endsWith = ( }: { bail?: boolean; } = {} -) => assert( - _isString, +) => /* @__PURE__ */ createRefinement( { name: 'endsWith', bail, @@ -205,28 +330,13 @@ export const endsWith = ( ]] as const ) -export const hasValue = ({ - exact = null, - max = null, - min = null, - range = null, - bail = false, -}: { - exact?: number | null; - max?: number | null; - min?: number | null; - range?: [number, number] | null; - bail?: boolean; -} = {}) => { - const constraints: ValueAssertionConstraint[] = [] - - if (exact !== null) constraints.push([(value: number) => value, isEqual, 'number.exact', exact] as const) - if (max !== null) constraints.push([(value: number) => value, isLte, 'number.max', max] as const) - if (min !== null) constraints.push([(value: number) => value, isGte, 'number.min', min] as const) - if (range !== null) constraints.push([(value: number) => value, inRange, 'number.range', range] as const) +export const hasValue = ( + options: O = {} as O +) => { + const { bail = false } = options + const constraints = buildValueConstraints(options) - return assert( - _isNumber, + return /* @__PURE__ */ createRefinement( { name: 'hasValue', bail, @@ -236,15 +346,14 @@ export const hasValue = ({ ) } -export const multipleOf = ( - step: number, +export const multipleOf = ( + step: Step, { bail = false, }: { bail?: boolean; } = {} -) => assert( - _isNumber, +) => /* @__PURE__ */ createRefinement( { name: 'multipleOf', bail, @@ -270,7 +379,7 @@ export const oneOf = ( ) => { const haystack = isArray(values) ? values : Object.values(values) - return assert((value: unknown): value is Actual => haystack.some(item => equalTo(item, value)), { + return /* @__PURE__ */ assert((value: unknown): value is Actual => haystack.some(item => equalTo(item, value)), { name: 'oneOf', bail, code: 'value.one-of', diff --git a/src/checkers.ts b/src/checkers.ts index 427265c..209adb2 100644 --- a/src/checkers.ts +++ b/src/checkers.ts @@ -2,7 +2,7 @@ export const isEqual = (value: number, exact: number) => value === exact export const isGte = (value: number, min: number) => value >= min export const isLte = (value: number, max: number) => value <= max -export const inRange = (value: number, [min, max]: [number, number]) => value >= min && value <= max +export const inRange = (value: number, [min, max]: readonly [number, number]) => value >= min && value <= max export const startsWith = (value: string, prefix: string) => value.startsWith(prefix) export const endsWith = (value: string, suffix: string) => value.endsWith(suffix) export const matchesPattern = (value: string, pattern: RegExp) => new RegExp(pattern.source, pattern.flags).test(value) diff --git a/src/combinators.ts b/src/combinators.ts index a7444df..3429af8 100644 --- a/src/combinators.ts +++ b/src/combinators.ts @@ -1,22 +1,30 @@ import type { + AsyncObjectShapeRuleDescriptor, + CompatibleConstraints, + CompatibleShapeDescriptor, Constraint, DiscriminatedUnionValidator, EachValidator, FieldsMatchObjectShapeRuleDescriptor, - GenericObjectShapeRuleDescriptor, InferConstraints, + InferShape, + MergeShapeDescriptors, MaybeMany, + MaybePromise, NullableValidator, NullishValidator, - ObjectShapeFieldSelector, - ObjectShapeRefinement, - ObjectShapeRefinementIssue, - ObjectShapeRuleDescriptor, - MergeObjectDescriptors, ObjectShape, + ObjectShapeRuleDescriptor, OptionalValidator, - PartialObjectDescriptor, + PartialShapeDescriptor, RecordValidator, + ShapeDescriptor, + ShapeFieldSelector, + ShapeRefinement, + ShapeRefineMethod, + ShapeRefinementViolationInput, + SyncObjectShapeRuleDescriptor, + SyncShapeRefinement, TupleValidator, UnknownKeysMode, UnionValidator, @@ -45,17 +53,17 @@ import { isUndefined, } from '@/predicates' -export type ShapeDescriptor = Record> - -export type InferShape = { - [K in keyof D]: InferConstraints -} - export type { - ObjectShapeFieldSelector, + AsyncObjectShapeRuleDescriptor, ObjectShape, - ObjectShapeRefinement, - ObjectShapeRefinementIssue, + ShapeDescriptor, + ShapeFieldSelector, + ShapeRefinement, + ShapeRefineMethod, + ShapeRefineMethodSync, + ShapeRefinementViolationInput, + SyncObjectShapeRuleDescriptor, + SyncShapeRefinement, UnknownKeysMode, } from '~types' @@ -68,6 +76,9 @@ type InferUnion[]> = { }[number] type VariantMap = Record> +type CompatibleConstraintTupleInputs[]> = { + readonly [K in keyof T]: CompatibleConstraints +} type InferDiscriminatedUnion = { [K in keyof T]: InferConstraints @@ -76,20 +87,15 @@ type InferDiscriminatedUnion = { type StrictObjectShape< D extends ShapeDescriptor, R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], - RI extends ObjectShapeRefinementIssue = never, + RI extends ShapeRefinementViolationInput = never, > = ObjectShape type PassthroughObjectShape< D extends ShapeDescriptor, R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], - RI extends ObjectShapeRefinementIssue = never, + RI extends ShapeRefinementViolationInput = never, > = ObjectShape -type ShapeRefinement< - T, - I extends ObjectShapeRefinementIssue = ObjectShapeRefinementIssue, -> = ObjectShapeRefinement - const describeConstraintMap = >>( constraints: T ): Record> => { @@ -102,7 +108,7 @@ const describeConstraintMap = >(descriptor: R): R => { +const normalizeRuleDescriptor = >(descriptor: R): R => { if (!descriptor.metadata) { return descriptor } @@ -113,11 +119,18 @@ const normalizeRuleDescriptor = >( + descriptor: R +): Omit & AsyncObjectShapeRuleDescriptor => ({ + ...normalizeRuleDescriptor(descriptor), + async: true, +}) + const passthrough = , Accepted>( kind: 'optional' | 'nullable' | 'nullish', accepts: (value: unknown) => value is Accepted, - constraints: C -): Validator | Accepted> => attachConstraintDescriptor({ + constraints: CompatibleConstraints +): Validator | Accepted> => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is InferConstraints | Accepted { return accepts(value) || matchesConstraints(value, constraints) }, @@ -128,7 +141,7 @@ const passthrough = , Accepted>( ): Validation[] { return accepts(value) ? [] - : [validate(value, constraints, path) as Validation] + : [validate(value, constraints as CompatibleConstraints>, path) as Validation] }, }, () => ({ kind, @@ -185,16 +198,16 @@ const omitDescriptor = < const extendDescriptor = < D extends ShapeDescriptor, E extends ShapeDescriptor, ->(descriptor: D, extension: E): MergeObjectDescriptors => ({ +>(descriptor: D, extension: E): MergeShapeDescriptors => ({ ...descriptor, ...extension, -}) as MergeObjectDescriptors +}) as MergeShapeDescriptors -const partialDescriptor = (descriptor: D): PartialObjectDescriptor => { - const partial = {} as PartialObjectDescriptor +const partialDescriptor = (descriptor: D): PartialShapeDescriptor => { + const partial = {} as PartialShapeDescriptor keysOf(descriptor).forEach(key => { - partial[key] = optional(descriptor[key]) + partial[key] = optional(descriptor[key] as CompatibleConstraints) }) return partial @@ -208,20 +221,18 @@ const getPathValue = (value: unknown, path: readonly PropertyKey[]) => path.redu return Reflect.get(Object(current), key) }, value) -const toPath = (selector: ObjectShapeFieldSelector): PropertyKey[] => Array.isArray(selector) +const toPath = (selector: ShapeFieldSelector): PropertyKey[] => typeof selector === 'object' ? [...selector] : [selector] -const collectShapeRefinementViolations = < +const toShapeRefinementViolations = < D extends ShapeDescriptor, - RI extends ObjectShapeRefinementIssue, + RI extends ShapeRefinementViolationInput, >( value: InferShape, path: PropertyKey[], - refinements: readonly ShapeRefinement, RI>[] -) => refinements.flatMap(refinement => { - const result = refinement(value) - + result: MaybeMany | null | undefined +) => { if (result === null || result === undefined) { return [] } @@ -242,13 +253,50 @@ const collectShapeRefinementViolations = < }, } }) +} + +const collectShapeRefinementViolations = < + D extends ShapeDescriptor, + RI extends ShapeRefinementViolationInput, +>( + value: InferShape, + path: PropertyKey[], + refinements: readonly ShapeRefinement, RI>[] +) => refinements.flatMap(refinement => { + const result = refinement(value) + + if (result instanceof Promise) { + throw new Error('Found asynchronous object-level shape refinement') + } + + return toShapeRefinementViolations(value, path, result) }) +const collectAsyncShapeRefinementViolations = < + D extends ShapeDescriptor, + RI extends ShapeRefinementViolationInput, +>( + value: InferShape, + path: PropertyKey[], + refinements: readonly ShapeRefinement, RI>[] +): MaybePromise => { + const results = refinements.map(refinement => refinement(value)) + + if (results.some(result => result instanceof Promise)) { + return Promise.all(results.map(result => Promise.resolve(result))).then(resolved => { + return resolved.flatMap(result => toShapeRefinementViolations(value, path, result)) + }) + } + + return (results as Array | null | undefined>) + .flatMap(result => toShapeRefinementViolations(value, path, result)) +} + const createObjectShape = < const D extends ShapeDescriptor, const M extends UnknownKeysMode, const R extends readonly ObjectShapeRuleDescriptor[], - RI extends ObjectShapeRefinementIssue = never, + RI extends ShapeRefinementViolationInput = never, >( descriptor: D, unknownKeys: M, @@ -256,13 +304,42 @@ const createObjectShape = < rules: R ): ObjectShape => { const keys = keysOf(descriptor) + const addAsyncRefinement = < + const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, + const RD extends SyncObjectShapeRuleDescriptor = SyncObjectShapeRuleDescriptor<'refine'> + >( + refinement: ShapeRefinement, I>, + ruleDescriptor: RD = { kind: 'refine' } as RD + ) => createObjectShape & AsyncObjectShapeRuleDescriptor], RI | I>( + descriptor, + unknownKeys, + [...refinements, refinement] as readonly ShapeRefinement, RI | I>[], + [...rules, normalizeAsyncRuleDescriptor(ruleDescriptor)] as [...R, Omit & AsyncObjectShapeRuleDescriptor] + ) + + const addSyncRefinement = < + const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, + const RD extends SyncObjectShapeRuleDescriptor = SyncObjectShapeRuleDescriptor<'refine'> + >( + refinement: SyncShapeRefinement, I>, + ruleDescriptor: RD = { kind: 'refine' } as RD + ) => createObjectShape( + descriptor, + unknownKeys, + [...refinements, refinement] as readonly ShapeRefinement, RI | I>[], + [...rules, normalizeRuleDescriptor(ruleDescriptor)] as [...R, RD] + ) - return attachConstraintDescriptor({ + const refine = /* @__PURE__ */ Object.assign(addAsyncRefinement, { + sync: addSyncRefinement, + }) as ShapeRefineMethod + + return /* @__PURE__ */ attachConstraintDescriptor({ descriptor, unknownKeys, check(value: unknown): value is InferShape { return isRecord(value) - && keys.every(key => matchesConstraints(value[key], descriptor[key])) + && keys.every(key => matchesConstraints(value[key], descriptor[key] as CompatibleConstraints)) && (unknownKeys === 'passthrough' || !hasUnknownKeys(value, descriptor)) && collectShapeRefinementViolations(value as InferShape, [], refinements).length === 0 }, @@ -281,7 +358,7 @@ const createObjectShape = < const validations = keys.reduce[]>((all, key) => [ ...all, - validate(value[key], descriptor[key], [...path, key]) as Validation, + validate(value[key], descriptor[key] as CompatibleConstraints, [...path, key]) as Validation, ], []) if (unknownKeys === 'strict') { @@ -294,7 +371,7 @@ const createObjectShape = < return structuralViolations.length > 0 ? structuralViolations - : collectShapeRefinementViolations(value as InferShape, path, refinements) + : Promise.resolve(collectAsyncShapeRefinementViolations(value as InferShape, path, refinements)) }) as Validation] } @@ -302,23 +379,14 @@ const createObjectShape = < return structuralViolations.length > 0 ? validations - : [collectShapeRefinementViolations(value as InferShape, path, refinements) as Validation] - }, - refine< - const I extends ObjectShapeRefinementIssue = ObjectShapeRefinementIssue, - const RD extends GenericObjectShapeRuleDescriptor = GenericObjectShapeRuleDescriptor<'refine'> - >( - refinement: ShapeRefinement, I>, - ruleDescriptor: RD = { kind: 'refine' } as RD - ) { - return createObjectShape( - descriptor, - unknownKeys, - [...refinements, refinement] as readonly ShapeRefinement, RI | I>[], - [...rules, normalizeRuleDescriptor(ruleDescriptor)] as [...R, RD] - ) + : [( + validate.sync + ? collectShapeRefinementViolations(value as InferShape, path, refinements) + : collectAsyncShapeRefinementViolations(value as InferShape, path, refinements) + ) as Validation] }, - fieldsMatch(selectedKeys: K) { + refine, + fieldsMatch(selectedKeys: K) { const [left, right] = selectedKeys const leftPath = toPath(left) const rightPath = toPath(right) @@ -331,7 +399,7 @@ const createObjectShape = < D, M, [...R, FieldsMatchObjectShapeRuleDescriptor], - RI | ObjectShapeRefinementIssue<'shape.fields.mismatch'> + RI | ShapeRefinementViolationInput<'shape.fields.mismatch'> >( descriptor, unknownKeys, @@ -343,9 +411,9 @@ const createObjectShape = < code: 'shape.fields.mismatch', args: [selectedKeys], }] - }] as readonly ShapeRefinement< + }] as readonly SyncShapeRefinement< InferShape, - RI | ObjectShapeRefinementIssue<'shape.fields.mismatch'> + RI | ShapeRefinementViolationInput<'shape.fields.mismatch'> >[], [...rules, ruleDescriptor] as [...R, FieldsMatchObjectShapeRuleDescriptor] ) @@ -369,7 +437,7 @@ const createObjectShape = < return createObjectShape(extendDescriptor(descriptor, extension), unknownKeys, [], []) }, merge( - shape: ObjectShape + shape: ObjectShape ) { return createObjectShape(extendDescriptor(descriptor, shape.descriptor), unknownKeys, [], []) }, @@ -406,7 +474,7 @@ const collectUnionViolations = ( value: unknown, path: PropertyKey[] ) => { - const branchResults = branches.map(branch => validate(value, branch, path)) + const branchResults = branches.map(branch => validate(value, branch as CompatibleConstraints, path)) if (branchResults.some(result => result instanceof Promise)) { return Promise.all(branchResults.map(result => Promise.resolve(result))).then(results => { @@ -417,7 +485,7 @@ const collectUnionViolations = ( return toUnionFailure(branches, value, path, branchResults as Validation[]) } -export const each = >(constraints: C): EachValidator => attachConstraintDescriptor({ +export const each = >(constraints: CompatibleConstraints): EachValidator => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is InferConstraints[] { return isArray(value) && value.every(item => matchesConstraints(item, constraints)) }, @@ -427,7 +495,7 @@ export const each = >(constraints: C): Eac path: PropertyKey[] ): Validation[] { return isArray(value) - ? value.map((item, index) => validate(item, constraints, [...path, index])) as Validation[] + ? value.map((item, index) => validate(item, constraints as CompatibleConstraints, [...path, index])) as Validation[] : [[{ value, path, @@ -439,7 +507,9 @@ export const each = >(constraints: C): Eac item: describeConstraints(constraints), })) -export const tuple = []>(constraints: T): TupleValidator => attachConstraintDescriptor({ +export const tuple = []>( + constraints: CompatibleConstraintTupleInputs +): TupleValidator => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is InferTuple { return isArray(value) && value.length === constraints.length @@ -473,7 +543,9 @@ export const tuple = []>(constrai items: constraints.map(constraint => describeConstraints(constraint)), })) -export const union = []>(constraints: T): UnionValidator => attachConstraintDescriptor({ +export const union = []>( + constraints: CompatibleConstraintTupleInputs +): UnionValidator => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is InferUnion { return constraints.some(constraint => matchesConstraints(value, constraint)) }, @@ -492,16 +564,16 @@ export const union = []>(constrai export const discriminatedUnion = < const K extends PropertyKey, const T extends VariantMap, ->(key: K, variants: T): DiscriminatedUnionValidator => attachConstraintDescriptor({ +>(key: K, variants: CompatibleShapeDescriptor): DiscriminatedUnionValidator => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is InferDiscriminatedUnion { if (!isRecord(value)) { return false } - const discriminator = value[key] + const discriminator = value[key] as PropertyKey return Object.prototype.hasOwnProperty.call(variants, discriminator) - && matchesConstraints(value, variants[discriminator as keyof T]) + && matchesConstraints(value, variants[discriminator as keyof T] as CompatibleConstraints) }, run( validate: F, @@ -516,7 +588,7 @@ export const discriminatedUnion = < }]] as Validation[] } - const discriminator = value[key] + const discriminator = value[key] as PropertyKey if (!Object.prototype.hasOwnProperty.call(variants, discriminator)) { return [[{ @@ -531,7 +603,11 @@ export const discriminatedUnion = < }]] as Validation[] } - return [validate(value, variants[discriminator as keyof T], path) as Validation] + return [validate( + value, + variants[discriminator as keyof T] as CompatibleConstraints, + path + ) as Validation] }, } as DiscriminatedUnionValidator, () => ({ kind: 'discriminatedUnion', @@ -539,7 +615,7 @@ export const discriminatedUnion = < variants: describeConstraintMap(variants), })) -export const record = >(constraints: C): RecordValidator => attachConstraintDescriptor({ +export const record = >(constraints: CompatibleConstraints): RecordValidator => /* @__PURE__ */ attachConstraintDescriptor({ check(value: unknown): value is Record> { return isRecord(value) && Object.values(value).every(item => matchesConstraints(item, constraints)) }, @@ -556,37 +632,41 @@ export const record = >(constraints: C): R }]] as Validation[] } - return Object.keys(value).map(key => validate(value[key], constraints, [...path, key]) as Validation) + return Object.keys(value).map(key => validate( + value[key], + constraints as CompatibleConstraints, + [...path, key] + ) as Validation) }, } as RecordValidator, () => ({ kind: 'record', values: describeConstraints(constraints), })) -export const shape = (descriptor: D): ObjectShape => { - return createObjectShape(descriptor, 'passthrough', [], []) +export const shape = (descriptor: CompatibleShapeDescriptor): ObjectShape => { + return /* @__PURE__ */ createObjectShape(descriptor, 'passthrough', [], []) } -export const exact = (value: T) => assert(isExact(value), { +export const exact = (value: T) => /* @__PURE__ */ assert(isExact(value), { name: 'exact', bail: true, code: 'value.exact', args: [value], }) -export const optional = >(constraints: C): OptionalValidator => passthrough( +export const optional = >(constraints: CompatibleConstraints): OptionalValidator => /* @__PURE__ */ passthrough( 'optional', isUndefined, constraints ) as OptionalValidator -export const nullable = >(constraints: C): NullableValidator => passthrough( +export const nullable = >(constraints: CompatibleConstraints): NullableValidator => /* @__PURE__ */ passthrough( 'nullable', isNull, constraints ) as NullableValidator -export const nullish = >(constraints: C): NullishValidator => passthrough( +export const nullish = >(constraints: CompatibleConstraints): NullishValidator => /* @__PURE__ */ passthrough( 'nullish', (value: unknown): value is null | undefined => isNull(value) || isUndefined(value), constraints diff --git a/src/constraints.ts b/src/constraints.ts index 2c189b8..7f1bc3e 100644 --- a/src/constraints.ts +++ b/src/constraints.ts @@ -1,21 +1,51 @@ import type { + Assertion, + CompatibleConstraints, Constraint, InferConstraints, MaybeMany, Validator, } from '~types' +import { + checkRefinementAssertion, + isRefinementAssertion, +} from '@/assert' + export const isValidator = (constraint: Constraint): constraint is Validator => 'run' in constraint export function arrayify(value: MaybeMany): T[] { + // Array.isArray does not exclude readonly arrays from the scalar branch. return Array.isArray(value) ? [...value] - : [value] + : [value as T] } export function matchesConstraints>( value: unknown, - constraints: C + constraints: CompatibleConstraints ): value is InferConstraints { - return arrayify(constraints).every(constraint => constraint.check(value)) + let establishedDomain = false + + return arrayify(constraints).every(constraint => { + if (isValidator(constraint)) { + establishedDomain = false + + return constraint.check(value) + } + + if (!establishedDomain && isRefinementAssertion(constraint)) { + return false + } + + const matched = establishedDomain && isRefinementAssertion(constraint) + ? checkRefinementAssertion(constraint as Assertion, value) + : constraint.check(value) + + if (matched) { + establishedDomain = true + } + + return matched + }) } diff --git a/src/index.ts b/src/index.ts index 28600ee..faf18e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,12 @@ import type { + Assertion, + CompatibleConstraints, Constraint, InferConstraints, - InferMaybeManyViolations, + InferViolations, MaybeMany, Recursive, - ValidationTuple, + ValidationResult, Violation, } from '~types' @@ -22,42 +24,57 @@ export { export type { AllOfConstraintDescriptor, AssertionDescriptor, - AssertionDescriptorConstraint, + AssertionStage, + AssertionConstraintDescriptor, + AsyncObjectShapeRuleDescriptor, + BaseConstraintDescriptor, + CompatibleConstraints, + CompatibleConstraintTuple, + CompatibleShapeDescriptor, Constraint, ConstraintDescriptor, - ConstraintDescriptorBase, ConstraintMetadata, CustomConstraintDescriptor, DescribeAssertionConstraint, DescribeAssertionConstraintTuple, DescribeConstraint, DescribeConstraintTuple, - DescribeMaybeMany, - DescribeObjectDescriptor, + DescribeConstraints, + DescribeShapeDescriptor, DescribedValidator, DiscriminatedUnionValidator, EachValidator, FieldsMatchObjectShapeRuleDescriptor, - GenericObjectShapeRuleDescriptor, + Guard, + InferShape, InferConstraint, InferConstraints, InferConstraintViolations, - InferMaybeManyViolations, + InferViolations, + MergeShapeDescriptors, + OpaqueValidatorDescriptor, + PartialShapeDescriptor, DiscriminatedUnionConstraintDescriptor, EachConstraintDescriptor, NullableValidator, NullishValidator, KnownViolationCode, KnownViolationSubject, - ObjectShapeFieldSelector, - ObjectShapeRefinement, - ObjectShapeRefinementIssue, ObjectShapeRuleDescriptor, ObjectShapeRuleDescriptorBase, OptionalValidator, RecordValidator, + Refinement, RecordConstraintDescriptor, + ShapeDescriptor, + ShapeFieldSelector, + ShapeRefinement, + ShapeRefineMethod, + ShapeRefineMethodSync, + ShapeRefinementViolationInput, ShapeConstraintDescriptor, + SyncObjectShapeRuleDescriptor, + SyncShapeRefinement, TupleValidator, TupleConstraintDescriptor, UnionValidator, @@ -74,14 +91,16 @@ export type { ViolationSubject, ViolationTreeNode, UnionConstraintDescriptor, - ValidationTuple, ValidationResult, Validator, - ValidatorDescriptor, Violation, WrapperConstraintDescriptor, } from '~types' +import { + isRefinementAssertion, + runRefinementAssertion, +} from '@/assert' import { arrayify, isValidator, @@ -89,19 +108,29 @@ import { const collectViolations = async ( value: unknown, - constraints: MaybeMany, + constraints: CompatibleConstraints>, path: PropertyKey[] = [] ): Promise => { const validations: Promise[] = [] + let establishedAssertionDomain = false for (const c of arrayify(constraints)) { if (isValidator(c)) { + establishedAssertionDomain = false validations.push(...c.run(collectViolations, value, path).map(v => v instanceof Promise ? v : Promise.resolve(v))) continue } - const v = c(value) + if (!establishedAssertionDomain && isRefinementAssertion(c)) { + throw new Error(`Refinement ${String(c.name)} requires a compatible preceding guard`) + } + + const v = establishedAssertionDomain && isRefinementAssertion(c) + ? runRefinementAssertion(c as Assertion, value) + : c(value) + if (v instanceof Promise) { + establishedAssertionDomain = false if (c.bail) { const awaited = await v if (awaited) { @@ -112,44 +141,63 @@ const collectViolations = async ( validations.push(v.then(v => v ? [Object.assign(v, { path: [...path] })] : [])) } } else if (v) { + establishedAssertionDomain = false validations.push(Promise.resolve([Object.assign(v, { path: [...path] })])) if (c.bail) { break } + } else { + establishedAssertionDomain = true } } return settle(value, path, validations) } +collectViolations.sync = false as const + const collectViolationsSync = ( value: unknown, - constraints: MaybeMany, + constraints: CompatibleConstraints>, path: PropertyKey[] = [] ): Violation[] => { const violations: Recursive[] = [] + let establishedAssertionDomain = false for (const c of arrayify(constraints)) { if (isValidator(c)) { + establishedAssertionDomain = false violations.push(...c.run(collectViolationsSync, value, path)) continue } - const v = c(value) + if (!establishedAssertionDomain && isRefinementAssertion(c)) { + throw new Error(`Refinement ${String(c.name)} requires a compatible preceding guard`) + } + + const v = establishedAssertionDomain && isRefinementAssertion(c) + ? runRefinementAssertion(c as Assertion, value) + : c(value) + if (v instanceof Promise) { throw new Error('Found asynchronous validator ' + String(c.name)) } else if (v) { + establishedAssertionDomain = false violations.push(Object.assign(v, { path: [...path] })) if (c.bail) break + } else { + establishedAssertionDomain = true } } return flatten(violations) as Violation[] } -function toResult(value: unknown, violations: V[]): ValidationTuple { +collectViolationsSync.sync = true as const + +function toResult(value: unknown, violations: V[]): ValidationResult { return violations.length === 0 ? [true, value as T, []] : [false, value, violations] @@ -189,33 +237,33 @@ async function settle (value: unknown, path: PropertyKey[], validations: Promise } export const matches = { - sync>(value: unknown, constraints: C): value is InferConstraints { - return collectViolationsSync(value, constraints).length === 0 + sync>(value: unknown, constraints: C & CompatibleConstraints): value is InferConstraints { + return collectViolationsSync(value, constraints as CompatibleConstraints>).length === 0 }, } -export const validate = Object.assign( +export const validate = /* @__PURE__ */ Object.assign( async >( value: unknown, - constraints: C - ): Promise, InferMaybeManyViolations>> => { - const violations = await collectViolations(value, constraints) + constraints: C & CompatibleConstraints + ): Promise, InferViolations>> => { + const violations = await collectViolations(value, constraints as CompatibleConstraints>) - return toResult, InferMaybeManyViolations>( + return toResult, InferViolations>( value, - violations as InferMaybeManyViolations[] + violations as InferViolations[] ) }, { sync>( value: unknown, - constraints: C - ): ValidationTuple, InferMaybeManyViolations> { - const violations = collectViolationsSync(value, constraints) + constraints: C & CompatibleConstraints + ): ValidationResult, InferViolations> { + const violations = collectViolationsSync(value, constraints as CompatibleConstraints>) - return toResult, InferMaybeManyViolations>( + return toResult, InferViolations>( value, - violations as InferMaybeManyViolations[] + violations as InferViolations[] ) }, } diff --git a/src/json-schema.ts b/src/json-schema.ts index 5ba8856..2b4263c 100644 --- a/src/json-schema.ts +++ b/src/json-schema.ts @@ -371,6 +371,20 @@ const numberSchema = ( ): JsonSchema => { const schema: MutableJsonSchema = { type: 'number' } + if (descriptor.name === 'isInteger') { + setSchemaProperty(schema, 'type', 'integer') + + return schema + } + + if (descriptor.name === 'isSafeInteger') { + setSchemaProperty(schema, 'type', 'integer') + setSchemaProperty(schema, 'minimum', Number.MIN_SAFE_INTEGER) + setSchemaProperty(schema, 'maximum', Number.MAX_SAFE_INTEGER) + + return schema + } + if (descriptor.name === 'multipleOf') { const [step] = descriptor.constraints[0]?.args ?? [] @@ -514,6 +528,13 @@ const exportAssertion = ( case 'isNumber': return { type: 'number' } + case 'isFiniteNumber': + return { type: 'number' } + + case 'isInteger': + case 'isSafeInteger': + return numberSchema(descriptor, context) + case 'isBoolean': return { type: 'boolean' } @@ -571,6 +592,18 @@ const exportAssertion = ( case 'isDate': return unsupported(descriptor, context, 'Date instances do not have a stable JSON Schema representation') + case 'isValidDate': + return unsupported(descriptor, context, 'Date instances do not have a stable JSON Schema representation') + + case 'isError': + return unsupported(descriptor, context, 'Error instances do not have a stable JSON Schema representation') + + case 'isPromiseLike': + return unsupported(descriptor, context, 'promise-like values do not have a stable JSON Schema representation') + + case 'isRegExp': + return unsupported(descriptor, context, 'regular expressions do not have a stable JSON Schema representation') + case 'isSet': return unsupported(descriptor, context, 'Set instances do not have a stable JSON Schema representation') diff --git a/src/metadata.ts b/src/metadata.ts index adadb80..9e9f63f 100644 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -4,7 +4,7 @@ import type { ConstraintDescriptor, ConstraintMetadata, DescribeConstraint, - DescribeMaybeMany, + DescribeConstraints, MaybeMany, Validator, } from '~types' @@ -152,15 +152,15 @@ export const meta = (validator: V): V => validator -export const describeConstraints = >(constraints: C): DescribeMaybeMany => { +export const describeConstraints = >(constraints: C): DescribeConstraints => { const values = arrayify(constraints) return values.length === 1 - ? describe(values[0] as Constraint) as DescribeMaybeMany + ? describe(values[0] as Constraint) as DescribeConstraints : { kind: 'allOf', constraints: values.map(value => describe(value)), - } as unknown as DescribeMaybeMany + } as unknown as DescribeConstraints } export const describe = (constraint: C): DescribeConstraint => { diff --git a/src/predicates.ts b/src/predicates.ts index a7d3651..64481b6 100644 --- a/src/predicates.ts +++ b/src/predicates.ts @@ -35,6 +35,11 @@ export function isDate (value: unknown): value is Date { return value instanceof Date } +/** Checks if value is a valid Date */ +export function isValidDate (value: unknown): value is Date { + return isDate(value) && !Number.isNaN(value.getTime()) +} + /** Checks if a value is an email */ export function isEmail (value: unknown): value is string { const pattern = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i @@ -52,6 +57,11 @@ export function isFile (value: unknown): value is File { return typeof File !== 'undefined' && value instanceof File } +/** Checks if a value is an Error */ +export function isError (value: unknown): value is Error { + return value instanceof Error +} + /** Checks if a value is a function */ export function isFunction unknown = (...args: never[]) => unknown>( value: unknown @@ -79,16 +89,43 @@ export function isNumber (value: unknown): value is number { return typeof value === 'number' && !isNaN(value) } +/** Checks if a value is a finite number */ +export function isFiniteNumber (value: unknown): value is number { + return isNumber(value) && Number.isFinite(value) +} + +/** Checks if a value is an integer */ +export function isInteger (value: unknown): value is number { + return isNumber(value) && Number.isInteger(value) +} + /** Checks if a value is an object, excluding null value */ export function isObject (value: unknown): value is object { return typeof value === 'object' && value !== null } +/** Checks if a value is promise-like */ +export function isPromiseLike(value: unknown): value is PromiseLike { + return (isObject(value) || isFunction(value)) + && 'then' in value + && isFunction((value as PromiseLike & { then: unknown }).then) +} + +/** Checks if a value is a regular expression */ +export function isRegExp (value: unknown): value is RegExp { + return value instanceof RegExp +} + /** Check if a value is a record like Record */ export function isRecord (value: unknown): value is Record { return isObject(value) && !isNull(value) && constructorOf(value) === Object && Object.keys(prototypeOf(value)).length === 0 } +/** Checks if a value is a safe integer */ +export function isSafeInteger (value: unknown): value is number { + return isNumber(value) && Number.isSafeInteger(value) +} + /** Checks if a value is a Set */ export function isSet(value: unknown): value is Set { return value instanceof Set @@ -142,18 +179,25 @@ export type Shape = { [K in keyof T]: [Predicate, boolean] | Predicate } -// Without `any` inference does not work properly -// eslint-disable-next-line -type ExtractType> = { - [K in keyof T]: T[K] extends [Predicate, true] +type ShapePropertyType = Config extends Predicate + ? U + : Config extends [Predicate, boolean] ? U - : T[K] extends [Predicate, false] - ? U | undefined - : never; -} extends infer O - ? O - : never + : never + +type OptionalShapeKeys = { + [K in keyof T]: T[K] extends [Predicate, infer Required] + ? false extends Required ? K : never + : never; +}[keyof T] +type ExtractType = { + [K in Exclude>]: ShapePropertyType; +} & { + [K in OptionalShapeKeys]?: ShapePropertyType; +} + +/** Checks present fields with their predicates; optional fields may be absent. */ // Without `any` inference does not work properly // eslint-disable-next-line export const isShape = >(shape: S) => { @@ -163,9 +207,10 @@ export const isShape = >(shape: S) => { const config = shape[p as keyof S] as [Predicate, boolean] | Predicate const [predicate, required] = isArray(config) ? config : [config, true] - return p in value - && value[p as keyof object] !== undefined - && predicate(value[p as keyof object]) - || !required + if (!(p in value)) { + return !required + } + + return predicate(value[p as keyof object]) }) } diff --git a/tests/assertion-violations.test-d.ts b/tests/assertion-violations.test-d.ts new file mode 100644 index 0000000..5566c73 --- /dev/null +++ b/tests/assertion-violations.test-d.ts @@ -0,0 +1,134 @@ +import { + assertType, + describe, + test, +} from 'vitest' + +import { + collection, + hasLength, + hasSize, + hasValue, + isInteger, + isNumber, + isValidDate, + isSet, + isString, + multipleOf, + validate, +} from '@/index' +import { describe as describeConstraint } from '@/index' + +describe('parameterized assertion violation types', () => { + test('hasLength({ min: 3 }) keeps only supported violation codes', () => { + const [ok, , violations] = validate.sync('ab', [isString, hasLength({ min: 3 })]) + + if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.string': + assertType<[]>(violation.violates.args) + return violation.violates.name + case 'length.min': + assertType<3>(violation.violates.args[0]) + return violation.violates.args[0] + default: + assertType(violation.violates) + return violation.violates + } + }) + } + }) + + test('hasLength({ min: 3, max: 5 }) keeps only the enabled range branches', () => { + const [ok, , violations] = validate.sync('abcdef', [isString, hasLength({ min: 3, max: 5 })]) + + if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.string': + return violation.violates.name + case 'length.min': + return violation.violates.args[0] + case 'length.max': + return violation.violates.args[0] + default: + assertType(violation.violates) + return violation.violates + } + }) + } + }) + + test('hasSize({ exact: 2 }) excludes unrelated size branches', () => { + const [ok, , violations] = validate.sync(new Set([1]), [isSet, hasSize({ exact: 2 })]) + + if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.set': + return violation.violates.name + case 'size.exact': + assertType<2>(violation.violates.args[0]) + return violation.violates.args[0] + default: + assertType(violation.violates) + return violation.violates + } + }) + } + }) + + test('hasValue({ range: [1, 10] }) excludes exact/min/max branches', () => { + const [ok, , violations] = validate.sync(11, [isNumber, hasValue({ range: [1, 10] as const })]) + + if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.number': + return violation.violates.name + case 'number.range': + assertType(violation.violates.args[0]) + return violation.violates.args[0] + default: + assertType(violation.violates) + return violation.violates + } + }) + } + }) + + test('multipleOf(5) keeps the exact step in violation args', () => { + const [ok, , violations] = validate.sync(12, [isNumber, multipleOf(5)]) + + if (!ok) { + collection(violations).map(violation => { + switch (violation.violates.code) { + case 'type.number': + return violation.violates.name + case 'number.multiple-of': + assertType<5>(violation.violates.args[0]) + return violation.violates.args[0] + default: + assertType(violation.violates) + return violation.violates + } + }) + } + }) + + test('standalone integer and valid-date assertions preserve dedicated descriptor codes', () => { + const integerDescriptor = describeConstraint(isInteger) + const validDateDescriptor = describeConstraint(isValidDate) + + if (integerDescriptor.kind === 'assertion') { + assertType<'number.integer'>(integerDescriptor.code) + assertType(integerDescriptor.args) + } + + if (validDateDescriptor.kind === 'assertion') { + assertType<'date.valid'>(validDateDescriptor.code) + assertType(validDateDescriptor.args) + } + }) +}) diff --git a/tests/assertions.test.ts b/tests/assertions.test.ts index 77c620a..fa06502 100644 --- a/tests/assertions.test.ts +++ b/tests/assertions.test.ts @@ -11,11 +11,18 @@ import { hasValue, isBigInt, isBlob, + isError, + isFiniteNumber, isFile, isFunction, + isInteger, isMap, isNaN, + isPromiseLike, + isRegExp, + isSafeInteger, isSet, + isValidDate, multipleOf, oneOf, endsWith, @@ -82,18 +89,6 @@ describe('hasLength', () => { }) }) - test.each([ - { options: { exact: 3 }, value: {} }, - { options: { exact: 3 }, value: null }, - { options: { max: 5 }, value: undefined }, - { options: { min: 3 }, value: new Date() }, - { options: { max: 5, min: 3 }, value: new Blob() }, - ])('unsupported #%#', ({ options, value }) => { - expect(hasLength(options)(value)).toEqual({ - value, - violates: assertionSubject('hasLength', 'length.unsupported-type'), - }) - }) }) describe('oneOf', () => { @@ -129,7 +124,7 @@ describe('oneOf', () => { { value: 1 }, { value: 2 }, { value: 3 }, - ], { equalTo: (a, b) => typeof b === 'object' && 'value' in b && a.value === b.value }).check + ], { equalTo: (a, b) => typeof b === 'object' && b !== null && 'value' in b && a.value === b.value }).check expect(isCorrect({ value: 1 })).toBe(true) expect(isCorrect({ value: 2 })).toBe(true) @@ -158,10 +153,6 @@ describe('string assertions', () => { value: 'Nick', violates: assertionSubject('hasPattern', 'string.pattern', [/^[a-z]+$/]), }) - expect(hasPattern(/^[a-z]+$/)(1)).toEqual({ - value: 1, - violates: assertionSubject('hasPattern', 'string.unsupported-type'), - }) }) test('startsWith', () => { @@ -171,10 +162,6 @@ describe('string assertions', () => { value: 'suffix', violates: assertionSubject('startsWith', 'string.starts-with', ['pre']), }) - expect(startsWith('pre')(false)).toEqual({ - value: false, - violates: assertionSubject('startsWith', 'string.unsupported-type'), - }) }) test('endsWith', () => { @@ -184,10 +171,6 @@ describe('string assertions', () => { value: 'index.js', violates: assertionSubject('endsWith', 'string.ends-with', ['.ts']), }) - expect(endsWith('.ts')(null)).toEqual({ - value: null, - violates: assertionSubject('endsWith', 'string.unsupported-type'), - }) }) }) @@ -205,10 +188,6 @@ describe('numeric and size assertions', () => { value: invalidSet, violates: assertionSubject('hasSize', 'size.max', [1]), }) - expect(hasSize({ min: 1 })([])).toEqual({ - value: [], - violates: assertionSubject('hasSize', 'size.unsupported-type'), - }) }) test('hasValue', () => { @@ -223,10 +202,6 @@ describe('numeric and size assertions', () => { value: 4, violates: assertionSubject('hasValue', 'number.max', [3]), }) - expect(hasValue({ max: 3 })('2')).toEqual({ - value: '2', - violates: assertionSubject('hasValue', 'number.unsupported-type'), - }) }) test('multipleOf', () => { @@ -242,10 +217,6 @@ describe('numeric and size assertions', () => { value: 10, violates: assertionSubject('multipleOf', 'number.multiple-of', [0]), }) - expect(multipleOf(5)('10')).toEqual({ - value: '10', - violates: assertionSubject('multipleOf', 'number.unsupported-type'), - }) }) }) @@ -272,6 +243,26 @@ describe('primitive assertions', () => { }) }) + test('isError', () => { + const value = new TypeError('boom') + + expect(isError.check(value)).toBe(true) + expect(isError(value)).toBe(null) + expect(isError({ message: 'boom' })).toEqual({ + value: { message: 'boom' }, + violates: assertionSubject('isError', 'type.error'), + }) + }) + + test('isFiniteNumber', () => { + expect(isFiniteNumber.check(1)).toBe(true) + expect(isFiniteNumber(1)).toBe(null) + expect(isFiniteNumber(Infinity)).toEqual({ + value: Infinity, + violates: assertionSubject('isFiniteNumber', 'number.finite'), + }) + }) + test('isFile', () => { const value = new File(['payload'], 'test.txt') const invalid = new Blob(['payload']) @@ -295,6 +286,15 @@ describe('primitive assertions', () => { }) }) + test('isInteger', () => { + expect(isInteger.check(1)).toBe(true) + expect(isInteger(1)).toBe(null) + expect(isInteger(1.5)).toEqual({ + value: 1.5, + violates: assertionSubject('isInteger', 'number.integer'), + }) + }) + test('isMap', () => { const value = new Map([['key', 1]]) @@ -315,6 +315,37 @@ describe('primitive assertions', () => { }) }) + test('isPromiseLike', () => { + const value = Promise.resolve(1) + + expect(isPromiseLike.check(value)).toBe(true) + expect(isPromiseLike(value)).toBe(null) + expect(isPromiseLike({})).toEqual({ + value: {}, + violates: assertionSubject('isPromiseLike', 'type.promise-like'), + }) + }) + + test('isRegExp', () => { + const value = /abc/ + + expect(isRegExp.check(value)).toBe(true) + expect(isRegExp(value)).toBe(null) + expect(isRegExp('abc')).toEqual({ + value: 'abc', + violates: assertionSubject('isRegExp', 'type.regexp'), + }) + }) + + test('isSafeInteger', () => { + expect(isSafeInteger.check(1)).toBe(true) + expect(isSafeInteger(1)).toBe(null) + expect(isSafeInteger(Number.MAX_SAFE_INTEGER + 1)).toEqual({ + value: Number.MAX_SAFE_INTEGER + 1, + violates: assertionSubject('isSafeInteger', 'number.safe-integer'), + }) + }) + test('isSet', () => { const value = new Set([1, 2, 3]) @@ -325,4 +356,16 @@ describe('primitive assertions', () => { violates: assertionSubject('isSet', 'type.set'), }) }) + + test('isValidDate', () => { + const value = new Date('2023-01-01') + const invalid = new Date('invalid') + + expect(isValidDate.check(value)).toBe(true) + expect(isValidDate(value)).toBe(null) + expect(isValidDate(invalid)).toEqual({ + value: invalid, + violates: assertionSubject('isValidDate', 'date.valid'), + }) + }) }) diff --git a/tests/builtin-guards.test-d.ts b/tests/builtin-guards.test-d.ts new file mode 100644 index 0000000..44eda35 --- /dev/null +++ b/tests/builtin-guards.test-d.ts @@ -0,0 +1,69 @@ +import type { + InferConstraint, + InferViolations, + ValidationResult, +} from '@/index' + +import { + describe, + expectTypeOf, + test, +} from 'vitest' + +import { + hasValue, + isError, + isFiniteNumber, + isInteger, + isPromiseLike, + isRegExp, + isSafeInteger, + isValidDate, + multipleOf, + validate, +} from '@/index' +import { isPromiseLike as isPromiseLikePredicate } from '@/predicates' + +describe('built-in guard types', () => { + test('preserves the narrowed domain and dedicated violation code of every new guard', () => { + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf>() + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + + expectTypeOf['violates']['code']>().toEqualTypeOf<'type.error'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'number.finite'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'number.integer'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'type.promise-like'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'type.regexp'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'number.safe-integer'>() + expectTypeOf['violates']['code']>().toEqualTypeOf<'date.valid'>() + expectTypeOf['violates']['args']>().toMatchTypeOf() + }) + + test('numeric guards establish domains for bounded and multiple-of refinements', () => { + const finite = validate.sync(4, [isFiniteNumber, hasValue({ min: 1 })]) + const integer = validate.sync(4, [isInteger, multipleOf(2)]) + const safeInteger = validate.sync(4, [isSafeInteger, hasValue({ max: 10 })]) + + expectTypeOf(finite).toMatchTypeOf>() + expectTypeOf(integer).toMatchTypeOf>() + expectTypeOf(safeInteger).toMatchTypeOf>() + expectTypeOf<(typeof integer)[2][number]['violates']['code']>().toEqualTypeOf<'number.integer' | 'number.multiple-of'>() + }) + + test('promise-like predicates narrow to unknown unless a value type is provided', () => { + const value: unknown = {} + + if (isPromiseLikePredicate(value)) { + expectTypeOf(value).toEqualTypeOf>() + } + + if (isPromiseLikePredicate(value)) { + expectTypeOf(value).toEqualTypeOf>() + } + }) +}) diff --git a/tests/combinators.test-d.ts b/tests/combinators.test-d.ts index 6101263..f5cf8be 100644 --- a/tests/combinators.test-d.ts +++ b/tests/combinators.test-d.ts @@ -1,5 +1,9 @@ import type { - ValidationTuple, + AsyncObjectShapeRuleDescriptor, + ShapeRefinement, + ShapeRefinementViolationInput, + SyncShapeRefinement, + ValidationResult, Violation, } from '@/index' @@ -21,17 +25,26 @@ import { union, } from '@/combinators' import { + hasLength, isNumber, isString, matches, + describe as describeConstraint, validate, } from '@/index' describe('combinator types', () => { + test('shape rejects incompatible staged assertion tuples in fields', () => { + shape({ + // @ts-expect-error incompatible clarifying assertion + name: [isNumber, hasLength({ min: 3 })] as const, + }) + }) + test('exact preserves literal types', () => { const result = validate.sync('admin', exact('admin')) - assertType>(result) + assertType>(result) }) test('optional, nullable and nullish affect inferred object types', () => { @@ -49,7 +62,7 @@ describe('combinator types', () => { role: 'admin', }, schema) - assertType { test('tuple preserves positional inference', () => { const result = validate.sync(['admin', undefined], tuple([exact('admin'), optional(isString)])) - assertType>(result) + assertType>(result) }) test('record wraps value inference for dynamic keys', () => { @@ -95,13 +108,13 @@ describe('combinator types', () => { backup: 'admin', }, record(exact('admin'))) - assertType>>(result) + assertType>>(result) }) test('union combines branch inference into a union type', () => { const result = validate.sync('admin', union([exact('admin'), isNumber])) - assertType>(result) + assertType>(result) }) test('union preserves object variant inference', () => { @@ -119,7 +132,7 @@ describe('combinator types', () => { }), ])) - assertType>(result) @@ -140,7 +153,7 @@ describe('combinator types', () => { }), })) - assertType>(result) @@ -159,7 +172,7 @@ describe('combinator types', () => { const extended = profile.extend({ team: isString }) const merged = profile.merge(shape({ role: exact('editor'), team: isString })) - assertType>(validate.sync({ @@ -167,7 +180,7 @@ describe('combinator types', () => { nickname: undefined, }, picked)) - assertType>(validate.sync({ @@ -175,13 +188,13 @@ describe('combinator types', () => { role: 'admin', }, omitted)) - assertType>(validate.sync({}, partialProfile)) - assertType { team: 'validators', }, extended)) - assertType { const registration = shape({ password: isString, confirmPassword: isString, - }).refine(value => { + }).refine(async value => { + assertType<{ + password: string; + confirmPassword: string; + }>(value) + + return [] + }) + const syncRegistration = shape({ + password: isString, + confirmPassword: isString, + }).refine.sync(value => { assertType<{ password: string; confirmPassword: string; @@ -221,13 +245,63 @@ describe('combinator types', () => { const confirmedRegistration = registration.fieldsMatch(['password', 'confirmPassword']) - assertType>(validate.sync({ + }>>>(validate({ + password: 'secret', + confirmPassword: 'secret', + }, registration)) + + assertType>>(validate({ password: 'secret', confirmPassword: 'secret', }, confirmedRegistration)) + + assertType>(validate.sync({ + password: 'secret', + confirmPassword: 'secret', + }, syncRegistration)) + }) + + test('async refine descriptors are marked in shape metadata types', () => { + const schema = shape({ + password: isString, + confirmPassword: isString, + }).refine(async () => [], { + kind: 'passwordConfirmation', + }) + + const descriptor = describeConstraint(schema) + + if (descriptor.kind === 'shape') { + assertType]>(descriptor.rules) + } + }) + + test('object-level refinement types expose async-first and sync-safe names', () => { + assertType>(async value => { + assertType(value.password) + + return [] + }) + + assertType>(value => { + assertType(value.password) + + return [] + }) + + assertType>({ + code: 'shape.fields.mismatch', + args: [[['password'], ['confirmPassword']]], + }) }) test('fieldsMatch also accepts nested path selectors without changing inferred shape types', () => { @@ -238,7 +312,7 @@ describe('combinator types', () => { }), }).fieldsMatch([['password'], ['confirm', 'password']]) - assertType { }), }).fieldsMatch(['password', ['confirm', 'password']]) - assertType true, }, }) @@ -755,7 +757,7 @@ describe('shape object api', () => { }]]) }) - test('refine adds sync object-level rules that run after structural validation', async () => { + test('refine keeps sync callbacks valid in the async-first API', async () => { const registration = shape({ password: isString, confirmPassword: isString, @@ -790,6 +792,72 @@ describe('shape object api', () => { }]]) }) + test('refine awaits async object-level rules after structural validation', async () => { + const registration = shape({ + email: isString, + }).refine(async value => { + await Promise.resolve() + + return value.email === 'taken@example.com' + ? [{ + path: ['email'], + code: 'user.email.taken', + }] + : [] + }) + + expect(await validate({ + email: 'free@example.com', + }, registration)).toEqual([true, { + email: 'free@example.com', + }, []]) + + expect(await validate({ + email: 'taken@example.com', + }, registration)).toEqual([false, { + email: 'taken@example.com', + }, [{ + value: 'taken@example.com', + path: ['email'], + violates: validatorSubject('shape', 'user.email.taken'), + }]]) + }) + + test('refine.sync keeps the explicit sync path safe for validate.sync', () => { + const registration = shape({ + password: isString, + confirmPassword: isString, + }).refine.sync(value => { + return value.password === value.confirmPassword + ? [] + : [{ + path: ['confirmPassword'], + code: 'shape.fields.mismatch', + args: [['password', 'confirmPassword']], + }] + }) + + expect(validate.sync({ + password: 'secret', + confirmPassword: 'secret', + }, registration)).toEqual([true, { + password: 'secret', + confirmPassword: 'secret', + }, []]) + + expect(validate.sync({ + password: 'secret', + confirmPassword: 'different', + }, registration)).toEqual([false, { + password: 'secret', + confirmPassword: 'different', + }, [{ + value: 'different', + path: ['confirmPassword'], + violates: validatorSubject('shape', 'shape.fields.mismatch', [['password', 'confirmPassword']]), + }]]) + }) + test('refine can target nested paths when matching fields from different object levels', () => { const registration = shape({ password: isString, @@ -910,6 +978,94 @@ describe('shape object api', () => { expect(runs).toBe(0) }) + test('refine combines async field validation and async object-level validation in one flow', async () => { + const asyncDomain = createAsyncAssertion('asyncDomain', async value => { + return value === 'blocked@example.com' + ? { + value, + violates: assertionSubject('asyncDomain', 'user.email.blocked'), + } + : null + }) + let runs = 0 + const schema = shape({ + email: [isString, asyncDomain], + confirmEmail: isString, + }).refine(async value => { + runs += 1 + await Promise.resolve() + + return value.email === value.confirmEmail + ? [] + : [{ + path: ['confirmEmail'], + code: 'shape.fields.mismatch', + args: [['email', 'confirmEmail']], + }] + }) + + expect(await validate({ + email: 'blocked@example.com', + confirmEmail: 'blocked@example.com', + }, schema)).toEqual([false, { + email: 'blocked@example.com', + confirmEmail: 'blocked@example.com', + }, [{ + value: 'blocked@example.com', + path: ['email'], + violates: assertionSubject('asyncDomain', 'user.email.blocked'), + }]]) + expect(runs).toBe(0) + + expect(await validate({ + email: 'ok@example.com', + confirmEmail: 'other@example.com', + }, schema)).toEqual([false, { + email: 'ok@example.com', + confirmEmail: 'other@example.com', + }, [{ + value: 'other@example.com', + path: ['confirmEmail'], + violates: validatorSubject('shape', 'shape.fields.mismatch', [['email', 'confirmEmail']]), + }]]) + expect(runs).toBe(1) + }) + + test('validate.sync and matches.sync fail explicitly on async refine callbacks', () => { + const registration = shape({ + email: isString, + }).refine(async () => { + return [{ + code: 'shape.async.unreachable', + }] + }) + + expect(() => validate.sync({ + email: 'taken@example.com', + }, registration)).toThrow('Found asynchronous object-level shape refinement') + expect(() => matches.sync({ + email: 'taken@example.com', + }, registration)).toThrow('Found asynchronous object-level shape refinement') + expect(() => registration.check({ + email: 'taken@example.com', + })).toThrow('Found asynchronous object-level shape refinement') + }) + + test('shape.run keeps async-first refine fallback for custom runners without a sync marker', () => { + const registration = shape({}).refine(() => []) + const bareRunner = ((value: unknown) => { + return value === null + ? [{ + value, + path: [], + violates: validatorSubject('shape', 'type.record'), + }] + : [] + }) as unknown as Validate + + expect(registration.run(bareRunner, {}, [])).toEqual([[]]) + }) + test('fieldsMatch is a thin helper over refine for the common confirmation-field case', () => { const registration = shape({ password: isString, diff --git a/tests/custom-assertions.test-d.ts b/tests/custom-assertions.test-d.ts new file mode 100644 index 0000000..879e39d --- /dev/null +++ b/tests/custom-assertions.test-d.ts @@ -0,0 +1,62 @@ +import { + describe, + expectTypeOf, + test, +} from 'vitest' + +import { + assert, + isString, + refine, + validate, +} from '@/index' + +describe('custom assertion checker types', () => { + test('connects extractor values and checker arguments', () => { + const minLength = refine({ name: 'minLength', bail: false }, [[ + (value: string) => value.length, + (length: number, min: number) => length >= min, + 'custom.min-length', + 3, + ]]) + const result = validate.sync('abcd', [isString, minLength]) + + if (result[0]) expectTypeOf(result[1]).toEqualTypeOf() + + assert(isString.check, { name: 'wrongValue', bail: true }, [ + // @ts-expect-error checker cannot consume the extractor result + [(value: string) => value.length, (value: string) => value.startsWith('x'), 'custom.wrong'], + ]) + refine({ name: 'wrongArgs', bail: false }, [ + // @ts-expect-error checker arguments must accept the constraint args + [(value: string) => value.length, (length: number, min: number) => length >= min, 'custom.wrong', 'three'], + ]) + assert(isString.check, { name: 'wrongInput', bail: true }, [ + // @ts-expect-error extractor must accept the guarded input + [(value: number) => value, (value: number) => value > 0, 'custom.wrong'], + ]) + }) + + test('requires a domain accepted by every extractor in a refinement', () => { + const incompatible = refine({ name: 'incompatible', bail: false }, [ + [(value: string) => value.toUpperCase(), (value: string) => value.length > 0, 'custom.string'], + [(value: number) => value.toFixed(), (value: string) => value.length > 0, 'custom.number'], + ]) + + // @ts-expect-error string is not accepted by the numeric extractor + validate.sync('abc', [isString, incompatible]) + }) + + test('supports generic custom refinement factories', () => { + const minLength = (minimum: Minimum) => refine({ name: 'minLength', bail: false }, [[ + (value: string) => value.length, + (length: number, min: number) => length >= min, + 'custom.min-length', + minimum, + ]]) + const result = validate.sync('abcd', [isString, minLength(3)]) + + if (result[0]) expectTypeOf(result[1]).toEqualTypeOf() + expectTypeOf<(typeof result)[2][number]['violates']['code']>().toEqualTypeOf<'type.string' | 'custom.min-length'>() + }) +}) diff --git a/tests/json-schema.test.ts b/tests/json-schema.test.ts index cfa809c..8391fd6 100644 --- a/tests/json-schema.test.ts +++ b/tests/json-schema.test.ts @@ -21,15 +21,22 @@ import { isDate, isDefined, isEmail, + isError, + isFiniteNumber, isFile, isFunction, + isInteger, isMap, isNaN, isNull, isNumber, + isPromiseLike, + isRegExp, + isSafeInteger, isSet, isString, isSymbol, + isValidDate, meta, multipleOf, nullable, @@ -260,12 +267,15 @@ describe('toJsonSchema', () => { test.each([ [isBigInt, 'bigint values cannot be represented in JSON Schema'], [isBlob, 'Blob instances do not have a stable JSON Schema representation'], + [isError, 'Error instances do not have a stable JSON Schema representation'], [isFile, 'File instances do not have a stable JSON Schema representation'], [isFunction, 'functions cannot be represented in JSON Schema'], [isMap, 'Map instances do not have a stable JSON Schema representation'], [isNaN, 'NaN cannot be represented in JSON Schema'], + [isPromiseLike, 'promise-like values do not have a stable JSON Schema representation'], + [isRegExp, 'regular expressions do not have a stable JSON Schema representation'], [isSet, 'Set instances do not have a stable JSON Schema representation'], - [hasSize({ min: 1 }), 'Map and Set sizes do not have a stable JSON Schema representation'], + [isValidDate, 'Date instances do not have a stable JSON Schema representation'], ] as const)('throws in strict mode for unsupported built-in assertion %s', (assertion, reason) => { expect(() => toJsonSchema(shape({ value: assertion, @@ -274,6 +284,12 @@ describe('toJsonSchema', () => { ) }) + test('throws in strict mode for unsupported built-in refinement export', () => { + expect(() => toJsonSchema(hasSize({ min: 1 }), { mode: 'strict' })).toThrowError( + 'Cannot export assertion at : Map and Set sizes do not have a stable JSON Schema representation' + ) + }) + test('exports remaining supported assertion variants, metadata primitives and optionality inference', () => { const hidden = Symbol('hidden') @@ -295,17 +311,20 @@ describe('toJsonSchema', () => { optionalUnion: union([exact(undefined), isString]), optionalAllOf: [optional(isString), exact(undefined)], optionalEnum: oneOf([undefined, 'draft']), - exactLength: hasLength({ exact: 3 }), - maxLength: hasLength({ max: 5 }), - rangeLength: hasLength({ range: [1, 3] }), - valueExact: hasValue({ exact: 3 }), - valueMin: hasValue({ min: 1 }), - valueMax: hasValue({ max: 10 }), - valueRange: hasValue({ range: [1, 10] }), - valueMultipleOf: multipleOf(5), - textPattern: hasPattern(/^[a-z]+$/), - textPrefix: startsWith('pre'), - textSuffix: endsWith('.ts'), + finiteValue: isFiniteNumber, + integerValue: isInteger, + safeIntegerValue: isSafeInteger, + exactLength: [isString, hasLength({ exact: 3 })], + maxLength: [isString, hasLength({ max: 5 })], + rangeLength: [isString, hasLength({ range: [1, 3] })], + valueExact: [isNumber, hasValue({ exact: 3 })], + valueMin: [isNumber, hasValue({ min: 1 })], + valueMax: [isNumber, hasValue({ max: 10 })], + valueRange: [isNumber, hasValue({ range: [1, 10] })], + valueMultipleOf: [isNumber, multipleOf(5)], + textPattern: [isString, hasPattern(/^[a-z]+$/)], + textPrefix: [isString, startsWith('pre')], + textSuffix: [isString, endsWith('.ts')], [hidden]: isString, }))).toEqual({ type: 'object', @@ -338,69 +357,124 @@ describe('toJsonSchema', () => { allOf: [{ type: 'string' }, {}], }, optionalEnum: {}, + finiteValue: { + type: 'number', + }, + integerValue: { + type: 'integer', + }, + safeIntegerValue: { + type: 'integer', + minimum: Number.MIN_SAFE_INTEGER, + maximum: Number.MAX_SAFE_INTEGER, + }, exactLength: { - anyOf: [{ + allOf: [{ type: 'string', - minLength: 3, - maxLength: 3, }, { - type: 'array', - minItems: 3, - maxItems: 3, + anyOf: [{ + type: 'string', + minLength: 3, + maxLength: 3, + }, { + type: 'array', + minItems: 3, + maxItems: 3, + }], }], }, maxLength: { - anyOf: [{ + allOf: [{ type: 'string', - maxLength: 5, }, { - type: 'array', - maxItems: 5, + anyOf: [{ + type: 'string', + maxLength: 5, + }, { + type: 'array', + maxItems: 5, + }], }], }, rangeLength: { - anyOf: [{ + allOf: [{ type: 'string', - minLength: 1, - maxLength: 3, }, { - type: 'array', - minItems: 1, - maxItems: 3, + anyOf: [{ + type: 'string', + minLength: 1, + maxLength: 3, + }, { + type: 'array', + minItems: 1, + maxItems: 3, + }], }], }, valueExact: { - type: 'number', - const: 3, + allOf: [{ + type: 'number', + }, { + type: 'number', + const: 3, + }], }, valueMin: { - type: 'number', - minimum: 1, + allOf: [{ + type: 'number', + }, { + type: 'number', + minimum: 1, + }], }, valueMax: { - type: 'number', - maximum: 10, + allOf: [{ + type: 'number', + }, { + type: 'number', + maximum: 10, + }], }, valueRange: { - type: 'number', - minimum: 1, - maximum: 10, + allOf: [{ + type: 'number', + }, { + type: 'number', + minimum: 1, + maximum: 10, + }], }, valueMultipleOf: { - type: 'number', - multipleOf: 5, + allOf: [{ + type: 'number', + }, { + type: 'number', + multipleOf: 5, + }], }, textPattern: { - type: 'string', - pattern: '^[a-z]+$', + allOf: [{ + type: 'string', + }, { + type: 'string', + pattern: '^[a-z]+$', + }], }, textPrefix: { - type: 'string', - pattern: '^pre', + allOf: [{ + type: 'string', + }, { + type: 'string', + pattern: '^pre', + }], }, textSuffix: { - type: 'string', - pattern: '\\.ts$', + allOf: [{ + type: 'string', + }, { + type: 'string', + pattern: '\\.ts$', + }], }, }, required: [ @@ -410,6 +484,9 @@ describe('toJsonSchema', () => { 'nullValue', 'passthrough', 'nullableEmpty', + 'finiteValue', + 'integerValue', + 'safeIntegerValue', 'exactLength', 'maxLength', 'rangeLength', @@ -534,25 +611,32 @@ describe('toJsonSchema', () => { emptyMultipleOfDescriptor, badExact: exact({ role: 'admin' }), badEnum: oneOf([{ role: 'admin' }] as never), - invalidExactLength: hasLength({ exact: -1 as never }), - invalidMinLength: hasLength({ min: -1 as never }), - invalidMaxLength: hasLength({ max: -1 as never }), - invalidRangeLength: hasLength({ range: [1, -1] as never }), - invalidValueExact: hasValue({ exact: Number.POSITIVE_INFINITY as never }), - invalidValueMin: hasValue({ min: Number.POSITIVE_INFINITY as never }), - invalidValueMax: hasValue({ max: Number.POSITIVE_INFINITY as never }), - invalidValueRange: hasValue({ range: [1, Number.NaN] as never }), - invalidMultipleOf: multipleOf(0), - invalidPattern: hasPattern(/ok/i), + invalidExactLength: [isString, hasLength({ exact: -1 as never })], + invalidMinLength: [isString, hasLength({ min: -1 as never })], + invalidMaxLength: [isString, hasLength({ max: -1 as never })], + invalidRangeLength: [isString, hasLength({ range: [1, -1] as never })], + invalidValueExact: [isNumber, hasValue({ exact: Number.POSITIVE_INFINITY as never })], + invalidValueMin: [isNumber, hasValue({ min: Number.POSITIVE_INFINITY as never })], + invalidValueMax: [isNumber, hasValue({ max: Number.POSITIVE_INFINITY as never })], + invalidValueRange: [isNumber, hasValue({ range: [1, Number.NaN] as never })], + invalidMultipleOf: [isNumber, multipleOf(0)], + invalidPattern: [isString, hasPattern(/ok/i)], bigInt: isBigInt, blob: isBlob, date: isDate, + error: isError, + finite: isFiniteNumber, file: isFile, fn: isFunction, + integer: isInteger, map: isMap, nan: isNaN, + promise: isPromiseLike, + regexp: isRegExp, + safeInteger: isSafeInteger, set: isSet, symbol: isSymbol, + validDate: isValidDate, validator: bareValidator, weirdDescriptor, }))).toEqual({ @@ -574,25 +658,60 @@ describe('toJsonSchema', () => { emptyMultipleOfDescriptor: {}, badExact: {}, badEnum: {}, - invalidExactLength: {}, - invalidMinLength: {}, - invalidMaxLength: {}, - invalidRangeLength: {}, - invalidValueExact: {}, - invalidValueMin: {}, - invalidValueMax: {}, - invalidValueRange: {}, - invalidMultipleOf: {}, - invalidPattern: {}, + invalidExactLength: { + allOf: [{ type: 'string' }, {}], + }, + invalidMinLength: { + allOf: [{ type: 'string' }, {}], + }, + invalidMaxLength: { + allOf: [{ type: 'string' }, {}], + }, + invalidRangeLength: { + allOf: [{ type: 'string' }, {}], + }, + invalidValueExact: { + allOf: [{ type: 'number' }, {}], + }, + invalidValueMin: { + allOf: [{ type: 'number' }, {}], + }, + invalidValueMax: { + allOf: [{ type: 'number' }, {}], + }, + invalidValueRange: { + allOf: [{ type: 'number' }, {}], + }, + invalidMultipleOf: { + allOf: [{ type: 'number' }, {}], + }, + invalidPattern: { + allOf: [{ type: 'string' }, {}], + }, bigInt: {}, blob: {}, date: {}, + error: {}, + finite: { + type: 'number', + }, file: {}, fn: {}, + integer: { + type: 'integer', + }, map: {}, nan: {}, + promise: {}, + regexp: {}, + safeInteger: { + type: 'integer', + minimum: Number.MIN_SAFE_INTEGER, + maximum: Number.MAX_SAFE_INTEGER, + }, set: {}, symbol: {}, + validDate: {}, validator: {}, weirdDescriptor: {}, }, @@ -623,12 +742,19 @@ describe('toJsonSchema', () => { 'bigInt', 'blob', 'date', + 'error', + 'finite', 'file', 'fn', + 'integer', 'map', 'nan', + 'promise', + 'regexp', + 'safeInteger', 'set', 'symbol', + 'validDate', 'validator', 'weirdDescriptor', ], diff --git a/tests/match.test.ts b/tests/match.test.ts index b2ff38b..decf7c3 100644 --- a/tests/match.test.ts +++ b/tests/match.test.ts @@ -5,10 +5,13 @@ import { } from 'vitest' import { + hasLength, + each, isDefined, isString, matches, } from '@/index' +import { matchesConstraints } from '@/constraints' const expectString = (value: T) => value @@ -29,4 +32,22 @@ describe('matches.sync', () => { expect(matches.sync(value, [isDefined, isString])).toBe(false) }) + + test('returns false for dynamic refinement sequences without a preceding guard', () => { + const staged = [hasLength({ min: 2 })] + + expect(matchesConstraints('nickname', staged as never)).toBe(false) + }) + + test('uses staged refinement checks after a compatible guard succeeds', () => { + expect(matchesConstraints('neo', [isString, hasLength({ min: 2 })])).toBe(true) + expect(matchesConstraints('n', [isString, hasLength({ min: 2 })])).toBe(false) + }) + + test('requires a new guard after a structural validator in dynamic sequences', () => { + const constraints = [each(isString), hasLength({ min: 2 })] + + expect(matchesConstraints(['a', 'b'], constraints as never)).toBe(false) + expect(matchesConstraints(['a', 'b'], [each(isString), isDefined, hasLength({ min: 2 })])).toBe(true) + }) }) diff --git a/tests/metadata.test-d.ts b/tests/metadata.test-d.ts index c4bac99..bc4cc17 100644 --- a/tests/metadata.test-d.ts +++ b/tests/metadata.test-d.ts @@ -1,9 +1,9 @@ import type { + AsyncObjectShapeRuleDescriptor, AssertionDescriptor, ConstraintDescriptor, FieldsMatchObjectShapeRuleDescriptor, - GenericObjectShapeRuleDescriptor, - ValidationTuple, + ValidationResult, ViolationCode, } from '@/index' @@ -36,7 +36,7 @@ describe('metadata and introspection types', () => { role: 'admin', }, schema) - assertType>(result) @@ -82,7 +82,7 @@ describe('metadata and introspection types', () => { assertType<'strict' | 'passthrough'>(descriptor.unknownKeys) assertType, - GenericObjectShapeRuleDescriptor<'passwordConfirmation'>, + AsyncObjectShapeRuleDescriptor<'passwordConfirmation'>, ]>(descriptor.rules) } }) diff --git a/tests/metadata.test.ts b/tests/metadata.test.ts index 6aaecb0..36dede0 100644 --- a/tests/metadata.test.ts +++ b/tests/metadata.test.ts @@ -6,6 +6,8 @@ import { test, } from 'vitest' +import type { Assertion } from '~types' + import { assert, custom, @@ -18,11 +20,16 @@ import { meta, optional, record, + refine, shape, tuple, union, validate, } from '@/index' +import { + checkRefinementAssertion, + runRefinementAssertion, +} from '@/assert' suite('meta', () => { test('attaches metadata without changing validation semantics or mutating the source constraint', () => { @@ -122,6 +129,7 @@ suite('describe', () => { { kind: 'fieldsMatch', selectors: ['password', 'confirmPassword'] }, { kind: 'passwordConfirmation', + async: true, metadata: { fields: ['password', 'confirmPassword'], }, @@ -306,3 +314,93 @@ suite('describe', () => { }) }) }) + +suite('refinement helpers', () => { + test('checks staged refinements through the internal fast-path', () => { + const minLength = refine({ + name: 'minLength', + bail: true, + }, [ + [(value: string) => value.length, (length: number, min: number) => length >= min, 'length.min', 2], + ] as const) + + expect(checkRefinementAssertion(minLength, 'abcd')).toBe(true) + expect(checkRefinementAssertion(minLength, 'a')).toBe(false) + }) + + test('falls back to assertion.check when no internal refinement helper is attached', () => { + const fallback = (((value: unknown) => value === 'ok' ? null : { + value, + violates: { + kind: 'assertion' as const, + name: 'fallback', + code: 'fallback', + args: [], + }, + }) as unknown) as Assertion + + Object.defineProperties(fallback, { + name: { + configurable: true, + value: 'fallback', + }, + bail: { + enumerable: true, + value: true, + }, + constraints: { + enumerable: true, + value: [], + }, + check: { + enumerable: true, + value: (value: unknown): value is 'ok' => value === 'ok', + }, + }) + + expect(checkRefinementAssertion(fallback, 'ok')).toBe(true) + expect(checkRefinementAssertion(fallback, 'nope')).toBe(false) + }) + + test('falls back to direct assertion execution when no internal refinement runner is attached', () => { + const fallback = (((value: unknown) => value === 'ok' ? null : { + value, + violates: { + kind: 'assertion' as const, + name: 'fallback', + code: 'fallback', + args: [], + }, + }) as unknown) as Assertion + + Object.defineProperties(fallback, { + name: { + configurable: true, + value: 'fallback', + }, + bail: { + enumerable: true, + value: true, + }, + constraints: { + enumerable: true, + value: [], + }, + check: { + enumerable: true, + value: (value: unknown): value is 'ok' => value === 'ok', + }, + }) + + expect(runRefinementAssertion(fallback, 'ok')).toBeNull() + expect(runRefinementAssertion(fallback, 'nope')).toEqual({ + value: 'nope', + violates: { + kind: 'assertion', + name: 'fallback', + code: 'fallback', + args: [], + }, + }) + }) +}) diff --git a/tests/predicates.test-d.ts b/tests/predicates.test-d.ts new file mode 100644 index 0000000..f7ae4c9 --- /dev/null +++ b/tests/predicates.test-d.ts @@ -0,0 +1,43 @@ +import { + describe, + expectTypeOf, + test, +} from 'vitest' + +import { + isNumber, + isShape, + isString, +} from '@/predicates' + +describe('isShape types', () => { + test('narrows shorthand and tuple fields while preserving optional keys', () => { + const predicate = isShape({ + id: isNumber, + title: [isString, true], + nickname: [isString, false], + }) + const value: unknown = {} + + if (predicate(value)) { + expectTypeOf(value.id).toEqualTypeOf() + expectTypeOf(value.title).toEqualTypeOf() + expectTypeOf(value.nickname).toEqualTypeOf() + expectTypeOf({ id: 1, title: 'Profile' }).toMatchTypeOf() + expectTypeOf<{ id: number; title: string; nickname?: string }>().toMatchTypeOf() + expectTypeOf(value).toMatchTypeOf<{ id: number; title: string; nickname?: string }>() + expectTypeOf({}).not.toMatchTypeOf() + } + }) + + test('keeps fields optional when required is decided at runtime', () => { + const required = false as boolean + const predicate = isShape({ name: [isString, required] }) + const value: unknown = {} + + if (predicate(value)) { + expectTypeOf({}).toMatchTypeOf() + expectTypeOf(value.name).toEqualTypeOf() + } + }) +}) diff --git a/tests/predicates.test.ts b/tests/predicates.test.ts index dcc74b1..a89e279 100644 --- a/tests/predicates.test.ts +++ b/tests/predicates.test.ts @@ -8,20 +8,27 @@ import { isBlob, isDate, isEmail, + isError, isExact, + isFiniteNumber, isFile, isFunction, + isInteger, isMap, isNaN, isNull, isNumber, isObject, + isPromiseLike, + isRegExp, isRecord, + isSafeInteger, isSet, isShape, isString, isSymbol, isUndefined, + isValidDate, And, Or, Not, @@ -110,6 +117,7 @@ describe('isDate', () => { test('returns true when a value is a valid Date object', () => { expect(isDate(new Date())).toBe(true) expect(isDate(new Date('2023-01-01'))).toBe(true) + expect(isDate(new Date('invalid'))).toBe(true) }) test('returns false when a value is not a valid Date object', () => { @@ -122,6 +130,19 @@ describe('isDate', () => { }) }) +describe('isValidDate', () => { + test('returns true when a value is a valid Date object', () => { + expect(isValidDate(new Date())).toBe(true) + expect(isValidDate(new Date('2023-01-01'))).toBe(true) + }) + + test('returns false when a value is not a valid Date object', () => { + expect(isValidDate(new Date('invalid'))).toBe(false) + expect(isValidDate('2023-01-01')).toBe(false) + expect(isValidDate(null)).toBe(false) + }) +}) + describe('isEmail', () => { test('returns true when a value is email', () => { expect(isEmail('my@test.test')).toBe(true) @@ -139,6 +160,19 @@ describe('isEmail', () => { }) }) +describe('isError', () => { + test('returns true when a value is an Error', () => { + expect(isError(new Error('boom'))).toBe(true) + expect(isError(new TypeError('boom'))).toBe(true) + }) + + test('returns false when a value is not an Error', () => { + expect(isError({ message: 'boom' })).toBe(false) + expect(isError('boom')).toBe(false) + expect(isError(null)).toBe(false) + }) +}) + describe('isExact', () => { test('returns true when a value is equal exactly to the specified one', () => { expect(isExact(1)(1)).toBe(true) @@ -231,6 +265,7 @@ describe('isNumber', () => { test('returns true when a value\'s type is a number', () => { expect(isNumber(1)).toBe(true) expect(isNumber(1.5)).toBe(true) + expect(isNumber(Infinity)).toBe(true) }) test('returns false when a value\'s type is not a number', () => { @@ -240,6 +275,36 @@ describe('isNumber', () => { }) }) +describe('isFiniteNumber', () => { + test('returns true when a value is a finite number', () => { + expect(isFiniteNumber(1)).toBe(true) + expect(isFiniteNumber(1.5)).toBe(true) + expect(isFiniteNumber(-42)).toBe(true) + }) + + test('returns false when a value is not a finite number', () => { + expect(isFiniteNumber(Number.NaN)).toBe(false) + expect(isFiniteNumber(Infinity)).toBe(false) + expect(isFiniteNumber(-Infinity)).toBe(false) + expect(isFiniteNumber('1')).toBe(false) + }) +}) + +describe('isInteger', () => { + test('returns true when a value is an integer', () => { + expect(isInteger(0)).toBe(true) + expect(isInteger(42)).toBe(true) + expect(isInteger(-42)).toBe(true) + }) + + test('returns false when a value is not an integer', () => { + expect(isInteger(1.5)).toBe(false) + expect(isInteger(Number.NaN)).toBe(false) + expect(isInteger(Infinity)).toBe(false) + expect(isInteger('42')).toBe(false) + }) +}) + describe('isObject', () => { test('returns true when a value is an object', () => { expect(isObject({})).toBe(true) @@ -262,6 +327,34 @@ describe('isObject', () => { }) }) +describe('isPromiseLike', () => { + test('returns true when a value is promise-like', () => { + expect(isPromiseLike(Promise.resolve(1))).toBe(true) + expect(isPromiseLike({ then: () => undefined })).toBe(true) + expect(isPromiseLike(Object.assign(() => undefined, { then: () => undefined }))).toBe(true) + }) + + test('returns false when a value is not promise-like', () => { + expect(isPromiseLike({})).toBe(false) + expect(isPromiseLike({ then: true })).toBe(false) + expect(isPromiseLike(null)).toBe(false) + expect(isPromiseLike('promise')).toBe(false) + }) +}) + +describe('isRegExp', () => { + test('returns true when a value is a regular expression', () => { + expect(isRegExp(/abc/)).toBe(true) + expect(isRegExp(new RegExp('abc'))).toBe(true) + }) + + test('returns false when a value is not a regular expression', () => { + expect(isRegExp('abc')).toBe(false) + expect(isRegExp({})).toBe(false) + expect(isRegExp(null)).toBe(false) + }) +}) + describe('isRecord', () => { const a = Symbol('property') const b = Symbol('property') @@ -283,6 +376,21 @@ describe('isRecord', () => { }) }) +describe('isSafeInteger', () => { + test('returns true when a value is a safe integer', () => { + expect(isSafeInteger(0)).toBe(true) + expect(isSafeInteger(Number.MAX_SAFE_INTEGER)).toBe(true) + expect(isSafeInteger(Number.MIN_SAFE_INTEGER)).toBe(true) + }) + + test('returns false when a value is not a safe integer', () => { + expect(isSafeInteger(1.5)).toBe(false) + expect(isSafeInteger(Number.MAX_SAFE_INTEGER + 1)).toBe(false) + expect(isSafeInteger(Infinity)).toBe(false) + expect(isSafeInteger('42')).toBe(false) + }) +}) + describe('isSet', () => { test('returns true when a value is a Set', () => { expect(isSet(new Set())).toBe(true) @@ -322,8 +430,31 @@ describe('isShape', () => { expect(shape({ id: 1, name: 'Alice' })).toBe(true) expect(shape({ id: 1 })).toBe(true) + expect(shape({ id: 1, name: 2 })).toBe(false) expect(shape({ name: 'Alice' })).toBe(false) }) + + test('validates present undefined values through the field predicate', () => { + const stringShape = isShape({ name: [isString, false] }) + const optionalUndefinedShape = isShape({ name: [Or(isString, isUndefined), false] }) + const requiredUndefinedShape = isShape({ name: [isUndefined, true] }) + const shorthandUndefinedShape = isShape({ name: isUndefined }) + + expect(stringShape({ name: undefined })).toBe(false) + expect(optionalUndefinedShape({})).toBe(true) + expect(optionalUndefinedShape({ name: undefined })).toBe(true) + expect(requiredUndefinedShape({})).toBe(false) + expect(requiredUndefinedShape({ name: undefined })).toBe(true) + expect(shorthandUndefinedShape({})).toBe(false) + expect(shorthandUndefinedShape({ name: undefined })).toBe(true) + }) + + test('validates inherited optional properties when they are present', () => { + const shape = isShape({ name: [isString, false] }) + + expect(shape(Object.create({ name: 'Alice' }))).toBe(true) + expect(shape(Object.create({ name: 2 }))).toBe(false) + }) }) describe('isString', () => { @@ -372,17 +503,17 @@ describe('isUndefined', () => { describe('And', () => { test('returns true when a value satisfies all of the predicates', () => { - expect(And(isNumber, (value: number): value is number => isFinite(value))(1)).toBe(true) + expect(And(isNumber, (value: unknown): value is number => isNumber(value) && isFinite(value))(1)).toBe(true) expect(And( isString, - (value: string): value is string => value.length > 3, - (value: string): value is string => value.length < 10 + (value: unknown): value is string => isString(value) && value.length > 3, + (value: unknown): value is string => isString(value) && value.length < 10 )('NickName')).toBe(true) }) test('returns false when a value does not satisfy at least one of the predicates', () => { - expect(And(isNumber, (value: number): value is number => value > 10)(5)).toBe(false) - expect(And(isString, (value: string): value is string => value.length > 0)('')).toBe(false) + expect(And(isNumber, (value: unknown): value is number => isNumber(value) && value > 10)(5)).toBe(false) + expect(And(isString, (value: unknown): value is string => isString(value) && value.length > 0)('')).toBe(false) }) }) diff --git a/tests/validate.test.ts b/tests/validate.test.ts index 5738f1f..940abd7 100644 --- a/tests/validate.test.ts +++ b/tests/validate.test.ts @@ -77,6 +77,7 @@ const createAsyncAssertion = ( }, check: { enumerable: true, + // eslint-disable-next-line @typescript-eslint/no-unused-vars value: (_value: unknown): _value is unknown => true, }, }) @@ -204,14 +205,37 @@ describe('validate', () => { }])) }) + test('throws for dynamic refinement sequences without a preceding guard', () => { + const staged = [hasLength({ min: 2 })] as Assertion[] + + expect(() => validate.sync('abc', staged)).toThrow('Refinement hasLength requires a compatible preceding guard') + }) + + test('evaluates refinements in sync validation after a compatible guard', () => { + expect(validate.sync('neo', [isString, hasLength({ min: 2 })])).toEqual(valid('neo')) + expect(validate.sync('n', [isString, hasLength({ min: 2 })])).toEqual(invalid('n', [{ + value: 'n', + path: [], + violates: assertionSubject('hasLength', 'length.min', [2]), + }])) + }) + + test('rejects async validation for dynamic refinement sequences without a preceding guard', async () => { + const staged = [hasLength({ min: 2 })] as Assertion[] + + await expect(validate('abc', staged)).rejects.toThrow('Refinement hasLength requires a compatible preceding guard') + }) + test('awaits async assertions with bail and stops further checks on failure', async () => { - expect(await validate('', [ + const constraints: Assertion[] = [ createAsyncAssertion('asyncBail', async (value: unknown) => ({ value, violates: assertionSubject('asyncBail', 'asyncBail'), }), true), hasLength({ min: 2 }), - ])).toEqual(invalid('', [{ + ] + + expect(await validate('', constraints)).toEqual(invalid('', [{ value: '', path: [], violates: assertionSubject('asyncBail', 'asyncBail'), @@ -224,6 +248,7 @@ describe('validate', () => { value, violates: assertionSubject('asyncNoBail', 'asyncNoBail'), })), + isString, hasLength({ min: 2 }), ])).toEqual(invalid('', [{ value: '', @@ -239,6 +264,7 @@ describe('validate', () => { test('continues after async bail assertions that succeed', async () => { expect(await validate('', [ createAsyncAssertion('asyncBailPass', async () => null, true), + isString, hasLength({ min: 2 }), ])).toEqual(invalid('', [{ value: '', @@ -250,6 +276,7 @@ describe('validate', () => { test('ignores async assertions without bail when they return null', async () => { expect(await validate('', [ createAsyncAssertion('asyncNoBailPass', async () => null), + isString, hasLength({ min: 2 }), ])).toEqual(invalid('', [{ value: '', diff --git a/tests/validate.tuple.test-d.ts b/tests/validate.tuple.test-d.ts index c9e947b..45e1af0 100644 --- a/tests/validate.tuple.test-d.ts +++ b/tests/validate.tuple.test-d.ts @@ -1,7 +1,9 @@ import type { - ValidationTuple, + Guard, + Refinement, + ValidationResult, Violation, -} from '@/index' +} from '~types' import { describe, @@ -13,13 +15,20 @@ import { collection, each, hasLength, + isNumber, shape, isDefined, isString, + matches, validate, } from '@/index' describe('validate tuple types', () => { + test('built-in assertions expose staged public types', () => { + assertType>(isString) + assertType>(hasLength({ min: 3 })) + }) + const profile = shape({ name: [isDefined, isString], tags: each(isString), @@ -31,7 +40,7 @@ describe('validate tuple types', () => { tags: ['ts'], }, profile) - assertType>(result) @@ -120,11 +129,59 @@ describe('validate tuple types', () => { assertType(violation.violates.args) return String(violation.violates.args[0]) default: - return violation.violates.code + assertType(violation.violates) + return violation.violates } }) assertType(messages) } }) + + test('accepts staged tuples after a compatible guard prefix', () => { + const result = validate.sync('abcd', [isDefined, isString, hasLength({ min: 3 })]) + + assertType>(result) + }) + + test('intersects stages without flattening unions inside a guard domain', () => { + const constraints = [isDefined, isString] + const result = validate.sync('abc', constraints) + + if (result[0]) { + result[1].toUpperCase() + assertType(result[1]) + } + }) + + test('rejects incompatible clarifying assertions in tuples', () => { + // @ts-expect-error incompatible clarifying assertion + validate.sync(12, [isNumber, hasLength({ min: 3 })] as const) + }) + + test('rejects tuples that start with a clarifying assertion', () => { + // @ts-expect-error clarifying assertions require an established domain + validate.sync('abc', [hasLength({ min: 3 })] as const) + }) + + test('rejects standalone clarifying assertions in validation APIs', () => { + // @ts-expect-error clarifying assertions are not standalone validation constraints + validate.sync('abc', hasLength({ min: 3 })) + }) + + test('requires a new guard after a structural validator', () => { + const constraints = [each(isString), hasLength({ min: 2 })] as const + + // @ts-expect-error validators do not establish an assertion domain + validate.sync(['a', 'b'], constraints) + // @ts-expect-error validators do not establish an assertion domain + validate(['a', 'b'], constraints) + // @ts-expect-error validators do not establish an assertion domain + matches.sync(['a', 'b'], constraints) + // @ts-expect-error nested fields obey the same stage rules + shape({ tags: constraints }) + + const result = validate.sync(['a', 'b'], [each(isString), isDefined, hasLength({ min: 2 })]) + assertType>(result) + }) }) diff --git a/tests/violation-codes.test-d.ts b/tests/violation-codes.test-d.ts index 6a67a4d..87c21c4 100644 --- a/tests/violation-codes.test-d.ts +++ b/tests/violation-codes.test-d.ts @@ -8,7 +8,7 @@ declare module '@/index' { import type { KnownViolationSubject, - ObjectShapeRefinementIssue, + ShapeRefinementViolationInput, ViolationArgs, ViolationCode, ViolationEntry, @@ -49,7 +49,7 @@ describe('violation code registry augmentation', () => { const issue = { code: 'shape.password.mismatch' as const, args: [] as const, - } satisfies ObjectShapeRefinementIssue<'shape.password.mismatch'> + } satisfies ShapeRefinementViolationInput<'shape.password.mismatch'> const legacySubject = { kind: 'runtime' as const, diff --git a/tsconfig.json b/tsconfig.json index 738796a..c12b406 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "strict": true, "esModuleInterop": true, "module": "ESNext", "moduleResolution": "Bundler", @@ -9,12 +10,15 @@ "~types/*": ["./types/*"] }, "resolveJsonModule": true, - "target": "ES2017" + "target": "ES2017", + "allowImportingTsExtensions": true }, "include": [ "src/**/*.ts", "src/shims-*.d.ts", "tests/**/*.ts", + "vite.config*.ts", + "vitest.config.ts", "rollup.config.ts" ] } diff --git a/types/index.d.ts b/types/index.d.ts index 70c4db1..f79dbda 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -27,6 +27,9 @@ export type Checker = (val /** Extracts a derived value from the original input before a checker runs. */ export type Extractor = (value: T) => V +/** Public stage marker for assertion pipelines. */ +export type AssertionStage = 'guard' | 'refinement' + /** Origin layer that produced a violation. */ export type ViolationKind = 'assertion' | 'validator' | 'runtime' @@ -63,23 +66,27 @@ type ResolveViolationSubjectArgs; 'length.exact': ViolationCodeEntry<'assertion', 'hasLength', readonly [exact: number]>; 'length.max': ViolationCodeEntry<'assertion', 'hasLength', readonly [max: number]>; 'length.min': ViolationCodeEntry<'assertion', 'hasLength', readonly [min: number]>; 'length.range': ViolationCodeEntry<'assertion', 'hasLength', readonly [range: readonly [number, number]]>; 'length.unsupported-type': ViolationCodeEntry<'assertion', 'hasLength', readonly []>; 'number.exact': ViolationCodeEntry<'assertion', 'hasValue', readonly [exact: number]>; + 'number.finite': ViolationCodeEntry<'assertion', 'isFiniteNumber', readonly []>; + 'number.integer': ViolationCodeEntry<'assertion', 'isInteger', readonly []>; 'number.max': ViolationCodeEntry<'assertion', 'hasValue', readonly [max: number]>; 'number.min': ViolationCodeEntry<'assertion', 'hasValue', readonly [min: number]>; 'number.multiple-of': ViolationCodeEntry<'assertion', 'multipleOf', readonly [step: number]>; 'number.nan': ViolationCodeEntry<'assertion', 'isNaN', readonly []>; 'number.range': ViolationCodeEntry<'assertion', 'hasValue', readonly [range: readonly [number, number]]>; + 'number.safe-integer': ViolationCodeEntry<'assertion', 'isSafeInteger', readonly []>; 'number.unsupported-type': ViolationCodeEntry<'assertion', 'hasValue' | 'multipleOf', readonly []>; 'runtime.rejection': ViolationCodeEntry<'runtime', 'validate', readonly [reason: unknown]>; 'shape.fields.mismatch': ViolationCodeEntry< 'validator', 'shape', - readonly [selectors: readonly [ObjectShapeFieldSelector, ObjectShapeFieldSelector]] + readonly [selectors: readonly [ShapeFieldSelector, ShapeFieldSelector]] >; 'shape.unknown-key': ViolationCodeEntry<'validator', 'shape', readonly []>; 'size.exact': ViolationCodeEntry<'assertion', 'hasSize', readonly [exact: number]>; @@ -102,12 +109,15 @@ export interface ViolationCodeRegistry { 'type.blob': ViolationCodeEntry<'assertion', 'isBlob', readonly []>; 'type.boolean': ViolationCodeEntry<'assertion', 'isBoolean', readonly []>; 'type.date': ViolationCodeEntry<'assertion', 'isDate', readonly []>; + 'type.error': ViolationCodeEntry<'assertion', 'isError', readonly []>; 'type.file': ViolationCodeEntry<'assertion', 'isFile', readonly []>; 'type.function': ViolationCodeEntry<'assertion', 'isFunction', readonly []>; 'type.map': ViolationCodeEntry<'assertion', 'isMap', readonly []>; 'type.null': ViolationCodeEntry<'assertion', 'isNull', readonly []>; 'type.number': ViolationCodeEntry<'assertion', 'isNumber', readonly []>; + 'type.promise-like': ViolationCodeEntry<'assertion', 'isPromiseLike', readonly []>; 'type.record': ViolationCodeEntry<'validator', 'shape' | 'discriminatedUnion' | 'record', readonly []>; + 'type.regexp': ViolationCodeEntry<'assertion', 'isRegExp', readonly []>; 'type.set': ViolationCodeEntry<'assertion', 'isSet', readonly []>; 'type.string': ViolationCodeEntry<'assertion', 'isString', readonly []>; 'type.symbol': ViolationCodeEntry<'assertion', 'isSymbol', readonly []>; @@ -225,7 +235,7 @@ export declare const collection: (violations: readonly V[]) export type ConstraintMetadata = Readonly> /** Public descriptor entry for additional assertion-level checks. */ -export interface AssertionDescriptorConstraint< +export interface AssertionConstraintDescriptor< C extends string = string, A extends readonly unknown[] = readonly unknown[], > { @@ -234,7 +244,7 @@ export interface AssertionDescriptorConstraint< } /** Shared descriptor shape returned by `describe(...)`. */ -export interface ConstraintDescriptorBase { +export interface BaseConstraintDescriptor { readonly kind: K; readonly metadata?: ConstraintMetadata } @@ -243,8 +253,8 @@ export interface ConstraintDescriptorBase { export interface AssertionDescriptor< C extends string = string, A extends readonly unknown[] = readonly unknown[], - T extends readonly AssertionDescriptorConstraint[] = readonly AssertionDescriptorConstraint[], -> extends ConstraintDescriptorBase<'assertion'> { + T extends readonly AssertionConstraintDescriptor[] = readonly AssertionConstraintDescriptor[], +> extends BaseConstraintDescriptor<'assertion'> { readonly name: string; readonly bail: boolean; readonly code: C; @@ -253,17 +263,17 @@ export interface AssertionDescriptor< } /** Generic fallback descriptor for custom validators without structural instrumentation. */ -export type ValidatorDescriptor = ConstraintDescriptorBase<'validator'> +export type OpaqueValidatorDescriptor = BaseConstraintDescriptor<'validator'> /** Public extension descriptor for custom validators that expose their own `describe()` contract. */ -export interface CustomConstraintDescriptor extends ConstraintDescriptorBase { +export interface CustomConstraintDescriptor extends BaseConstraintDescriptor { readonly [key: string]: unknown } /** Descriptor for sequential arrays of constraints used in a single slot. */ export interface AllOfConstraintDescriptor< T extends readonly unknown[] = readonly ConstraintDescriptor[], -> extends ConstraintDescriptorBase<'allOf'> { +> extends BaseConstraintDescriptor<'allOf'> { readonly constraints: T } @@ -271,42 +281,42 @@ export interface AllOfConstraintDescriptor< export interface WrapperConstraintDescriptor< K extends 'optional' | 'nullable' | 'nullish' = 'optional' | 'nullable' | 'nullish', C = ConstraintDescriptor, -> extends ConstraintDescriptorBase { +> extends BaseConstraintDescriptor { readonly child: C } /** Descriptor for `each(...)`. */ export interface EachConstraintDescriptor< C = ConstraintDescriptor, -> extends ConstraintDescriptorBase<'each'> { +> extends BaseConstraintDescriptor<'each'> { readonly item: C } /** Descriptor for `tuple(...)`. */ export interface TupleConstraintDescriptor< T extends readonly unknown[] = readonly ConstraintDescriptor[], -> extends ConstraintDescriptorBase<'tuple'> { +> extends BaseConstraintDescriptor<'tuple'> { readonly items: T } /** Descriptor for `union(...)`. */ export interface UnionConstraintDescriptor< T extends readonly unknown[] = readonly ConstraintDescriptor[], -> extends ConstraintDescriptorBase<'union'> { +> extends BaseConstraintDescriptor<'union'> { readonly branches: T } /** Descriptor for `record(...)`. */ export interface RecordConstraintDescriptor< C = ConstraintDescriptor, -> extends ConstraintDescriptorBase<'record'> { +> extends BaseConstraintDescriptor<'record'> { readonly values: C } /** Descriptor for `discriminatedUnion(...)`. */ export interface DiscriminatedUnionConstraintDescriptor< V = Readonly>, -> extends ConstraintDescriptorBase<'discriminatedUnion'> { +> extends BaseConstraintDescriptor<'discriminatedUnion'> { readonly key: PropertyKey; readonly variants: V } @@ -317,29 +327,37 @@ export interface ObjectShapeRuleDescriptorBase { readonly metadata?: ConstraintMetadata } -/** Generic compact descriptor for sync object-level rules added via `.refine(...)`. */ -export type GenericObjectShapeRuleDescriptor< +/** Generic compact descriptor for sync-safe object-level rules. */ +export type SyncObjectShapeRuleDescriptor< K extends string = 'refine', > = ObjectShapeRuleDescriptorBase +/** Compact descriptor for object-level rules registered through the async-first `.refine(...)` API. */ +export interface AsyncObjectShapeRuleDescriptor< + K extends string = 'refine', +> extends ObjectShapeRuleDescriptorBase { + readonly async: true +} + /** Descriptor for the built-in `.fieldsMatch(...)` helper. */ export interface FieldsMatchObjectShapeRuleDescriptor< - Left extends ObjectShapeFieldSelector = ObjectShapeFieldSelector, - Right extends ObjectShapeFieldSelector = ObjectShapeFieldSelector, + Left extends ShapeFieldSelector = ShapeFieldSelector, + Right extends ShapeFieldSelector = ShapeFieldSelector, > extends ObjectShapeRuleDescriptorBase<'fieldsMatch'> { readonly selectors: readonly [Left, Right] } /** Machine-readable summary of object-level rules registered on a shape. */ export type ObjectShapeRuleDescriptor = - | GenericObjectShapeRuleDescriptor + | SyncObjectShapeRuleDescriptor + | AsyncObjectShapeRuleDescriptor | FieldsMatchObjectShapeRuleDescriptor /** Descriptor for `shape(...)`. */ export interface ShapeConstraintDescriptor< F = Readonly>, R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], -> extends ConstraintDescriptorBase<'shape'> { +> extends BaseConstraintDescriptor<'shape'> { readonly unknownKeys: UnknownKeysMode; readonly fields: F; readonly rules: R @@ -349,7 +367,7 @@ export interface ShapeConstraintDescriptor< export type BuiltInConstraintDescriptor = | AssertionDescriptor | AllOfConstraintDescriptor - | ValidatorDescriptor + | OpaqueValidatorDescriptor | WrapperConstraintDescriptor | EachConstraintDescriptor | TupleConstraintDescriptor @@ -368,9 +386,13 @@ export type ConstraintDescriptor = BuiltInConstraintDescriptor | CustomConstrain * `type LengthConstraint = AssertionConstraint` */ export type AssertionConstraint< - T = unknown, - V = unknown, - A extends readonly unknown[] = readonly unknown[], + // Defaults erase heterogeneous checker signatures; concrete tuples retain their types. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T = any, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + V = any, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + A extends readonly unknown[] = any[], C extends string = string > = readonly [ Extractor, @@ -381,13 +403,13 @@ export type AssertionConstraint< /** Maps an assertion checker tuple into its public descriptor entry. */ export type DescribeAssertionConstraint = - C extends AssertionConstraint - ? AssertionDescriptorConstraint + C extends readonly [unknown, unknown, infer Code extends string, ...infer A] + ? AssertionConstraintDescriptor : never /** Maps an assertion checker tuple into the violation subject it can produce. */ export type AssertionConstraintSubject = - C extends AssertionConstraint + C extends readonly [unknown, unknown, infer Code extends string, ...infer A] ? { kind: 'assertion'; name: N; @@ -403,6 +425,8 @@ export type DescribeAssertionConstraintTuple> +declare const assertionStageBrand: unique symbol + /** * Leaf-level validator that checks a single value and either succeeds with `null` * or returns a structured violation. @@ -415,20 +439,42 @@ export type Assertion< Code extends string = string, A extends readonly unknown[] = readonly unknown[], Name extends string = string, + Stage extends AssertionStage = AssertionStage, > = ((value: unknown) => MaybePromise + Stage extends 'refinement' + ? AssertionConstraintSubject + : { + kind: 'assertion'; + name: Name; + code: Code; + args: A; + } | AssertionConstraintSubject >, 'path'> | null>) & { readonly name: Name; readonly bail: boolean; readonly constraints: C; readonly check: Predicate; + readonly [assertionStageBrand]: Stage; } +/** Assertion stage that establishes the base domain for subsequent checks. */ +export type Guard< + T = unknown, + C extends readonly AssertionConstraint[] = readonly AssertionConstraint[], + Code extends string = string, + A extends readonly unknown[] = readonly unknown[], + Name extends string = string, +> = Assertion + +/** Assertion stage that validates properties inside an already established domain. */ +export type Refinement< + T = unknown, + C extends readonly AssertionConstraint[] = readonly AssertionConstraint[], + Code extends string = string, + A extends readonly unknown[] = readonly unknown[], + Name extends string = string, +> = Assertion + /** * Any reusable validation unit: either a leaf `Assertion` or a composed `Validator`. * @@ -437,14 +483,77 @@ export type Assertion< */ export type Constraint = Assertion | Validator +type ConstraintSequenceState< + Value, + Ready extends boolean, +> = { + value: Value; + ready: Ready; +} + +type ApplyConstraintStep< + State extends ConstraintSequenceState, + Step extends Constraint, +> = + [Step] extends [Refinement] + ? State['ready'] extends true + ? [State['value']] extends [Input] + ? ConstraintSequenceState + : never + : never + : Step extends Validator + ? ConstraintSequenceState + : Step extends Assertion + ? ConstraintSequenceState + : never + +type CompatibleConstraintTupleState< + T extends readonly Constraint[], + State extends ConstraintSequenceState = ConstraintSequenceState, +> = + T extends readonly [infer First extends Constraint, ...infer Rest extends readonly Constraint[]] + ? ApplyConstraintStep extends infer Next + ? [Next] extends [never] + ? never + : Next extends ConstraintSequenceState + ? CompatibleConstraintTupleState + : never + : never + : State + +/** Tuple of sequential constraints with stage-aware assertion compatibility checks. */ +export type CompatibleConstraintTuple = + number extends T['length'] + ? T + : T extends readonly [Constraint, ...Constraint[]] + ? CompatibleConstraintTupleState extends never + ? never + : T + : T + +/** One-or-many constraint input after applying staged assertion compatibility checks. */ +export type CompatibleConstraints = + C extends readonly Constraint[] + ? CompatibleConstraintTuple + : C extends Refinement + ? never + : C extends Constraint + ? C + : never + /** Extracts the validated TypeScript type from a single constraint. */ export type InferConstraint = - C extends Assertion + C extends Assertion ? T : C extends Validator ? T : never +type InferConstraintIntersection = + (C extends unknown ? (value: InferConstraint) => void : never) extends (value: infer Output) => void + ? Output + : never + /** * Extracts the validated TypeScript type from one or many constraints. * @@ -460,22 +569,28 @@ export type InferConstraints = C extends readonly [] ? unknown : C extends readonly unknown[] - ? UnionToIntersection> + ? number extends C['length'] + ? InferConstraintIntersection + : Intersect<{ [K in keyof C]: InferConstraint }> : InferConstraint /** Internal async runner signature used by composed validators. */ -export type Validate = ( +export type Validate = (( value: unknown, - constraints: MaybeMany, + constraints: CompatibleConstraints>, path?: PropertyKey[] -) => Promise +) => Promise) & { + readonly sync?: false +} /** Internal sync runner signature used by composed validators. */ -export type ValidateSync = ( +export type ValidateSync = (( value: unknown, - constraints: MaybeMany, + constraints: CompatibleConstraints>, path?: PropertyKey[] -) => Violation[] +) => Violation[]) & { + readonly sync: true +} /** Internal union of async and sync runner signatures. */ export type ValidateLike = Validate | ValidateSync @@ -489,18 +604,18 @@ export type Validation = F extends Validate export type UnknownKeysMode = 'passthrough' | 'strict' /** Field selector accepted by shape helpers that can point to the current level or a nested path. */ -export type ObjectShapeFieldSelector = PropertyKey | readonly PropertyKey[] +export type ShapeFieldSelector = PropertyKey | readonly PropertyKey[] -type ResolveObjectShapeRefinementIssueCode = COrA extends string ? COrA : string -type ResolveObjectShapeRefinementIssueArgs = [COrA] extends [readonly unknown[]] +type ResolveShapeRefinementViolationCode = COrA extends string ? COrA : string +type ResolveShapeRefinementViolationArgs = [COrA] extends [readonly unknown[]] ? COrA : ViolationArgs -/** Machine-readable issue returned by an object-level shape refinement. */ -export type ObjectShapeRefinementIssue< +/** Machine-readable violation input returned by an object-level shape refinement. */ +export type ShapeRefinementViolationInput< COrA extends string | readonly unknown[] = string, - C extends string = ResolveObjectShapeRefinementIssueCode, - A extends readonly unknown[] = ResolveObjectShapeRefinementIssueArgs, + C extends string = ResolveShapeRefinementViolationCode, + A extends readonly unknown[] = ResolveShapeRefinementViolationArgs, > = { path?: PropertyKey[]; code: C; @@ -512,18 +627,68 @@ export type ObjectShapeRefinementIssue< value?: unknown; } -/** Sync object-level rule that runs after the base shape has validated successfully. */ -export type ObjectShapeRefinement< +/** Sync-safe object-level rule that runs after the base shape has validated successfully. */ +export type SyncShapeRefinement< T, - I extends ObjectShapeRefinementIssue = ObjectShapeRefinementIssue, + I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, > = ( value: T ) => MaybeMany | null | undefined +/** Async-first object-level rule that runs after the base shape has validated successfully. */ +export type ShapeRefinement< + T, + I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, +> = ( + value: T +) => MaybePromise | null | undefined> + +type AsyncObjectShapeRuleDescriptorOf> = + Omit & AsyncObjectShapeRuleDescriptor + +/** Explicitly sync-safe callable helper exposed as `shape(...).refine.sync(...)`. */ +export interface ShapeRefineMethodSync< + D extends ShapeDescriptor = ShapeDescriptor, + M extends UnknownKeysMode = UnknownKeysMode, + R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], + RI extends ShapeRefinementViolationInput = never, +> { + ( + refinement: SyncShapeRefinement, I> + ): ObjectShape], RI | I>; + < + const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, + const RD extends SyncObjectShapeRuleDescriptor = SyncObjectShapeRuleDescriptor<'refine'> + >( + refinement: SyncShapeRefinement, I>, + descriptor: RD + ): ObjectShape; +} + +/** Async-first callable shape helper exposed as `shape(...).refine(...)`. */ +export interface ShapeRefineMethod< + D extends ShapeDescriptor = ShapeDescriptor, + M extends UnknownKeysMode = UnknownKeysMode, + R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], + RI extends ShapeRefinementViolationInput = never, +> { + ( + refinement: ShapeRefinement, I> + ): ObjectShape], RI | I>; + < + const I extends ShapeRefinementViolationInput = ShapeRefinementViolationInput, + const RD extends SyncObjectShapeRuleDescriptor = SyncObjectShapeRuleDescriptor<'refine'> + >( + refinement: ShapeRefinement, I>, + descriptor: RD + ): ObjectShape], RI | I>; + sync: ShapeRefineMethodSync; +} + type KnownCodeViolation = Violation> -type ShapeRefinementIssueSubject = - I extends ObjectShapeRefinementIssue +type ShapeRefinementIssueSubject = + I extends ShapeRefinementViolationInput ? C extends KnownViolationCode ? { kind: 'validator'; @@ -534,55 +699,57 @@ type ShapeRefinementIssueSubject = : ViolationSubject : never -type ShapeRefinementIssueViolation = - I extends ObjectShapeRefinementIssue +type ShapeRefinementIssueViolation = + I extends ShapeRefinementViolationInput ? Violation> : never -type InferObjectDescriptorViolations = { - [K in keyof D]: InferMaybeManyViolations +type InferShapeViolations = { + [K in keyof D]: InferViolations }[keyof D] /** Maps a single constraint into the union of violations it can produce. */ export type InferConstraintViolations = - C extends Assertion + C extends Guard ? Violation<{ kind: 'assertion'; name: Name; code: Code; args: Args; } | AssertionConstraintSubject> + : C extends Refinement + ? Violation> : C extends ObjectShape ? KnownCodeViolation<'type.record'> | (M extends 'strict' ? KnownCodeViolation<'shape.unknown-key'> : never) - | InferObjectDescriptorViolations + | InferShapeViolations | ShapeRefinementIssueViolation : C extends OptionalValidator - ? InferMaybeManyViolations + ? InferViolations : C extends NullableValidator - ? InferMaybeManyViolations + ? InferViolations : C extends NullishValidator - ? InferMaybeManyViolations + ? InferViolations : C extends EachValidator - ? KnownCodeViolation<'type.array'> | InferMaybeManyViolations + ? KnownCodeViolation<'type.array'> | InferViolations : C extends TupleValidator ? KnownCodeViolation<'type.array'> | KnownCodeViolation<'tuple.length'> - | InferMaybeManyViolations + | InferViolations : C extends UnionValidator - ? KnownCodeViolation<'union.no-match'> | InferMaybeManyViolations + ? KnownCodeViolation<'union.no-match'> | InferViolations : C extends DiscriminatedUnionValidator ? KnownCodeViolation<'type.record'> | KnownCodeViolation<'union.invalid-discriminator'> - | InferMaybeManyViolations + | InferViolations : C extends RecordValidator - ? KnownCodeViolation<'type.record'> | InferMaybeManyViolations + ? KnownCodeViolation<'type.record'> | InferViolations : C extends Validator ? Violation : never /** Maps one-or-many constraints into the union of violations they can produce. */ -export type InferMaybeManyViolations> = +export type InferViolations> = C extends readonly [] ? never : C extends readonly Constraint[] @@ -598,7 +765,7 @@ export type ValidationSuccess = [ok: true, validated: T, violations: []] export type ValidationFailure = [ok: false, validated: unknown, violations: V[]] /** - * The result tuple returned by `validate(...)` and `validate.sync(...)`. + * The result returned by `validate(...)` and `validate.sync(...)`. * * Example: * `const [ok, validated, violations] = await validate(value, schema)` @@ -606,10 +773,7 @@ export type ValidationFailure = [ok: false, val * Example: * `if (ok) validated.name.toUpperCase()` */ -export type ValidationTuple = ValidationSuccess | ValidationFailure - -/** Alias for `ValidationTuple`. */ -export type ValidationResult = ValidationTuple +export type ValidationResult = ValidationSuccess | ValidationFailure /** Attaches read-only metadata to a constraint without changing validation semantics. */ export declare const meta: (constraint: C, metadata: M) => C @@ -644,22 +808,27 @@ export interface DescribedValidator< export declare const custom: (validator: V) => V /** Descriptor that maps object keys to one or many constraints. */ -export type ObjectDescriptor = Record> +export type ShapeDescriptor = Record> + +/** Shape descriptor with stage-aware compatibility checks applied to every field slot. */ +export type CompatibleShapeDescriptor = { + [K in keyof D]: CompatibleConstraints +} -/** Runtime type inferred from an object descriptor. */ -export type InferObjectDescriptor = { +/** Runtime type inferred from a shape descriptor. */ +export type InferShape = { [K in keyof D]: InferConstraints } /** Descriptor produced by `.partial()` where every field accepts `undefined`. */ -export type PartialObjectDescriptor = { +export type PartialShapeDescriptor = { [K in keyof D]: Validator | undefined> } /** Utility type for overriding descriptor keys from left to right. */ -export type MergeObjectDescriptors< - Left extends ObjectDescriptor, - Right extends ObjectDescriptor, +export type MergeShapeDescriptors< + Left extends ShapeDescriptor, + Right extends ShapeDescriptor, > = Omit & Right /** @@ -669,67 +838,58 @@ export type MergeObjectDescriptors< * `const user = shape({ name: isString }).strict()` */ export interface ObjectShape< - D extends ObjectDescriptor = ObjectDescriptor, + D extends ShapeDescriptor = ShapeDescriptor, M extends UnknownKeysMode = 'passthrough', R extends readonly ObjectShapeRuleDescriptor[] = readonly ObjectShapeRuleDescriptor[], - RI extends ObjectShapeRefinementIssue = never, -> extends Validator> { + RI extends ShapeRefinementViolationInput = never, +> extends Validator> { readonly descriptor: D; readonly unknownKeys: M; - refine( - refinement: ObjectShapeRefinement, I> - ): ObjectShape], RI | I>; - refine< - const I extends ObjectShapeRefinementIssue = ObjectShapeRefinementIssue, - const RD extends GenericObjectShapeRuleDescriptor = GenericObjectShapeRuleDescriptor<'refine'> - >( - refinement: ObjectShapeRefinement, I>, - descriptor: RD - ): ObjectShape; - fieldsMatch( + readonly refine: ShapeRefineMethod; + fieldsMatch( keys: K - ): ObjectShape], RI | ObjectShapeRefinementIssue<'shape.fields.mismatch'>>; + ): ObjectShape], RI | ShapeRefinementViolationInput<'shape.fields.mismatch'>>; strict(): ObjectShape; passthrough(): ObjectShape; pick(keys: K): ObjectShape, M, [], never>; omit(keys: K): ObjectShape, M, [], never>; - partial(): ObjectShape, M, [], never>; - extend(descriptor: E): ObjectShape, M, [], never>; - merge( - shape: ObjectShape - ): ObjectShape, M, [], never>; + partial(): ObjectShape, M, [], never>; + extend(descriptor: E): ObjectShape, M, [], never>; + merge( + shape: ObjectShape + ): ObjectShape, M, [], never>; } /** Helper that maps a single constraint into its public `describe(...)` result. */ export type DescribeConstraint = - C extends Assertion + C extends Assertion ? AssertionDescriptor> - : C extends ObjectShape - ? ShapeConstraintDescriptor, R> & { readonly unknownKeys: M } + : C extends ObjectShape + ? ShapeConstraintDescriptor, R> & { readonly unknownKeys: M } : C extends OptionalValidator - ? WrapperConstraintDescriptor<'optional', DescribeMaybeMany> + ? WrapperConstraintDescriptor<'optional', DescribeConstraints> : C extends NullableValidator - ? WrapperConstraintDescriptor<'nullable', DescribeMaybeMany> + ? WrapperConstraintDescriptor<'nullable', DescribeConstraints> : C extends NullishValidator - ? WrapperConstraintDescriptor<'nullish', DescribeMaybeMany> + ? WrapperConstraintDescriptor<'nullish', DescribeConstraints> : C extends EachValidator - ? EachConstraintDescriptor> + ? EachConstraintDescriptor> : C extends TupleValidator ? TupleConstraintDescriptor> : C extends UnionValidator ? UnionConstraintDescriptor> : C extends DiscriminatedUnionValidator - ? DiscriminatedUnionConstraintDescriptor> + ? DiscriminatedUnionConstraintDescriptor> : C extends RecordValidator - ? RecordConstraintDescriptor> + ? RecordConstraintDescriptor> : C extends DescribedValidator ? D & { readonly metadata?: ConstraintMetadata } : C extends Validator - ? ValidatorDescriptor + ? OpaqueValidatorDescriptor : never /** Helper that maps a one-or-many constraint slot into its public `describe(...)` result. */ -export type DescribeMaybeMany> = +export type DescribeConstraints> = C extends readonly [infer Only] ? Only extends Constraint ? DescribeConstraint @@ -743,14 +903,14 @@ export type DescribeMaybeMany> = : never /** Helper that maps object descriptors into their `describe(...)` field tree. */ -export type DescribeObjectDescriptor = { - [K in keyof D]: DescribeMaybeMany +export type DescribeShapeDescriptor = { + [K in keyof D]: DescribeConstraints } /** Helper that maps tuples of constraints into tuples of descriptors. */ export type DescribeConstraintTuple[]> = { - readonly [K in keyof T]: DescribeMaybeMany -} & ReadonlyArray> + readonly [K in keyof T]: DescribeConstraints +} & ReadonlyArray> declare const optionalValidatorBrand: unique symbol declare const nullableValidatorBrand: unique symbol diff --git a/vite.config.basic.ts b/vite.config.basic.ts index 978c0c2..c9382c2 100644 --- a/vite.config.basic.ts +++ b/vite.config.basic.ts @@ -6,8 +6,8 @@ export default defineConfig({ resolve: { alias: { - '@': resolve(__dirname, './src'), - '~types': resolve(__dirname, './types/'), + '@': resolve(import.meta.dirname, './src'), + '~types': resolve(import.meta.dirname, './types/'), }, }, }) \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 7e6ea68..81c4eff 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,30 +3,60 @@ import { mergeConfig, } from 'vite' -import dts from 'vite-plugin-dts' +import dts from 'unplugin-dts/vite' import { join, resolve, } from 'node:path' +import { + cp, + readFile, + readdir, + writeFile, +} from 'node:fs/promises' + +import packageJson from './package.json' with { type: 'json' } + +import basic from './vite.config.basic.ts' -import { name } from './package.json' +const writeModuleDeclarations = async () => { + const outputDirectory = resolve(import.meta.dirname, 'dist') + await cp(resolve(import.meta.dirname, 'types'), join(outputDirectory, 'types'), { recursive: true }) + const files = (await readdir(outputDirectory, { recursive: true })).filter(file => file.endsWith('.d.ts')) -import basic from './vite.config.basic' + for (const file of files) { + const source = await readFile(join(outputDirectory, file), 'utf8') + + for (const [declarationExtension, moduleExtension] of [ + ['.d.ts', '.js'], + ['.d.mts', '.mjs'], + ['.d.cts', '.cjs'], + ]) { + const content = source.replace(/(from\s+|import\()(['"])(\.[^'"]+)\2/g, (_, prefix, quote, specifier: string) => { + const target = specifier === '../types' + ? './types/index' + : specifier.replace(/^\.\.\/types\//, './types/') + + return `${prefix}${quote}${target.replace(/\.(?:js|mjs|cjs)$/, '')}${moduleExtension}${quote}` + }) + await writeFile(join(outputDirectory, file.replace(/\.d\.ts$/, declarationExtension)), content) + } + } +} export default mergeConfig(basic, defineConfig({ build: { lib: { - name, - formats: ['es', 'cjs'], + name: packageJson.name, entry: { - assert: resolve(__dirname, './src/assert.ts'), - assertions: resolve(__dirname, './src/assertions.ts'), - combinators: resolve(__dirname, './src/combinators.ts'), - 'json-schema': resolve(__dirname, './src/json-schema.ts'), - metadata: resolve(__dirname, './src/metadata.ts'), - predicates: resolve(__dirname, './src/predicates.ts'), - index: resolve(__dirname, './src/index.ts'), + assert: resolve(import.meta.dirname, './src/assert.ts'), + assertions: resolve(import.meta.dirname, './src/assertions.ts'), + combinators: resolve(import.meta.dirname, './src/combinators.ts'), + 'json-schema': resolve(import.meta.dirname, './src/json-schema.ts'), + metadata: resolve(import.meta.dirname, './src/metadata.ts'), + predicates: resolve(import.meta.dirname, './src/predicates.ts'), + index: resolve(import.meta.dirname, './src/index.ts'), }, fileName: (format, entryName) => `${entryName}.${{ cjs: 'cjs', @@ -34,12 +64,13 @@ export default mergeConfig(basic, defineConfig({ }[format as 'es' | 'cjs']}`, }, minify: false, - rollupOptions: { - output: { + rolldownOptions: { + output: (['es', 'cjs'] as const).map(format => ({ + format, exports: 'named', - dir: join(__dirname, '/dist'), - chunkFileNames: '[name].[format].js', - }, + dir: resolve(import.meta.dirname, 'dist'), + chunkFileNames: `[name]-[hash].${format === 'es' ? 'mjs' : 'cjs'}`, + })), }, }, @@ -48,8 +79,11 @@ export default mergeConfig(basic, defineConfig({ exclude: [ 'scripts/**/*.*', 'tests/**/*.*', + 'vite.config*.ts', + 'vitest.config.ts', ], insertTypesEntry: true, staticImport: true, + afterBuild: writeModuleDeclarations, })], })) diff --git a/vitest.config.ts b/vitest.config.ts index 896b4a9..04e2db8 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,7 @@ import { mergeConfig, } from 'vitest/config' -import basic from './vite.config.basic' +import basic from './vite.config.basic.ts' export default mergeConfig(basic, defineConfig({ test: { @@ -11,6 +11,7 @@ export default mergeConfig(basic, defineConfig({ '**/*.{test,spec}.?(c|m)[jt]s?(x)', ], coverage: { + enabled: true, provider: 'v8', include: ['src/**'], reporter: [ diff --git a/yarn.lock b/yarn.lock index 7296622..59dde7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,17 +22,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-string-parser@npm:7.25.7" - checksum: 10c0/73ef2ceb81f8294678a0afe8ab0103729c0370cac2e830e0d5128b03be5f6a2635838af31d391d763e3c5a4460ed96f42fd7c9b552130670d525be665913bc4c - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-string-parser@npm:7.27.1" - checksum: 10c0/8bda3448e07b5583727c103560bcf9c4c24b3c1051a4c516d4050ef69df37bb9a4734a585fe12725b8c2763de0a265aa1e909b485a4e3270b7cfd3e4dbe4b602 +"@babel/helper-string-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-string-parser@npm:7.29.7" + checksum: 10c0/194bc0f1716e396d5ffde56ad6119745fb9557662c98611590e5e454906783a4ccb21ce93056b8eb69a4909044834e45d96e50ac695bbe9e3221648fe033c06c languageName: node linkType: hard @@ -43,17 +36,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-validator-identifier@npm:7.25.7" - checksum: 10c0/07438e5bf01ab2882a15027fdf39ac3b0ba1b251774a5130917907014684e2f70fef8fd620137ca062c4c4eedc388508d2ea7a3a7d9936a32785f4fe116c68c0 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-validator-identifier@npm:7.28.5" - checksum: 10c0/42aaebed91f739a41f3d80b72752d1f95fd7c72394e8e4bd7cdd88817e0774d80a432451bcba17c2c642c257c483bf1d409dd4548883429ea9493a3bc4ab0847 +"@babel/helper-validator-identifier@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-identifier@npm:7.29.7" + checksum: 10c0/4795354e7ae0dcafa72de1cd04ec51252dc1498517170beaf019e03effc5b7bf13c6b21a3949a77e07b8125be7f106ed1131350d8ebd4566ae874094a726d62b languageName: node linkType: hard @@ -68,434 +54,264 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.25.3": - version: 7.25.8 - resolution: "@babel/parser@npm:7.25.8" +"@babel/parser@npm:^7.29.7": + version: 7.29.9 + resolution: "@babel/parser@npm:7.29.9" dependencies: - "@babel/types": "npm:^7.25.8" + "@babel/types": "npm:^7.29.8" bin: parser: ./bin/babel-parser.js - checksum: 10c0/a1a13845b7e8dda4c970791814a4bbf60004969882f18f470e260ad822d2e1f8941948f851e9335895563610f240fa6c98481ce8019865e469502bbf21daafa4 + checksum: 10c0/171b16eb4527cdbbb72cb98710f91acb22356e2c40196ba3b7a1b84efa8c55d0b0992f399c8c675c3e17f67fd133676c5c4118e5f20db243f427c8b29b0c3f40 languageName: node linkType: hard -"@babel/parser@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/parser@npm:7.29.0" +"@babel/types@npm:^7.29.7, @babel/types@npm:^7.29.8": + version: 7.29.8 + resolution: "@babel/types@npm:7.29.8" dependencies: - "@babel/types": "npm:^7.29.0" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/333b2aa761264b91577a74bee86141ef733f9f9f6d4fc52548e4847dc35dfbf821f58c46832c637bfa761a6d9909d6a68f7d1ed59e17e4ffbb958dc510c17b62 + "@babel/helper-string-parser": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + checksum: 10c0/be7c279f0abf2a086c633e21b49c7ca80275d05283cc5a268b67a708c9914bd0c944f1422b3eb3cb37682a2af5d560abf520ccf9b01b53ecbfe6b71fbc3fdde6 languageName: node linkType: hard -"@babel/types@npm:^7.25.8": - version: 7.25.8 - resolution: "@babel/types@npm:7.25.8" - dependencies: - "@babel/helper-string-parser": "npm:^7.25.7" - "@babel/helper-validator-identifier": "npm:^7.25.7" - to-fast-properties: "npm:^2.0.0" - checksum: 10c0/55ca2d6df6426c98db2769ce884ce5e9de83a512ea2dd7bcf56c811984dc14351cacf42932a723630c5afcff2455809323decd645820762182f10b7b5252b59f +"@bcoe/v8-coverage@npm:^1.0.2": + version: 1.0.2 + resolution: "@bcoe/v8-coverage@npm:1.0.2" + checksum: 10c0/1eb1dc93cc17fb7abdcef21a6e7b867d6aa99a7ec88ec8207402b23d9083ab22a8011213f04b2cf26d535f1d22dc26139b7929e6c2134c254bd1e14ba5e678c3 languageName: node linkType: hard -"@babel/types@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/types@npm:7.29.0" +"@cacheable/memory@npm:^2.2.0": + version: 2.2.0 + resolution: "@cacheable/memory@npm:2.2.0" dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/23cc3466e83bcbfab8b9bd0edaafdb5d4efdb88b82b3be6728bbade5ba2f0996f84f63b1c5f7a8c0d67efded28300898a5f930b171bb40b311bca2029c4e9b4f + "@cacheable/utils": "npm:^2.5.0" + "@keyv/bigmap": "npm:^1.3.1" + hookified: "npm:^1.15.1" + keyv: "npm:^5.6.0" + checksum: 10c0/c74889eb09871be0696065778fff013a498ddc73b538d113c2cb6ece361746f2959fbddfa4ce03ce53c9259998be05949e393212e72413dbd07616744eabd261 languageName: node linkType: hard -"@bcoe/v8-coverage@npm:^1.0.2": - version: 1.0.2 - resolution: "@bcoe/v8-coverage@npm:1.0.2" - checksum: 10c0/1eb1dc93cc17fb7abdcef21a6e7b867d6aa99a7ec88ec8207402b23d9083ab22a8011213f04b2cf26d535f1d22dc26139b7929e6c2134c254bd1e14ba5e678c3 +"@cacheable/utils@npm:^2.5.0": + version: 2.5.0 + resolution: "@cacheable/utils@npm:2.5.0" + dependencies: + hashery: "npm:^1.5.1" + keyv: "npm:^5.6.0" + checksum: 10c0/99e901accd71eeb0bce91484d6c66d7ef2c731b541561eb5dc9ea7fed78bdc0b65e5dd2a80edde50191143bcfc5f238fc4742475b32e82d43b43eea224038e35 languageName: node linkType: hard -"@commitlint/cli@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/cli@npm:20.4.3" +"@commitlint/cli@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/cli@npm:21.2.3" dependencies: - "@commitlint/format": "npm:^20.4.3" - "@commitlint/lint": "npm:^20.4.3" - "@commitlint/load": "npm:^20.4.3" - "@commitlint/read": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" + "@commitlint/config-conventional": "npm:^21.2.3" + "@commitlint/format": "npm:^21.2.3" + "@commitlint/lint": "npm:^21.2.3" + "@commitlint/load": "npm:^21.2.3" + "@commitlint/read": "npm:^21.2.3" + "@commitlint/types": "npm:^21.2.3" tinyexec: "npm:^1.0.0" - yargs: "npm:^17.0.0" + yargs: "npm:^18.0.0" bin: - commitlint: ./cli.js - checksum: 10c0/1f54b6870a16548a6af189336c479ed49ab8da615fbaec4c8ff3124a115db0a38bdbd07d49afe27e0d1ac35ba723640532db2b4f3c96720515eca0aa9265747d + commitlint: cli.js + checksum: 10c0/544e86b5e5af0cbae5a55b5643dd9a8565b7f00e435378b46eb372a0b46adf330577b7d5c25abddbb30d4aa3ad78b114b2514ca936aeff3b310eb6e5f13dfc9c languageName: node linkType: hard -"@commitlint/config-conventional@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/config-conventional@npm:20.4.3" +"@commitlint/config-conventional@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/config-conventional@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" - conventional-changelog-conventionalcommits: "npm:^9.2.0" - checksum: 10c0/c7c6fb0b3201b17fae3a3e488b20795e7facbda511017d96939029f83d320567c310576ec9074f9536a3c811ea5d8038b3ddc92905c198e24c00b1a2759a8c84 + "@commitlint/types": "npm:^21.2.3" + conventional-changelog-conventionalcommits: "npm:^10.0.0" + checksum: 10c0/584a7b436d6f2aace31f9a35c48da213aa5eed01f7d21ca6db3800992e59c0f52894e54d2006f1c42739b8edce509387bd2cba783a5b18088db58da3b2afbf44 languageName: node linkType: hard -"@commitlint/config-validator@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/config-validator@npm:20.4.3" +"@commitlint/config-validator@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/config-validator@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^21.2.3" ajv: "npm:^8.11.0" - checksum: 10c0/e65f2bd3cc00b0b8b46c9bf830f78c90c60eb0d864d8e3cf02badf83196637ce7c0c9febabd91bb66d9b77138bc3e741416fff1fb4ffa4054a877cac75f2bae7 + checksum: 10c0/54641610bf9863ba085be7e806a34324e67b8ee8e3f4c12fe7c3f1116a385729eabd0d16f42823d60128bc6de99742e31112bc54c70ef45b5c439cad6fd95d8d languageName: node linkType: hard -"@commitlint/ensure@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/ensure@npm:20.4.3" +"@commitlint/ensure@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/ensure@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" - lodash.camelcase: "npm:^4.3.0" - lodash.kebabcase: "npm:^4.1.1" - lodash.snakecase: "npm:^4.1.1" - lodash.startcase: "npm:^4.4.0" - lodash.upperfirst: "npm:^4.3.1" - checksum: 10c0/aa1f42317af156f8af1314311f9195f6d8150807e5d5971432bd086b8ead39c8c6166bf426d413790bb105e015f9c556de4d69083cb0a897293bed56b884d6a4 + "@commitlint/types": "npm:^21.2.3" + es-toolkit: "npm:^1.46.0" + checksum: 10c0/55314de93bc297624c62e10f68622928fde9b3a8e9522d0f8c1b54e31c86d5b1e98518682673651e7e5894be821d683099b23eb26aae300b0e7958ee62b340bc languageName: node linkType: hard -"@commitlint/execute-rule@npm:^20.0.0": - version: 20.0.0 - resolution: "@commitlint/execute-rule@npm:20.0.0" - checksum: 10c0/a1035ae9d6842489e617f18b244e6e53ac44b051b54501b9544019d33da924c877d7b893bfa2a66ad325a9c2ff65b11137d5383743e31d3e0b606decc1619584 +"@commitlint/execute-rule@npm:^21.0.1": + version: 21.0.1 + resolution: "@commitlint/execute-rule@npm:21.0.1" + checksum: 10c0/84fd03f20e808b9f4b68193410d9be90c54b3599f81e82ac23847e90ccba4b52768cfd1ee637931a6ca90575eaefa6ed5fc43a5398d52a4e2d6bef6dd354227e languageName: node linkType: hard -"@commitlint/format@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/format@npm:20.4.3" +"@commitlint/format@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/format@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^21.2.3" picocolors: "npm:^1.1.1" - checksum: 10c0/e221f61a07eaf917185b8f30ff6405f642495a4b199cbfd4a0f130a11068ed5afceb938790fb35383aea9fed101fd4777dd169962a9a721e50851cdadf8044a2 + checksum: 10c0/d87685e1e10d3338d4d1cab929af03d938070b1bfed79c16ef6fb54a95e1f5e11d56ed7ac188e332b0db8ab25302426087b2152a58334c09c6764497fd2b3465 languageName: node linkType: hard -"@commitlint/is-ignored@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/is-ignored@npm:20.4.3" +"@commitlint/is-ignored@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/is-ignored@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^21.2.3" semver: "npm:^7.6.0" - checksum: 10c0/bc118de0aabc63dc82b85e96119489e3b008c5db63c1d9dfccd6c465ba422734a0b80f465382ac38a9fb07b9a80995e4eeb529214ad3c2fe93d80e505fb43fbd + checksum: 10c0/bf2b8a47149c537cb90bacc9dec12cfeae891597490e3919813deacaec3b64821268c2595c84327641b9b1e5988e2668362ecca4cdf011141deac1ad3956f56b languageName: node linkType: hard -"@commitlint/lint@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/lint@npm:20.4.3" +"@commitlint/lint@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/lint@npm:21.2.3" dependencies: - "@commitlint/is-ignored": "npm:^20.4.3" - "@commitlint/parse": "npm:^20.4.3" - "@commitlint/rules": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - checksum: 10c0/e6af7cbbf935a393a970352674f88ec3e05f08c9f88f638b81279febf77c1795d75112e27248f7788a14e0747ec06fa2ab3efca5d0836070d35b0283fa515817 + "@commitlint/is-ignored": "npm:^21.2.3" + "@commitlint/parse": "npm:^21.2.3" + "@commitlint/rules": "npm:^21.2.3" + "@commitlint/types": "npm:^21.2.3" + checksum: 10c0/fe572e141f84b2a289e7c33356b8adaecc75d09e5e4cb07f173e0d80ea5f1070897536729fab5f1e0123e77a06982c97c3a417ae84b46877d7bd0913e382b647 languageName: node linkType: hard -"@commitlint/load@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/load@npm:20.4.3" +"@commitlint/load@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/load@npm:21.2.3" dependencies: - "@commitlint/config-validator": "npm:^20.4.3" - "@commitlint/execute-rule": "npm:^20.0.0" - "@commitlint/resolve-extends": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" + "@commitlint/config-validator": "npm:^21.2.3" + "@commitlint/execute-rule": "npm:^21.0.1" + "@commitlint/resolve-extends": "npm:^21.2.3" + "@commitlint/types": "npm:^21.2.3" cosmiconfig: "npm:^9.0.1" cosmiconfig-typescript-loader: "npm:^6.1.0" + es-toolkit: "npm:^1.46.0" is-plain-obj: "npm:^4.1.0" - lodash.mergewith: "npm:^4.6.2" picocolors: "npm:^1.1.1" - checksum: 10c0/80fb52e259492a130701cfe637e9c06a6151a980bd51f0d2c011f7e973f7188d8c3d52d078302b75e4e767d618ebdca3a49935268a38e807298bf08fa7f5e49d + checksum: 10c0/b79e17711857fe6a14459e1acb63f233d39bcfacdab8ebbbc60bca0f87843768e9c6a40ccea5e8ab6e095c3eb79d74c61d910e620eef33fe673a034494b74e50 languageName: node linkType: hard -"@commitlint/message@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/message@npm:20.4.3" - checksum: 10c0/16f7a67d17df916830a9d6b2cdbaef0d680afcc47e9de53b18c7580bcbb50d8241b86c0e26a4ae71bd1d4a1025b318eb6c920e75fbc97aee7341744d4ef5dcbc +"@commitlint/message@npm:^21.2.0": + version: 21.2.0 + resolution: "@commitlint/message@npm:21.2.0" + checksum: 10c0/f3f97efd382970316aac689545b7f7bc278e114cce0540469ba56539f2ab78089b84bd0137c82be0908d1e251890e035348acd369c24c4011abf6445d8ec928f languageName: node linkType: hard -"@commitlint/parse@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/parse@npm:20.4.3" +"@commitlint/parse@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/parse@npm:21.2.3" dependencies: - "@commitlint/types": "npm:^20.4.3" - conventional-changelog-angular: "npm:^8.2.0" - conventional-commits-parser: "npm:^6.3.0" - checksum: 10c0/404fecad36b1586a611f1a56e8f7b5c39482c5f010949029020e23103464ab03bece04083557443ec3055917e632118c8ba52cc2c3ab76bac95b704d9338a272 + "@commitlint/types": "npm:^21.2.3" + conventional-changelog-angular: "npm:^9.0.0" + conventional-commits-parser: "npm:^7.0.0" + checksum: 10c0/5692b5298bf9668d45cde1a33087bf40c17ccf9c6421dbe314740b5a9779386261532386c4dfae421d82c80dbc1742ca5a78150dfeb6891421570b4206bb343b languageName: node linkType: hard -"@commitlint/read@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/read@npm:20.4.3" +"@commitlint/read@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/read@npm:21.2.3" dependencies: - "@commitlint/top-level": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - git-raw-commits: "npm:^4.0.0" - minimist: "npm:^1.2.8" + "@commitlint/top-level": "npm:^21.2.0" + "@commitlint/types": "npm:^21.2.3" + "@conventional-changelog/git-client": "npm:^3.0.0" tinyexec: "npm:^1.0.0" - checksum: 10c0/3e7f88ad9bd780f6b0ec6511d00d222aa61d1fd8fad98d7dfdf9d98d112b655c5ae0c2d575709008f01ceb049e134ccfc2fb21ea5948a93ad60c65fada289c49 + checksum: 10c0/7a0421c9135dbef584ecf8e4aa8d3eee2536cf575dab8dbcbf7ea8d79753fd31df5701cb877f413189763f1d2e0e6fbc7b6e2061b35b15acca1ed602a0b28ca3 languageName: node linkType: hard -"@commitlint/resolve-extends@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/resolve-extends@npm:20.4.3" +"@commitlint/resolve-extends@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/resolve-extends@npm:21.2.3" dependencies: - "@commitlint/config-validator": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - global-directory: "npm:^4.0.1" - import-meta-resolve: "npm:^4.0.0" - lodash.mergewith: "npm:^4.6.2" + "@commitlint/config-validator": "npm:^21.2.3" + "@commitlint/types": "npm:^21.2.3" + es-toolkit: "npm:^1.46.0" + global-directory: "npm:^5.0.0" resolve-from: "npm:^5.0.0" - checksum: 10c0/09220329bacdcb0c90bb93d18e9d57bb832a64a2683bd39d183e07b19131aa19999c61abf30159989432755997852e3fb78227333b46ad662dd62b7c91c01a78 + checksum: 10c0/527fb212ced6b5a1009f2a7ee972e58369196030d846d23f59a141c0f22e1b22fc19bfec0ff2739d63f72fa764d62dd78c0204d435f1134d62e0b88ea1defcd4 languageName: node linkType: hard -"@commitlint/rules@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/rules@npm:20.4.3" +"@commitlint/rules@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/rules@npm:21.2.3" dependencies: - "@commitlint/ensure": "npm:^20.4.3" - "@commitlint/message": "npm:^20.4.3" - "@commitlint/to-lines": "npm:^20.0.0" - "@commitlint/types": "npm:^20.4.3" - checksum: 10c0/03348731a9d01acd65a7e5a19c6a24d1fb5418bad09c9d4bde40081a1c75d7e06157049a8f8973ecdfa640f3c1dd8f70b8ce678e6a3456b855198dcaa51ca667 + "@commitlint/ensure": "npm:^21.2.3" + "@commitlint/message": "npm:^21.2.0" + "@commitlint/to-lines": "npm:^21.0.1" + "@commitlint/types": "npm:^21.2.3" + checksum: 10c0/cb15fe727d0a0a8845b472eef1dc61885862ee23e1afd154e55a288a486fbc2a228ec87f0152a58a4d27646cc0a19eddee0855c15a3f528653b5c19512f0e115 languageName: node linkType: hard -"@commitlint/to-lines@npm:^20.0.0": - version: 20.0.0 - resolution: "@commitlint/to-lines@npm:20.0.0" - checksum: 10c0/49bc05eb0649adc6f4740a4f3976cc43402080bd9d90567c654180f90c0b6deb9a922b0efbde38567ac1def8f63cc506589124cc7f862e3914d30e13f29997c0 +"@commitlint/to-lines@npm:^21.0.1": + version: 21.0.1 + resolution: "@commitlint/to-lines@npm:21.0.1" + checksum: 10c0/bdf0640e260e11aeb6c6450095477ff123d2792c19307aba11ffaf35170ec8f05244d106edfecfb979fe5c1559b821db77a9d844261ef443895cee1d847e15ca languageName: node linkType: hard -"@commitlint/top-level@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/top-level@npm:20.4.3" +"@commitlint/top-level@npm:^21.2.0": + version: 21.2.0 + resolution: "@commitlint/top-level@npm:21.2.0" dependencies: escalade: "npm:^3.2.0" - checksum: 10c0/52a1f59677d3d2e4bdd998bbde6e7e3848ce52372c7bd394ad24555820cadbf6820886bc33bf42a8c73878c6f0b211334ce93c4f4fbf6d8e8022b72c5c39ebd5 + checksum: 10c0/2358c836db34a0405b8e7e4eda38ca120d80dafa0b6ca84b12460131649d7fbdad35e5b68de19db51cf3a4725ae8a721f8f1f6909dcd161d60e3953d96f775f3 languageName: node linkType: hard -"@commitlint/types@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/types@npm:20.4.3" +"@commitlint/types@npm:^21.2.3": + version: 21.2.3 + resolution: "@commitlint/types@npm:21.2.3" dependencies: - conventional-commits-parser: "npm:^6.3.0" + conventional-commits-parser: "npm:^7.0.0" picocolors: "npm:^1.1.1" - checksum: 10c0/2181f9696f95b828551521e576fe786f81de5b5669e0ac876808e86811587011f7b78644f97c1d6623cc2bad68e0592416327080f14f153deccc20c5d295367e + checksum: 10c0/64a2dd651b6c54b0e332a77d5e39fac823cf5750f0f9d8f6f562b97143ee2b76b689537a2d2bf98e64258b5d951fb0e21bc83bcf7969ce4b084f8a588d933740 languageName: node linkType: hard -"@cspotcode/source-map-support@npm:^0.8.0": - version: 0.8.1 - resolution: "@cspotcode/source-map-support@npm:0.8.1" +"@conventional-changelog/git-client@npm:^3.0.0": + version: 3.1.2 + resolution: "@conventional-changelog/git-client@npm:3.1.2" dependencies: - "@jridgewell/trace-mapping": "npm:0.3.9" - checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/aix-ppc64@npm:0.27.3" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-arm64@npm:0.27.3" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-arm@npm:0.27.3" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-x64@npm:0.27.3" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/darwin-arm64@npm:0.27.3" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/darwin-x64@npm:0.27.3" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/freebsd-arm64@npm:0.27.3" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/freebsd-x64@npm:0.27.3" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-arm64@npm:0.27.3" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-arm@npm:0.27.3" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-ia32@npm:0.27.3" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-loong64@npm:0.27.3" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-mips64el@npm:0.27.3" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-ppc64@npm:0.27.3" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-riscv64@npm:0.27.3" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-s390x@npm:0.27.3" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-x64@npm:0.27.3" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/netbsd-arm64@npm:0.27.3" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/netbsd-x64@npm:0.27.3" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openbsd-arm64@npm:0.27.3" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openbsd-x64@npm:0.27.3" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openharmony-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openharmony-arm64@npm:0.27.3" - conditions: os=openharmony & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/sunos-x64@npm:0.27.3" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-arm64@npm:0.27.3" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-ia32@npm:0.27.3" - conditions: os=win32 & cpu=ia32 + "@simple-libs/child-process-utils": "npm:^2.0.0" + "@simple-libs/stream-utils": "npm:^2.0.0" + semver: "npm:^7.5.2" + peerDependencies: + conventional-commits-filter: ^6.0.1 + conventional-commits-parser: ^7.1.2 + peerDependenciesMeta: + conventional-commits-filter: + optional: true + conventional-commits-parser: + optional: true + checksum: 10c0/ee07d87638e5a2ded3d14498fc9530f6023651573dd56ee729b587def16d13f94ae362c5b0c2a17acda538bad0787f7c4df5d36ee7164a92b9eb79cc0e039145 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-x64@npm:0.27.3" - conditions: os=win32 & cpu=x64 +"@conventional-changelog/template@npm:^1.4.0": + version: 1.4.0 + resolution: "@conventional-changelog/template@npm:1.4.0" + checksum: 10c0/052ac38b43f67b2572d101ced1dee2691a2ac3828cbc1041738cf1646b956ff0fb3e87258ec59f46eb2c3fcc9a68bb89f90b8dcb1e354880f2c71d8f5ef3a021 languageName: node linkType: hard @@ -517,32 +333,32 @@ __metadata: languageName: node linkType: hard -"@eslint/config-array@npm:^0.23.3": - version: 0.23.3 - resolution: "@eslint/config-array@npm:0.23.3" +"@eslint/config-array@npm:^0.23.5": + version: 0.23.5 + resolution: "@eslint/config-array@npm:0.23.5" dependencies: - "@eslint/object-schema": "npm:^3.0.3" + "@eslint/object-schema": "npm:^3.0.5" debug: "npm:^4.3.1" minimatch: "npm:^10.2.4" - checksum: 10c0/7c19027acf9110cc542513ff9f3ca73a61d127e900c24f0e8e4d5e18aa22baf08d1d5bc386563d2f9311095f3b7898fe9b627b590fe9232b745ef60d4443cf9f + checksum: 10c0/b24833c4c76e78ee075d306cd3f095db46b2db0f90cc13a6ee6e4275f9889731c05bf5403ab5fefb79c756e07ac9184ed0e04570341382f9eccbccc80e6d1a0c languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.5.2": - version: 0.5.3 - resolution: "@eslint/config-helpers@npm:0.5.3" +"@eslint/config-helpers@npm:^0.7.0": + version: 0.7.0 + resolution: "@eslint/config-helpers@npm:0.7.0" dependencies: - "@eslint/core": "npm:^1.1.1" - checksum: 10c0/c836476e839a79dcdc9f7e0013057cfe0341162180d50e5a08668edb4b4b6c520a3174011469f6ef02efd2affd092263c020e89d0a3452c801427b0ac003549a + "@eslint/core": "npm:^1.2.1" + checksum: 10c0/fd40d57d6f1db49f7b647048b88a433dc7f6522ef3edf855a43cb526ef4fc40622ceed0dc8de2e03d254f30f8e035370570de1d4bd8e7c2b1200131451e0d331 languageName: node linkType: hard -"@eslint/core@npm:^1.1.1": - version: 1.1.1 - resolution: "@eslint/core@npm:1.1.1" +"@eslint/core@npm:^1.2.1": + version: 1.2.1 + resolution: "@eslint/core@npm:1.2.1" dependencies: "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/129c654c78afc1f6d61dccb0ce841be667f09f052f7d5642614b6ba5eeebd579ca6cc336d7b750d88625e61f7aad22fdd62bf83847fbfc10cc3e58cfe6c5072e + checksum: 10c0/10979b40588ecfef771fcb5013a542a35fb30692cc95a65f3481b0b36fbd89f5679efeb30d57f4eed35203d859aabace2a620177d6c536f71b299a1af2f3398f languageName: node linkType: hard @@ -558,20 +374,20 @@ __metadata: languageName: node linkType: hard -"@eslint/object-schema@npm:^3.0.3": - version: 3.0.3 - resolution: "@eslint/object-schema@npm:3.0.3" - checksum: 10c0/4abbb7cba5419dce46ae8aa8e979fa190f2e906a8e1b5a8e22e4489f62a68dea3967679f66acbc0c3ef89f33252a7460e39fc2d6f2b4f616a137f3514eda4784 +"@eslint/object-schema@npm:^3.0.5": + version: 3.0.5 + resolution: "@eslint/object-schema@npm:3.0.5" + checksum: 10c0/1db337431f520b99e9edda64ef5fafd7ec6a029843eeb608753025125b6649d861d843cffafafd3c4e37926d7d5f9ec0c6a8e3665c13c3da2144e8132892e92e languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.6.1": - version: 0.6.1 - resolution: "@eslint/plugin-kit@npm:0.6.1" +"@eslint/plugin-kit@npm:^0.7.3": + version: 0.7.3 + resolution: "@eslint/plugin-kit@npm:0.7.3" dependencies: - "@eslint/core": "npm:^1.1.1" + "@eslint/core": "npm:^1.2.1" levn: "npm:^0.4.1" - checksum: 10c0/f8354a7b92cc41e7a55d51986d192134be84f9dc0c91b5e649d075d733b56981c4ca8bf4460d54120c4c87b47984167bad2cb9bceb303f11b0a3bad22b3ed06a + checksum: 10c0/2daebaedcfbd261478e8b87dfb46d3118f48277c19eb298483ebc6f3b438e9688b86ddca13b3aeb08dfb06be00fb6073506852386aa124645c1170e7e33d140c languageName: node linkType: hard @@ -622,6 +438,13 @@ __metadata: languageName: node linkType: hard +"@isaacs/cliui@npm:^9.0.0": + version: 9.0.0 + resolution: "@isaacs/cliui@npm:9.0.0" + checksum: 10c0/971063b7296419f85053dacd0a0285dcadaa3dfc139228b23e016c1a9848121ad4aa5e7fcca7522062014e1eb6239a7424188b9f2cba893a79c90aae5710319c + languageName: node + linkType: hard + "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -631,10 +454,23 @@ __metadata: languageName: node linkType: hard -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: 10c0/0dbc9e29bc640bbbdc5b9876d2859c69042bfcf1423c1e6421bcca53e826660bff4e41c7d4bcb8dbea696404231a6f902f76ba41835d049e20f2dd6cffb713bf +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b + languageName: node + linkType: hard + +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 languageName: node linkType: hard @@ -645,13 +481,6 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: 10c0/0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 - languageName: node - linkType: hard - "@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": version: 1.5.0 resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" @@ -659,24 +488,14 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.5.5": - version: 1.5.5 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" - checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 +"@jridgewell/sourcemap-codec@npm:^1.6.0": + version: 1.6.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.6.0" + checksum: 10c0/b5be700e45a775f218589c3466c4ffea630582b4988657652da464e5ab8a7d18bf928ee4fd2363fb346ede4bea9c6ff0bae05a538358c4565ece6199531b5f72 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.0.3" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.31": +"@jridgewell/trace-mapping@npm:0.3.31, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.31": version: 0.3.31 resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: @@ -686,57 +505,122 @@ __metadata: languageName: node linkType: hard -"@microsoft/api-extractor-model@npm:7.33.4": - version: 7.33.4 - resolution: "@microsoft/api-extractor-model@npm:7.33.4" +"@keyv/bigmap@npm:^1.3.1": + version: 1.3.1 + resolution: "@keyv/bigmap@npm:1.3.1" dependencies: - "@microsoft/tsdoc": "npm:~0.16.0" - "@microsoft/tsdoc-config": "npm:~0.18.1" - "@rushstack/node-core-library": "npm:5.20.3" - checksum: 10c0/c71569e59a5f876c600f38240ed8d12c1e4c908a2a6af9cd75f3b22334d7c950b54f367622205930253fc03474c0aa7d017adfce571feff3011780f2502c0391 + hashery: "npm:^1.4.0" + hookified: "npm:^1.15.0" + peerDependencies: + keyv: ^5.6.0 + checksum: 10c0/acc6a4a5edf462ce23e95672ab4bfaf7cd1941dff6bf3a2f671ce467961ace1fac9d3eb75a9ed9a8e92012e00a7d8b16ad1677bc539a52c3ad0cec31473e2349 languageName: node linkType: hard -"@microsoft/api-extractor@npm:^7.50.1": - version: 7.57.6 - resolution: "@microsoft/api-extractor@npm:7.57.6" +"@keyv/serialize@npm:^1.1.1": + version: 1.1.1 + resolution: "@keyv/serialize@npm:1.1.1" + checksum: 10c0/b0008cae4a54400c3abf587b8cc2474c6f528ee58969ce6cf9cb07a04006f80c73c85971d6be6544408318a2bc40108236a19a82aea0a6de95aae49533317374 + languageName: node + linkType: hard + +"@modulify/conventional-bump@npm:^0.1.3": + version: 0.1.3 + resolution: "@modulify/conventional-bump@npm:0.1.3" dependencies: - "@microsoft/api-extractor-model": "npm:7.33.4" - "@microsoft/tsdoc": "npm:~0.16.0" - "@microsoft/tsdoc-config": "npm:~0.18.1" - "@rushstack/node-core-library": "npm:5.20.3" - "@rushstack/rig-package": "npm:0.7.2" - "@rushstack/terminal": "npm:0.22.3" - "@rushstack/ts-command-line": "npm:5.3.3" - diff: "npm:~8.0.2" - lodash: "npm:~4.17.23" - minimatch: "npm:10.2.1" - resolve: "npm:~1.22.1" - semver: "npm:~7.5.4" - source-map: "npm:~0.6.1" - typescript: "npm:5.8.2" - bin: - api-extractor: bin/api-extractor - checksum: 10c0/2f4598cc6b7cb6acc65e2029dabb7c8679495a95ed36708264088eed4a7cacb62e7f69662f71ab61e273a6441c66ae3c392f605a512fb9a4e7f9211f702287ac + "@modulify/conventional-git": "npm:^0.1.3" + semver: "npm:^7.7.4" + peerDependencies: + "@types/node": ">=20" + "@types/semver": ^7.7.1 + peerDependenciesMeta: + "@types/node": + optional: true + "@types/semver": + optional: true + checksum: 10c0/f03c067fd7173de699b986a4261a71d777ce448cbbc9157a63aa0bbe0db4e9a71ff91cae927d654103e6bc344693c4c809262663c83df87fce7a332ef67149cb + languageName: node + linkType: hard + +"@modulify/conventional-changelog@npm:^0.1.3": + version: 0.1.3 + resolution: "@modulify/conventional-changelog@npm:0.1.3" + dependencies: + "@modulify/conventional-bump": "npm:^0.1.3" + "@modulify/conventional-git": "npm:^0.1.3" + "@types/nunjucks": "npm:^3.2.6" + nunjucks: "npm:^3.2.4" + peerDependencies: + "@types/node": ">=20" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/2a48c6baa566f1be514baed4db069a289738945c081be0b42701507cbe3965d95d4f7db62c7b4cebccff9a424553a21af3a25992b87adce23e442473a7565dd9 languageName: node linkType: hard -"@microsoft/tsdoc-config@npm:~0.18.1": - version: 0.18.1 - resolution: "@microsoft/tsdoc-config@npm:0.18.1" +"@modulify/conventional-git@npm:^0.1.3": + version: 0.1.3 + resolution: "@modulify/conventional-git@npm:0.1.3" dependencies: - "@microsoft/tsdoc": "npm:0.16.0" - ajv: "npm:~8.18.0" - jju: "npm:~1.4.0" - resolve: "npm:~1.22.2" - checksum: 10c0/06507f7ced4fadf3e68368c60810c1e057403581f720e6cf96b4d6b6bc7a927232510da40425ffd67d5d918ec7cfba8baec56406687330f233f67eb11b9d8d65 + "@modulify/git-toolkit": "npm:^0.0.3" + semver: "npm:^7.7.4" + peerDependencies: + "@types/node": ">=20" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/2816827f0693b3eafa7b08f4b166840418f553f06e8dfdaad9dab7f2bdee164cdf3e8af80f75308a2482aef02d7b2ea893589cea5fe955474a6bf19864abd925 + languageName: node + linkType: hard + +"@modulify/conventional-release@npm:^0.1.3": + version: 0.1.3 + resolution: "@modulify/conventional-release@npm:0.1.3" + dependencies: + "@modulify/conventional-bump": "npm:^0.1.3" + "@modulify/conventional-changelog": "npm:^0.1.3" + "@modulify/conventional-git": "npm:^0.1.3" + "@modulify/git-toolkit": "npm:^0.0.3" + "@modulify/pkg": "npm:^1.0.1" + chalk: "npm:^5.6.2" + figures: "npm:^6.1.0" + semver: "npm:^7.7.4" + yargs: "npm:^17.7.2" + peerDependencies: + "@types/node": ">=20" + "@types/semver": ^7.7.1 + peerDependenciesMeta: + "@types/node": + optional: true + "@types/semver": + optional: true + bin: + conventional-release: bin/index.js + checksum: 10c0/8265285c6a8324bc349f8891a1a014d95109491cef915a111f85a10e6c5df833ae36551de64c77ef07fb6c65772e6c509c92883ca8923fff39dada03809ca687 + languageName: node + linkType: hard + +"@modulify/git-toolkit@npm:^0.0.3": + version: 0.0.3 + resolution: "@modulify/git-toolkit@npm:0.0.3" + peerDependencies: + "@types/node": ">=20" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/47579452bb3722eca9c54ddbc296e4106a6e1014f034b3dd8c602ab281d41d3879899d388ce34825de2947e9864158c9685959ab2b764db95ca9ecbd4b3895a4 languageName: node linkType: hard -"@microsoft/tsdoc@npm:0.16.0, @microsoft/tsdoc@npm:~0.16.0": - version: 0.16.0 - resolution: "@microsoft/tsdoc@npm:0.16.0" - checksum: 10c0/8883bb0ed22753af7360e9222687fda4eb448f0a574ea34b4596c11e320148b3ae0d24e00f8923df8ba7bc62a46a6f53b9343243a348640d923dfd55d52cd6bb +"@modulify/pkg@npm:^1.0.1": + version: 1.0.1 + resolution: "@modulify/pkg@npm:1.0.1" + dependencies: + detect-indent: "npm:^7.0.1" + detect-newline: "npm:^4.0.1" + glob: "npm:^11.0.0" + checksum: 10c0/09b3fac8bee717bbb987e5c41f0eac90990077acdd1b4e197e28765c1768162a13b241bb15d0f1630f82e9aa354ca124035e10f3d3790cb4cf1a730aa70b2c70 languageName: node linkType: hard @@ -744,22 +628,22 @@ __metadata: version: 0.0.0-use.local resolution: "@modulify/validator@workspace:." dependencies: - "@commitlint/cli": "npm:^20.4.3" - "@commitlint/config-conventional": "npm:^20.4.3" + "@commitlint/cli": "npm:^21.2.3" + "@commitlint/config-conventional": "npm:^21.2.3" "@eslint/js": "npm:^10.0.1" - "@types/node": "npm:^25.3.5" - "@vitest/coverage-v8": "npm:4.0.18" - "@vitest/ui": "npm:4.0.18" - eslint: "npm:^10.0.3" - globals: "npm:^17.4.0" + "@modulify/conventional-release": "npm:^0.1.3" + "@types/node": "npm:^24.19.0" + "@vitest/coverage-v8": "npm:5.0.2" + "@vitest/ui": "npm:5.0.2" + eslint: "npm:^10.11.0" + globals: "npm:^17.12.0" husky: "npm:^9.1.7" - ts-node: "npm:^10.9.2" tslib: "npm:^2.8.1" - typescript: "npm:^5.5.4" - typescript-eslint: "npm:^8.56.1" - vite: "npm:^7.3.1" - vite-plugin-dts: "npm:^4.5.4" - vitest: "npm:^4.0.18" + typescript: "npm:~6.0.3" + typescript-eslint: "npm:^8.70.1" + unplugin-dts: "npm:^1.1.1" + vite: "npm:^8.3.1" + vitest: "npm:5.0.2" languageName: unknown linkType: soft @@ -785,6 +669,13 @@ __metadata: languageName: node linkType: hard +"@oxc-project/types@npm:=0.151.0": + version: 0.151.0 + resolution: "@oxc-project/types@npm:0.151.0" + checksum: 10c0/7dac5399345abf368449735c31c218439e6c3a2acf7b8cbc715a88b45989390208f61bea0f3eb28bee5a034a509a7f4142ae60069e6611b07c70a30867c8ca84 + languageName: node + linkType: hard + "@polka/url@npm:^1.0.0-next.24": version: 1.0.0-next.28 resolution: "@polka/url@npm:1.0.0-next.28" @@ -792,314 +683,147 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.1.4": - version: 5.1.4 - resolution: "@rollup/pluginutils@npm:5.1.4" - dependencies: - "@types/estree": "npm:^1.0.0" - estree-walker: "npm:^2.0.2" - picomatch: "npm:^4.0.2" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10c0/6d58fbc6f1024eb4b087bc9bf59a1d655a8056a60c0b4021d3beaeec3f0743503f52467fd89d2cf0e7eccf2831feb40a05ad541a17637ea21ba10b21c2004deb - languageName: node - linkType: hard - -"@rollup/rollup-android-arm-eabi@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.59.0" +"@rolldown/binding-android-arm-eabi@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-android-arm-eabi@npm:1.2.11" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-android-arm64@npm:4.59.0" +"@rolldown/binding-android-arm64@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-android-arm64@npm:1.2.11" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.59.0" +"@rolldown/binding-darwin-arm64@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-darwin-arm64@npm:1.2.11" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.59.0" +"@rolldown/binding-darwin-x64@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-darwin-x64@npm:1.2.11" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.59.0" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-freebsd-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-freebsd-x64@npm:4.59.0" +"@rolldown/binding-freebsd-x64@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-freebsd-x64@npm:1.2.11" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm-musleabihf@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.59.0" - conditions: os=linux & cpu=arm & libc=musl +"@rolldown/binding-linux-arm-gnueabihf@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.2.11" + conditions: os=linux & cpu=arm languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.59.0" +"@rolldown/binding-linux-arm64-gnu@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.2.11" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.59.0" +"@rolldown/binding-linux-arm64-musl@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.2.11" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loong64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.59.0" - conditions: os=linux & cpu=loong64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-loong64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-loong64-musl@npm:4.59.0" - conditions: os=linux & cpu=loong64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-ppc64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.59.0" +"@rolldown/binding-linux-ppc64-gnu@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.2.11" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.59.0" - conditions: os=linux & cpu=ppc64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.59.0" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.59.0" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-s390x-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.59.0" +"@rolldown/binding-linux-s390x-gnu@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.2.11" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.59.0" +"@rolldown/binding-linux-x64-gnu@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.2.11" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.59.0" +"@rolldown/binding-linux-x64-musl@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.2.11" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openbsd-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-openbsd-x64@npm:4.59.0" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-openharmony-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.59.0" +"@rolldown/binding-openharmony-arm64@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.2.11" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.59.0" +"@rolldown/binding-win32-arm64-msvc@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.2.11" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.59.0" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@rollup/rollup-win32-x64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-x64-gnu@npm:4.59.0" +"@rolldown/binding-win32-x64-msvc@npm:1.2.11": + version: 1.2.11 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.2.11" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.59.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@rushstack/node-core-library@npm:5.20.3": - version: 5.20.3 - resolution: "@rushstack/node-core-library@npm:5.20.3" - dependencies: - ajv: "npm:~8.18.0" - ajv-draft-04: "npm:~1.0.0" - ajv-formats: "npm:~3.0.1" - fs-extra: "npm:~11.3.0" - import-lazy: "npm:~4.0.0" - jju: "npm:~1.4.0" - resolve: "npm:~1.22.1" - semver: "npm:~7.5.4" - peerDependencies: - "@types/node": "*" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10c0/bc9b33c6bef033ae6b33efb400b446d8fbaf98777ce085d03c505821f699e0a703ebe987ec05998c37aae3c33bd0dd7a4eb5e6b831c61977be9faac10f8c1c77 - languageName: node - linkType: hard - -"@rushstack/problem-matcher@npm:0.2.1": - version: 0.2.1 - resolution: "@rushstack/problem-matcher@npm:0.2.1" - peerDependencies: - "@types/node": "*" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10c0/d6cf27f6bfcdc00763e6d51e582d4faef7109ba8906e6bb3bc375edae551c54a589ed61b7e01e9ae1dbdd4a7075fd82f2da541918b52f2233d6c86393beeaaa7 - languageName: node - linkType: hard - -"@rushstack/rig-package@npm:0.7.2": - version: 0.7.2 - resolution: "@rushstack/rig-package@npm:0.7.2" - dependencies: - resolve: "npm:~1.22.1" - strip-json-comments: "npm:~3.1.1" - checksum: 10c0/2e2839fa9a3984d4b6433d6e5d48130ba0be88fc1d80e1d832272a1e939d3bfed532e8b7560ef70f8b4ebc62593b8684f2ae1cc8aecd5595661066f53527253c +"@rolldown/pluginutils@npm:^1.0.0": + version: 1.0.1 + resolution: "@rolldown/pluginutils@npm:1.0.1" + checksum: 10c0/99d9b06d90196823e4d8c841f258db7a16e5dbba5824a2962b05d907b79f1ba929d56f22dd744fd530936e568c865ee56a719dc31e57e13bc0a8eb4764a8d8dd languageName: node linkType: hard -"@rushstack/terminal@npm:0.22.3": - version: 0.22.3 - resolution: "@rushstack/terminal@npm:0.22.3" +"@rollup/pluginutils@npm:^5.1.4": + version: 5.1.4 + resolution: "@rollup/pluginutils@npm:5.1.4" dependencies: - "@rushstack/node-core-library": "npm:5.20.3" - "@rushstack/problem-matcher": "npm:0.2.1" - supports-color: "npm:~8.1.1" + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" peerDependencies: - "@types/node": "*" + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: - "@types/node": + rollup: optional: true - checksum: 10c0/0e81fe7543b5365d776c2d8f68252ccd543be2723fc9f640ebce5c6b84eec9c7fc63f385c517dfed9325ba4a8daf62175ca4df299fb1eea33561155412cf4667 + checksum: 10c0/6d58fbc6f1024eb4b087bc9bf59a1d655a8056a60c0b4021d3beaeec3f0743503f52467fd89d2cf0e7eccf2831feb40a05ad541a17637ea21ba10b21c2004deb languageName: node linkType: hard -"@rushstack/ts-command-line@npm:5.3.3": - version: 5.3.3 - resolution: "@rushstack/ts-command-line@npm:5.3.3" +"@simple-libs/child-process-utils@npm:^2.0.0": + version: 2.0.0 + resolution: "@simple-libs/child-process-utils@npm:2.0.0" dependencies: - "@rushstack/terminal": "npm:0.22.3" - "@types/argparse": "npm:1.0.38" - argparse: "npm:~1.0.9" - string-argv: "npm:~0.3.1" - checksum: 10c0/03d9e9989b2979884b952eefa519a3abfe1b218516c5468bc162aeae3ddca003e09574019d38018b4ca86736f0807084226d60253e3c6fb63b7f40aacfde2f45 - languageName: node - linkType: hard - -"@simple-libs/stream-utils@npm:^1.2.0": - version: 1.2.0 - resolution: "@simple-libs/stream-utils@npm:1.2.0" - checksum: 10c0/2788ac7b167d1b6c81b8c6fae2f5d9688b1f02ab31e9e15b33c9dc2ae920cf7de87869de10679be8957f9adb645c91c8919e271f3e34b6b4ec56daf725522dc7 - languageName: node - linkType: hard - -"@standard-schema/spec@npm:^1.0.0": - version: 1.1.0 - resolution: "@standard-schema/spec@npm:1.1.0" - checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 - languageName: node - linkType: hard - -"@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: 10c0/c176a2c1e1b16be120c328300ea910df15fb9a5277010116d26818272341a11483c5a80059389d04edacf6fd2d03d4687ad3660870fdd1cc0b7109e160adb220 + "@simple-libs/stream-utils": "npm:^2.0.0" + checksum: 10c0/8bd2ad6fe0eb7ed45e7f656b8fb2ea249673dad807ba69b950a91319747fd871c386010c766cbf8ac7242aeef76d4a03f83765c068ebb6267e2bf7e6a042e2f2 languageName: node linkType: hard -"@tsconfig/node12@npm:^1.0.7": - version: 1.0.11 - resolution: "@tsconfig/node12@npm:1.0.11" - checksum: 10c0/dddca2b553e2bee1308a056705103fc8304e42bb2d2cbd797b84403a223b25c78f2c683ec3e24a095e82cd435387c877239bffcb15a590ba817cd3f6b9a99fd9 - languageName: node - linkType: hard - -"@tsconfig/node14@npm:^1.0.0": - version: 1.0.3 - resolution: "@tsconfig/node14@npm:1.0.3" - checksum: 10c0/67c1316d065fdaa32525bc9449ff82c197c4c19092b9663b23213c8cbbf8d88b6ed6a17898e0cbc2711950fbfaf40388938c1c748a2ee89f7234fc9e7fe2bf44 - languageName: node - linkType: hard - -"@tsconfig/node16@npm:^1.0.2": - version: 1.0.4 - resolution: "@tsconfig/node16@npm:1.0.4" - checksum: 10c0/05f8f2734e266fb1839eb1d57290df1664fe2aa3b0fdd685a9035806daa635f7519bf6d5d9b33f6e69dd545b8c46bd6e2b5c79acb2b1f146e885f7f11a42a5bb - languageName: node - linkType: hard - -"@types/argparse@npm:1.0.38": - version: 1.0.38 - resolution: "@types/argparse@npm:1.0.38" - checksum: 10c0/4fc892da5df16923f48180da2d1f4562fa8b0507cf636b24780444fa0a1d7321d4dc0c0ecbee6152968823f5a2ae0d321b4f8c705a489bf1ae1245bdeb0868fd +"@simple-libs/stream-utils@npm:^2.0.0": + version: 2.0.0 + resolution: "@simple-libs/stream-utils@npm:2.0.0" + checksum: 10c0/27fa4a9eef3d652a80b970bee18589a618f66884cd15845a0c57d7b73f005ea4d9acda7fe580851af229d07de749419715d06dcedf33bcb1a671e7a27106fdda languageName: node linkType: hard @@ -1127,13 +851,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.8": - version: 1.0.8 - resolution: "@types/estree@npm:1.0.8" - checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 - languageName: node - linkType: hard - "@types/estree@npm:^1.0.0": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" @@ -1148,6 +865,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.8": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.15": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -1155,281 +879,259 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^25.3.5": - version: 25.3.5 - resolution: "@types/node@npm:25.3.5" +"@types/node@npm:^24.19.0": + version: 24.19.0 + resolution: "@types/node@npm:24.19.0" dependencies: - undici-types: "npm:~7.18.0" - checksum: 10c0/4cf0834a6f6933bf0aca6afead117ae3db3b8f02a5f7187a24f871db0fb9344e5e46573ba387bc53b7505e1e219c4c535cbe67221ced95bb5ad98573223b19d0 + undici-types: "npm:>=7.24.0 <7.24.7" + checksum: 10c0/f38afca05eb323a01243aa06a4cb8e69ef3423e1115e4464a211c6556156c024bb80fadeb7e3691802a247e7e653b70bad8c528b291153e4f48fccecc6159735 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.56.1" +"@types/nunjucks@npm:^3.2.6": + version: 3.2.6 + resolution: "@types/nunjucks@npm:3.2.6" + checksum: 10c0/bc62c5c9305c0c63a49a55c3553393fdc84d123b4831668212380077ee6646c3ba52bc49e3c651257addf3a47d775707dcefeaf5e1b76cf7f680096939894142 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.70.1" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/type-utils": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.70.1" + "@typescript-eslint/type-utils": "npm:8.70.1" + "@typescript-eslint/utils": "npm:8.70.1" + "@typescript-eslint/visitor-keys": "npm:8.70.1" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.4.0" + ts-api-utils: "npm:^2.5.0" peerDependencies: - "@typescript-eslint/parser": ^8.56.1 + "@typescript-eslint/parser": ^8.70.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/8a97e777792ee3e25078884ba0a04f6732367779c9487abcdc5a2d65b224515fa6a0cf1fac1aafc52fb30f3af97f2e1c9949aadbd6ca74a0165691f95494a721 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/6d703bd93dd65ad8bea35dfc7d79a69c0ecbcb7725e289028446673978fc2064993e1c6479dc70c06e1b776cea1a79fce17092cca337183cdd9f93c44f79f27a languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/parser@npm:8.56.1" +"@typescript-eslint/parser@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/parser@npm:8.70.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.70.1" + "@typescript-eslint/types": "npm:8.70.1" + "@typescript-eslint/typescript-estree": "npm:8.70.1" + "@typescript-eslint/visitor-keys": "npm:8.70.1" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/61c9dab481e795b01835c00c9c7c845f1d7ea7faf3b8657fccee0f8658a65390cb5fe2b5230ae8c4241bd6e0c32aa9455a91989a492bd3bd6fec7c7d9339377a + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/892025824f25e64ced093dc25a4ae1b6a03b1cdf8bbb00637914bd4fd640887bdc3fcf585f2eadb260677d329690c7e837aedc3680d5532f8277fd30e451bc30 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/project-service@npm:8.56.1" +"@typescript-eslint/project-service@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/project-service@npm:8.70.1" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.56.1" - "@typescript-eslint/types": "npm:^8.56.1" + "@typescript-eslint/tsconfig-utils": "npm:^8.70.1" + "@typescript-eslint/types": "npm:^8.70.1" debug: "npm:^4.4.3" peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/ca61cde575233bc79046d73ddd330d183fb3cbb941fddc31919336317cda39885c59296e2e5401b03d9325a64a629e842fd66865705ff0d85d83ee3ee40871e8 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/3f168d3dd18fd63718e0758c6e4f28741640c2dc38f18a46c9f2276bdc8a6e0927bfcd1f0cf40e01b6c2e3c2eac179ff6ed916c5ad539e284fb66511066e1425 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/scope-manager@npm:8.56.1" +"@typescript-eslint/scope-manager@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/scope-manager@npm:8.70.1" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" - checksum: 10c0/89cc1af2635eee23f2aa2ff87c08f88f3ad972ebf67eaacdc604a4ef4178535682bad73fd086e6f3c542e4e5d874253349af10d58291d079cc29c6c7e9831de4 + "@typescript-eslint/types": "npm:8.70.1" + "@typescript-eslint/visitor-keys": "npm:8.70.1" + checksum: 10c0/979ef0a6119ffd7045dc0e7e14c9e9a12c135a83554962ff4b33acab7bfdabda3631e8c6818ef5fc6c9b1d21d381f61e593a1bd8c92019333926447a27aaca21 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.56.1, @typescript-eslint/tsconfig-utils@npm:^8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.56.1" +"@typescript-eslint/tsconfig-utils@npm:8.70.1, @typescript-eslint/tsconfig-utils@npm:^8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.70.1" peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d03b64d7ff19020beeefa493ae667c2e67a4547d25a3ecb9210a3a52afe980c093d772a91014bae699ee148bfb60cc659479e02bfc2946ea06954a8478ef1fe1 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/c1b11fd209a547f637403a4143a5bfc72bfa6eae2f6771b62131392964f5012056608f10ce9156a5316f8b16cbe98f41de156e3f83f72870a875c80c0a8b9248 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/type-utils@npm:8.56.1" +"@typescript-eslint/type-utils@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/type-utils@npm:8.70.1" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.70.1" + "@typescript-eslint/typescript-estree": "npm:8.70.1" + "@typescript-eslint/utils": "npm:8.70.1" debug: "npm:^4.4.3" - ts-api-utils: "npm:^2.4.0" + ts-api-utils: "npm:^2.5.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/66517aed5059ef4a29605d06a510582f934d5789ae40ad673f1f0421f8aa13ec9ba7b8caab57ae9f270afacbf13ec5359cedfe74f21ae77e9a2364929f7e7cee + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/b195d46e7f9a4aece9bb7643db698a640c61a1dff846ae5a076c1b5e55b182f21fa2f57e6708438dcba067a61fccde61b2743c37bedc321768f2b6b3967dfa25 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/types@npm:8.56.1" - checksum: 10c0/e5a0318abddf0c4f98da3039cb10b3c0601c8601f7a9f7043630f0d622dabfe83a4cd833545ad3531fc846e46ca2874377277b392c2490dffec279d9242d827b +"@typescript-eslint/types@npm:8.70.1, @typescript-eslint/types@npm:^8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/types@npm:8.70.1" + checksum: 10c0/8bbc4806c5d9a7350b0cba1e60e93b235a3935d33972efba8f127688cc29db49efef2e42472bb5127f211daf2fbfd9f05be4e9bf8cd4cb8e7fdebb7be543ce16 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" +"@typescript-eslint/typescript-estree@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.70.1" dependencies: - "@typescript-eslint/project-service": "npm:8.56.1" - "@typescript-eslint/tsconfig-utils": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/project-service": "npm:8.70.1" + "@typescript-eslint/tsconfig-utils": "npm:8.70.1" + "@typescript-eslint/types": "npm:8.70.1" + "@typescript-eslint/visitor-keys": "npm:8.70.1" debug: "npm:^4.4.3" minimatch: "npm:^10.2.2" semver: "npm:^7.7.3" tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.4.0" + ts-api-utils: "npm:^2.5.0" peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/92f4421dac41be289761200dc2ed85974fa451deacb09490ae1870a25b71b97218e609a90d4addba9ded5b2abdebc265c9db7f6e9ce6d29ed20e89b8487e9618 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/d0444d74a6136c92bc83d89dfb0515b1f9a9809ed6913941c41104d163eb0f40fb8b13741f93b8d0def9c41d200f6fa691507723a1433d9f25ffe6857f16bb3a languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/utils@npm:8.56.1" +"@typescript-eslint/utils@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/utils@npm:8.70.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.70.1" + "@typescript-eslint/types": "npm:8.70.1" + "@typescript-eslint/typescript-estree": "npm:8.70.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d9ffd9b2944a2c425e0532f71dc61e61d0a923d1a17733cf2777c2a4ae638307d12d44f63b33b6b3dc62f02f47db93ec49344ecefe17b76ee3e4fb0833325be3 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/c946cf4ea68651ae25352c43fbc1cdb108079b70bed8a3bc86f0e3b35f166e468ab2c8b5d8137078622c1b22fc5599d55d8b88d530c2674df2d41f9e8bd3b305 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.56.1" +"@typescript-eslint/visitor-keys@npm:8.70.1": + version: 8.70.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.70.1" dependencies: - "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.70.1" eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/86d97905dec1af964cc177c185933d040449acf6006096497f2e0093c6a53eb92b3ac1db9eb40a5a2e8d91160f558c9734331a9280797f09f284c38978b22190 + checksum: 10c0/b5faf6ec7ef8c39bcc127401a2197315fa784a30bcc0e97c5e0dda3c2f574b64e097d6ca9d886accccd3a67f78a77e2b53520735a733d6e15dcd0fa666bb657c languageName: node linkType: hard -"@vitest/coverage-v8@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/coverage-v8@npm:4.0.18" +"@vitest/coverage-v8@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/coverage-v8@npm:5.0.2" dependencies: "@bcoe/v8-coverage": "npm:^1.0.2" - "@vitest/utils": "npm:4.0.18" - ast-v8-to-istanbul: "npm:^0.3.10" - istanbul-lib-coverage: "npm:^3.2.2" - istanbul-lib-report: "npm:^3.0.1" - istanbul-reports: "npm:^3.2.0" - magicast: "npm:^0.5.1" - obug: "npm:^2.1.1" - std-env: "npm:^3.10.0" - tinyrainbow: "npm:^3.0.3" + "@vitest/istanbul-lib-coverage": "npm:^1.0.0" + "@vitest/istanbul-lib-report": "npm:^1.0.0" + ast-v8-to-istanbul: "npm:^1.0.5" + magicast: "npm:^0.5.4" + obug: "npm:^2.1.4" + std-env: "npm:^4.2.0" + tinyrainbow: "npm:^3.1.1" peerDependencies: - "@vitest/browser": 4.0.18 - vitest: 4.0.18 + "@vitest/browser": 5.0.2 + vitest: 5.0.2 peerDependenciesMeta: "@vitest/browser": optional: true - checksum: 10c0/e23e0da86f0b2a020c51562bc40ebdc7fc7553c24f8071dfb39a6df0161badbd5eaf2eebbf8ceaef18933a18c1934ff52d1c0c4bde77bb87e0c1feb0c8cbee4d + checksum: 10c0/291db720aa27ee9ba609104fbf0c6442ea7db595e8e415be63614e68885fab8b267dedabe85eff24f93f247d058b9467e8cdd28ec30a9224fedbf498b763691d languageName: node linkType: hard -"@vitest/expect@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/expect@npm:4.0.18" +"@vitest/istanbul-lib-coverage@npm:1.0.1, @vitest/istanbul-lib-coverage@npm:^1.0.0": + version: 1.0.1 + resolution: "@vitest/istanbul-lib-coverage@npm:1.0.1" + checksum: 10c0/5259767db6c748a018c39554951e19818268fb6f72f74b74d2370471c7d83df990c3371247caea7d38f8e315df6dd461427dc242a1e7f5071e4b28863524f354 + languageName: node + linkType: hard + +"@vitest/istanbul-lib-report@npm:^1.0.0": + version: 1.0.1 + resolution: "@vitest/istanbul-lib-report@npm:1.0.1" dependencies: - "@standard-schema/spec": "npm:^1.0.0" - "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:4.0.18" - "@vitest/utils": "npm:4.0.18" - chai: "npm:^6.2.1" - tinyrainbow: "npm:^3.0.3" - checksum: 10c0/123b0aa111682e82ec5289186df18037b1a1768700e468ee0f9879709aaa320cf790463c15c0d8ee10df92b402f4394baf5d27797e604d78e674766d87bcaadc + "@vitest/istanbul-lib-coverage": "npm:1.0.1" + checksum: 10c0/1a76d4cd4c6284da0b897230d672769a5191235b3a0df41a3c861e3e12659d1790012705df6bad0f540e3f14b7b017f3611f99c9b9eb96972f8b55a3fb9270fe languageName: node linkType: hard -"@vitest/mocker@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/mocker@npm:4.0.18" +"@vitest/mocker@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/mocker@npm:5.0.2" dependencies: - "@vitest/spy": "npm:4.0.18" + "@jridgewell/trace-mapping": "npm:0.3.31" + "@vitest/spy": "npm:5.0.2" estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.21" + magic-string: "npm:^1.2.3" peerDependencies: msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - checksum: 10c0/fb0a257e7e167759d4ad228d53fa7bad2267586459c4a62188f2043dd7163b4b02e1e496dc3c227837f776e7d73d6c4343613e89e7da379d9d30de8260f1ee4b - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/pretty-format@npm:4.0.18" - dependencies: - tinyrainbow: "npm:^3.0.3" - checksum: 10c0/0086b8c88eeca896d8e4b98fcdef452c8041a1b63eb9e85d3e0bcc96c8aa76d8e9e0b6990ebb0bb0a697c4ebab347e7735888b24f507dbff2742ddce7723fd94 - languageName: node - linkType: hard - -"@vitest/runner@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/runner@npm:4.0.18" - dependencies: - "@vitest/utils": "npm:4.0.18" - pathe: "npm:^2.0.3" - checksum: 10c0/fdb4afa411475133c05ba266c8092eaf1e56cbd5fb601f92ec6ccb9bab7ca52e06733ee8626599355cba4ee71cb3a8f28c84d3b69dc972e41047edc50229bc01 + checksum: 10c0/e2d847563d47b61e9f3e5ed2d86af42b753311cd52c94ef7226398fd6f810b96ca4737855bcc4a59d78a0300859db50693d831ab29ca6334b159cc8e870f8149 languageName: node linkType: hard -"@vitest/snapshot@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/snapshot@npm:4.0.18" +"@vitest/pretty-format@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/pretty-format@npm:5.0.2" dependencies: - "@vitest/pretty-format": "npm:4.0.18" - magic-string: "npm:^0.30.21" - pathe: "npm:^2.0.3" - checksum: 10c0/d3bfefa558db9a69a66886ace6575eb96903a5ba59f4d9a5d0fecb4acc2bb8dbb443ef409f5ac1475f2e1add30bd1d71280f98912da35e89c75829df9e84ea43 + tinyrainbow: "npm:^3.1.1" + checksum: 10c0/fd3a6c7ab541ca1cf9b21cc8f44e141f50e5d07eb456edb85f1f9eacfd3a276a9ab5a442cbc35c023c3fc0f05cf2bfa022a7960d33538a2872db2043bf207616 languageName: node linkType: hard -"@vitest/spy@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/spy@npm:4.0.18" - checksum: 10c0/6de537890b3994fcadb8e8d8ac05942320ae184f071ec395d978a5fba7fa928cbb0c5de85af86a1c165706c466e840de8779eaff8c93450c511c7abaeb9b8a4e +"@vitest/spy@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/spy@npm:5.0.2" + checksum: 10c0/4a52231cc7b5b8959bb15a700a761464051a6d0cc35a231fc92fd4f58d10a01012671a20ea37ebc79e98bdd5dc257a3c52db10d6a592944560fb69651f6f1296 languageName: node linkType: hard -"@vitest/ui@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/ui@npm:4.0.18" +"@vitest/ui@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/ui@npm:5.0.2" dependencies: - "@vitest/utils": "npm:4.0.18" - fflate: "npm:^0.8.2" - flatted: "npm:^3.3.3" + "@vitest/utils": "npm:5.0.2" + fflate: "npm:^0.8.3" + flatted: "npm:^3.4.4" pathe: "npm:^2.0.3" sirv: "npm:^3.0.2" - tinyglobby: "npm:^0.2.15" - tinyrainbow: "npm:^3.0.3" + tinyrainbow: "npm:^3.1.1" peerDependencies: - vitest: 4.0.18 - checksum: 10c0/25ed45b52948101ba5c641aeb84126ce695d067984b8430f797498f7e3aeee53c5392e9e14290744a68b5114cfe933e84675b85340204cdbd118079217985157 - languageName: node - linkType: hard - -"@vitest/utils@npm:4.0.18": - version: 4.0.18 - resolution: "@vitest/utils@npm:4.0.18" - dependencies: - "@vitest/pretty-format": "npm:4.0.18" - tinyrainbow: "npm:^3.0.3" - checksum: 10c0/4a3c43c1421eb90f38576926496f6c80056167ba111e63f77cf118983902673737a1a38880b890d7c06ec0a12475024587344ee502b3c43093781533022f2aeb + vitest: 5.0.2 + checksum: 10c0/f232eae237a794b211a1c23ce10e98d125233070af23caaa92e7b89222a6118030df05525c094f493d650bfdcc190636763da1d5e3ed35976a59e6eefa0db5de languageName: node linkType: hard -"@volar/language-core@npm:2.4.11": - version: 2.4.11 - resolution: "@volar/language-core@npm:2.4.11" +"@vitest/utils@npm:5.0.2": + version: 5.0.2 + resolution: "@vitest/utils@npm:5.0.2" dependencies: - "@volar/source-map": "npm:2.4.11" - checksum: 10c0/ccc5de0c28b4186dc99ff9856b2ac2318ee1818480af3ca406f3c09d42b19b6df8698b525f6cf0fed368332fc76659cd4433fb38e6a55a85c7cefc97d665ccf8 + "@vitest/pretty-format": "npm:5.0.2" + convert-source-map: "npm:^2.0.0" + tinyrainbow: "npm:^3.1.1" + checksum: 10c0/5711e43595ce7afe83d0989f301ad6bc00605786fc39242953d2885fbdee2956e51d4ee32ad005234b4d81887538c385d480fe635d609a1646eb530d5b0802b6 languageName: node linkType: hard -"@volar/language-core@npm:~2.4.11": +"@volar/language-core@npm:2.4.28": version: 2.4.28 resolution: "@volar/language-core@npm:2.4.28" dependencies: @@ -1438,13 +1140,6 @@ __metadata: languageName: node linkType: hard -"@volar/source-map@npm:2.4.11": - version: 2.4.11 - resolution: "@volar/source-map@npm:2.4.11" - checksum: 10c0/8e5badf9f67d669679c48fe32258e082d823523ca2807438d38c0aac6c52b84d43580c8921b559fc5a27c0c7457ffcba569e60de7a597851690dec04ed77c5fc - languageName: node - linkType: hard - "@volar/source-map@npm:2.4.28": version: 2.4.28 resolution: "@volar/source-map@npm:2.4.28" @@ -1452,75 +1147,21 @@ __metadata: languageName: node linkType: hard -"@volar/typescript@npm:^2.4.11": - version: 2.4.11 - resolution: "@volar/typescript@npm:2.4.11" +"@volar/typescript@npm:^2.4.26": + version: 2.4.28 + resolution: "@volar/typescript@npm:2.4.28" dependencies: - "@volar/language-core": "npm:2.4.11" + "@volar/language-core": "npm:2.4.28" path-browserify: "npm:^1.0.1" vscode-uri: "npm:^3.0.8" - checksum: 10c0/bca9bda9c8c95fd06672b834d1804810fdad496e15ee8e2099f76de74fa529d835f342afb6b976e6e3bc4599a3bbbfd007a842694fe1300cf6286783b827f917 - languageName: node - linkType: hard - -"@vue/compiler-core@npm:3.5.13": - version: 3.5.13 - resolution: "@vue/compiler-core@npm:3.5.13" - dependencies: - "@babel/parser": "npm:^7.25.3" - "@vue/shared": "npm:3.5.13" - entities: "npm:^4.5.0" - estree-walker: "npm:^2.0.2" - source-map-js: "npm:^1.2.0" - checksum: 10c0/b89f3e3ca92c3177ae449ada1480df13d99b5b3b2cdcf3202fd37dc30f294a1db1f473209f8bae9233e2d338632219d39b2bfa6941d158cea55255e4b0b30f90 - languageName: node - linkType: hard - -"@vue/compiler-dom@npm:^3.5.0": - version: 3.5.13 - resolution: "@vue/compiler-dom@npm:3.5.13" - dependencies: - "@vue/compiler-core": "npm:3.5.13" - "@vue/shared": "npm:3.5.13" - checksum: 10c0/8f424a71883c9ef4abdd125d2be8d12dd8cf94ba56089245c88734b1f87c65e10597816070ba2ea0a297a2f66dc579f39275a9a53ef5664c143a12409612cd72 - languageName: node - linkType: hard - -"@vue/compiler-vue2@npm:^2.7.16": - version: 2.7.16 - resolution: "@vue/compiler-vue2@npm:2.7.16" - dependencies: - de-indent: "npm:^1.0.2" - he: "npm:^1.2.0" - checksum: 10c0/c76c3fad770b9a7da40b314116cc9da173da20e5fd68785c8ed8dd8a87d02f239545fa296e16552e040ec86b47bfb18283b39447b250c2e76e479bd6ae475bb3 + checksum: 10c0/075c890b9ec1cb17f17e38aaed035f8ee7d507439e87270d8e3c394356fc9387fd0bda9ec1069b36ea4c378d9375a08f5bc64c063a83427010ddd86d472124fc languageName: node linkType: hard -"@vue/language-core@npm:2.2.0": - version: 2.2.0 - resolution: "@vue/language-core@npm:2.2.0" - dependencies: - "@volar/language-core": "npm:~2.4.11" - "@vue/compiler-dom": "npm:^3.5.0" - "@vue/compiler-vue2": "npm:^2.7.16" - "@vue/shared": "npm:^3.5.0" - alien-signals: "npm:^0.4.9" - minimatch: "npm:^9.0.3" - muggle-string: "npm:^0.4.1" - path-browserify: "npm:^1.0.1" - peerDependencies: - typescript: "*" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/1c44cc4067266bbc825af358a867aed455963a08c160cd9df9a47571fd917a87d9de9bdea6149877e0c8309a6cf39f263e7cf2fbadeceba47a5a158f392151b2 - languageName: node - linkType: hard - -"@vue/shared@npm:3.5.13, @vue/shared@npm:^3.5.0": - version: 3.5.13 - resolution: "@vue/shared@npm:3.5.13" - checksum: 10c0/2c940ef907116f1c2583ca1d7733984e5705983ab07054c4e72f1d95eb0f7bdf4d01efbdaee1776c2008f79595963f44e98fced057f5957d86d57b70028f5025 +"a-sync-waterfall@npm:^1.0.0": + version: 1.0.1 + resolution: "a-sync-waterfall@npm:1.0.1" + checksum: 10c0/1c7b258da2c77eb1447dcc683afb10ca3dc8880de990562ccbb7b282538aba01e910345ce9e8500c1458272c7866b85fcfa5ca8159e33550b011ab5c586ec5a4 languageName: node linkType: hard @@ -1540,10 +1181,12 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.1.1": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 10c0/7e2a8dad5480df7f872569b9dccff2f3da7e65f5353686b1d6032ab9f4ddf6e3a2cb83a9b52cf50b1497fd522154dda92f0abf7153290cc79cd14721ff121e52 +"acorn@npm:^8.15.0": + version: 8.18.0 + resolution: "acorn@npm:8.18.0" + bin: + acorn: bin/acorn + checksum: 10c0/be771be2135cc07910cf76f444ad514d7dcfd6d4a8026e597e93155275abc8ef61eee12211d52146e9d962874269b634f397464942087be013c89d0c54c5f8e5 languageName: node linkType: hard @@ -1556,45 +1199,10 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.4.1": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" - bin: - acorn: bin/acorn - checksum: 10c0/3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 - languageName: node - linkType: hard - "agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": version: 7.1.4 resolution: "agent-base@npm:7.1.4" - checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe - languageName: node - linkType: hard - -"ajv-draft-04@npm:~1.0.0": - version: 1.0.0 - resolution: "ajv-draft-04@npm:1.0.0" - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - checksum: 10c0/6044310bd38c17d77549fd326bd40ce1506fa10b0794540aa130180808bf94117fac8c9b448c621512bea60e4a947278f6a978e87f10d342950c15b33ddd9271 - languageName: node - linkType: hard - -"ajv-formats@npm:~3.0.1": - version: 3.0.1 - resolution: "ajv-formats@npm:3.0.1" - dependencies: - ajv: "npm:^8.0.0" - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - checksum: 10c0/168d6bca1ea9f163b41c8147bae537e67bd963357a5488a1eaf3abe8baa8eec806d4e45f15b10767e6020679315c7e1e5e6803088dfb84efa2b4e9353b83dd0a + checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe languageName: node linkType: hard @@ -1610,18 +1218,6 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0": - version: 8.17.1 - resolution: "ajv@npm:8.17.1" - dependencies: - fast-deep-equal: "npm:^3.1.3" - fast-uri: "npm:^3.0.1" - json-schema-traverse: "npm:^1.0.0" - require-from-string: "npm:^2.0.2" - checksum: 10c0/ec3ba10a573c6b60f94639ffc53526275917a2df6810e4ab5a6b959d87459f9ef3f00d5e7865b82677cb7d21590355b34da14d1d0b9c32d75f95a187e76fff35 - languageName: node - linkType: hard - "ajv@npm:^8.11.0": version: 8.12.0 resolution: "ajv@npm:8.12.0" @@ -1634,25 +1230,6 @@ __metadata: languageName: node linkType: hard -"ajv@npm:~8.18.0": - version: 8.18.0 - resolution: "ajv@npm:8.18.0" - dependencies: - fast-deep-equal: "npm:^3.1.3" - fast-uri: "npm:^3.0.1" - json-schema-traverse: "npm:^1.0.0" - require-from-string: "npm:^2.0.2" - checksum: 10c0/e7517c426173513a07391be951879932bdf3348feaebd2199f5b901c20f99d60db8cd1591502d4d551dc82f594e82a05c4fe1c70139b15b8937f7afeaed9532f - languageName: node - linkType: hard - -"alien-signals@npm:^0.4.9": - version: 0.4.14 - resolution: "alien-signals@npm:0.4.14" - checksum: 10c0/5abb3377bcaf6b3819e950084b3ebd022ad90210105afb450c89dc347e80e28da441bf34858a57ea122abe7603e552ddbad80dc597c8f02a0a5206c5fb9c20cb - languageName: node - linkType: hard - "ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" @@ -1660,6 +1237,13 @@ __metadata: languageName: node linkType: hard +"ansi-regex@npm:^6.2.2": + version: 6.3.0 + resolution: "ansi-regex@npm:6.3.0" + checksum: 10c0/bc047786d0531f1f22d1e22e9863e8554488a399f1ee5270b753efa6de938a788d27456f2b256770f11fdd8b1e847483bc1b55ddc2b3ffe82ec45c875292c651 + languageName: node + linkType: hard + "ansi-styles@npm:^3.2.1": version: 3.2.1 resolution: "ansi-styles@npm:3.2.1" @@ -1678,10 +1262,10 @@ __metadata: languageName: node linkType: hard -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 10c0/070ff801a9d236a6caa647507bdcc7034530604844d64408149a26b9e87c2f97650055c0f049abd1efc024b334635c01f29e0b632b371ac3f26130f4cf65997a +"ansi-styles@npm:^6.2.1": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 languageName: node linkType: hard @@ -1692,19 +1276,17 @@ __metadata: languageName: node linkType: hard -"argparse@npm:~1.0.9": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: "npm:~1.0.2" - checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de +"argue-cli@npm:^3.1.0": + version: 3.2.0 + resolution: "argue-cli@npm:3.2.0" + checksum: 10c0/1b3df0c0e0a7a6199b45124aa2e664d9ec467b484cc9e9263ecf3062cc30725548fd840688ceee8bf5d67955cad8d155111e80ec6626d60b884b6c66264e9940 languageName: node linkType: hard -"array-ify@npm:^1.0.0": - version: 1.0.0 - resolution: "array-ify@npm:1.0.0" - checksum: 10c0/75c9c072faac47bd61779c0c595e912fe660d338504ac70d10e39e1b8a4a0c9c87658703d619b9d1b70d324177ae29dc8d07dda0d0a15d005597bc4c5a59c70c +"asap@npm:^2.0.3": + version: 2.0.6 + resolution: "asap@npm:2.0.6" + checksum: 10c0/c6d5e39fe1f15e4b87677460bd66b66050cd14c772269cee6688824c1410a08ab20254bb6784f9afb75af9144a9f9a7692d49547f4d19d715aeb7c0318f3136d languageName: node linkType: hard @@ -1715,14 +1297,14 @@ __metadata: languageName: node linkType: hard -"ast-v8-to-istanbul@npm:^0.3.10": - version: 0.3.12 - resolution: "ast-v8-to-istanbul@npm:0.3.12" +"ast-v8-to-istanbul@npm:^1.0.5": + version: 1.0.7 + resolution: "ast-v8-to-istanbul@npm:1.0.7" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.31" estree-walker: "npm:^3.0.3" js-tokens: "npm:^10.0.0" - checksum: 10c0/bad6ba222b1073c165c8d65dbf366193d4a90536dabe37f93a3df162269b1c9473975756e4c048f708c235efccc26f8e5321c547b7e9563b64b21b2e0f27cbc9 + checksum: 10c0/c6bbfbf8b8adc8d793f8d10fbf9bcb25b0c65f2faa73ec1e41d2937a9c18327167b9395134943a4814dd3d095d2453b2f0f71a5d33aecd808ac4725c23e69918 languageName: node linkType: hard @@ -1742,6 +1324,15 @@ __metadata: languageName: node linkType: hard +"brace-expansion@npm:^5.0.8": + version: 5.0.12 + resolution: "brace-expansion@npm:5.0.12" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/a40ac64d3bdb5bb222456514d3633c1f627f03b844f509c69e70f98b78be0ce85e21b44bbfecdd0ddd4cc0855ca4242b41ea96ddccf88c7c3c7a84405474bb3a + languageName: node + linkType: hard + "cacache@npm:^20.0.1": version: 20.0.3 resolution: "cacache@npm:20.0.3" @@ -1761,6 +1352,19 @@ __metadata: languageName: node linkType: hard +"cacheable@npm:^2.5.0": + version: 2.5.0 + resolution: "cacheable@npm:2.5.0" + dependencies: + "@cacheable/memory": "npm:^2.2.0" + "@cacheable/utils": "npm:^2.5.0" + hookified: "npm:^1.15.0" + keyv: "npm:^5.6.0" + qified: "npm:^0.10.1" + checksum: 10c0/ad4086a60ed327196901c16360312705e35bfde5118457449cfabaf4ece0fecad046985ea8b66b3ece46dd469cb33798d87e1dac3ed2c00746578054bccbf74d + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -1768,7 +1372,7 @@ __metadata: languageName: node linkType: hard -"chai@npm:^6.2.1": +"chai@npm:^6.2.2": version: 6.2.2 resolution: "chai@npm:6.2.2" checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 @@ -1786,6 +1390,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^5.6.2": + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 10c0/99a4b0f0e7991796b1e7e3f52dceb9137cae2a9dfc8fc0784a550dc4c558e15ab32ed70b14b21b52beb2679b4892b41a0aa44249bcb996f01e125d58477c6976 + languageName: node + linkType: hard + "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -1804,6 +1415,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^9.0.1": + version: 9.0.1 + resolution: "cliui@npm:9.0.1" + dependencies: + string-width: "npm:^7.2.0" + strip-ansi: "npm:^7.1.0" + wrap-ansi: "npm:^9.0.0" + checksum: 10c0/13441832e9efe7c7a76bd2b8e683555c478d461a9f249dc5db9b17fe8d4b47fa9277b503914b90bd00e4a151abb6b9b02b2288972ffe2e5e3ca40bcb1c2330d3 + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -1836,13 +1458,10 @@ __metadata: languageName: node linkType: hard -"compare-func@npm:^2.0.0": - version: 2.0.0 - resolution: "compare-func@npm:2.0.0" - dependencies: - array-ify: "npm:^1.0.0" - dot-prop: "npm:^5.1.0" - checksum: 10c0/78bd4dd4ed311a79bd264c9e13c36ed564cde657f1390e699e0f04b8eee1fc06ffb8698ce2dfb5fbe7342d509579c82d4e248f08915b708f77f7b72234086cc3 +"commander@npm:^5.1.0": + version: 5.1.0 + resolution: "commander@npm:5.1.0" + checksum: 10c0/da9d71dbe4ce039faf1fe9eac3771dca8c11d66963341f62602f7b66e36d2a3f8883407af4f9a37b1db1a55c59c0c1325f186425764c2e963dc1d67aec2a4b6d languageName: node linkType: hard @@ -1867,33 +1486,40 @@ __metadata: languageName: node linkType: hard -"conventional-changelog-angular@npm:^8.2.0": - version: 8.3.0 - resolution: "conventional-changelog-angular@npm:8.3.0" +"conventional-changelog-angular@npm:^9.0.0": + version: 9.4.0 + resolution: "conventional-changelog-angular@npm:9.4.0" dependencies: - compare-func: "npm:^2.0.0" - checksum: 10c0/bab87fa741a25e4fb623e2629912a5e592de5ed616398bee0cd9779dc950aae2a78ac48a6f4268cbb5f5544bb33644e01c7b40cea378bb9763ae5304cc22efc2 + "@conventional-changelog/template": "npm:^1.4.0" + checksum: 10c0/79368f0bb9a0b10cc38b5eb0af64b7a69c815f3e5fed853af9f80b56b8f09b1578d0fb47d8a0cf13e8030c6dedb81a0f507d1998cd064d2ade3f517c82fbdcde languageName: node linkType: hard -"conventional-changelog-conventionalcommits@npm:^9.2.0": - version: 9.3.0 - resolution: "conventional-changelog-conventionalcommits@npm:9.3.0" +"conventional-changelog-conventionalcommits@npm:^10.0.0": + version: 10.4.0 + resolution: "conventional-changelog-conventionalcommits@npm:10.4.0" dependencies: - compare-func: "npm:^2.0.0" - checksum: 10c0/36be9435bb1f6e97bc729a1e69471851b6621054980617dc9a82c03221de5f9c21cd2369308c364f89b2383bd596071f90c8c71efdbe7a2908f91a935685fc76 + "@conventional-changelog/template": "npm:^1.4.0" + checksum: 10c0/60d99d74e6fdba134fc4785c13f87df82b9cabd980b4390dc958a8abf75d6fe1fdad921f52fb75e02f01a376cfd194b9f506f1e7718041e522b5260b53273882 languageName: node linkType: hard -"conventional-commits-parser@npm:^6.3.0": - version: 6.3.0 - resolution: "conventional-commits-parser@npm:6.3.0" +"conventional-commits-parser@npm:^7.0.0": + version: 7.1.2 + resolution: "conventional-commits-parser@npm:7.1.2" dependencies: - "@simple-libs/stream-utils": "npm:^1.2.0" - meow: "npm:^13.0.0" + "@simple-libs/stream-utils": "npm:^2.0.0" + argue-cli: "npm:^3.1.0" bin: - conventional-commits-parser: dist/cli/index.js - checksum: 10c0/7b152db0b63617fb5f993c3422942c05f48ff42fef4350d7e73b1d8a9f24489050b126478f2aabee5e45f205dbd02cb0b486e4bb865f9c0b18c35b4d13952b25 + conventional-commits-parser: ./dist/cli/index.js + checksum: 10c0/dd1478a5ef4fddd52cdd67fa4a97d1f47908a20d22287ccfa3f5e09b8298a3bcf3eb49ed117744805cc07ca31edf8835ce0913e96b1bcf7c385cf9bcefb3cf54 + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b languageName: node linkType: hard @@ -1927,13 +1553,6 @@ __metadata: languageName: node linkType: hard -"create-require@npm:^1.1.0": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -1945,20 +1564,6 @@ __metadata: languageName: node linkType: hard -"dargs@npm:^8.0.0": - version: 8.1.0 - resolution: "dargs@npm:8.1.0" - checksum: 10c0/08cbd1ee4ac1a16fb7700e761af2e3e22d1bdc04ac4f851926f552dde8f9e57714c0d04013c2cca1cda0cba8fb637e0f93ad15d5285547a939dd1989ee06a82d - languageName: node - linkType: hard - -"de-indent@npm:^1.0.2": - version: 1.0.2 - resolution: "de-indent@npm:1.0.2" - checksum: 10c0/7058ce58abd6dfc123dd204e36be3797abd419b59482a634605420f47ae97639d0c183ec5d1b904f308a01033f473673897afc2bd59bc620ebf1658763ef4291 - languageName: node - linkType: hard - "debug@npm:4, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" @@ -2002,26 +1607,31 @@ __metadata: languageName: node linkType: hard -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: 10c0/81b91f9d39c4eaca068eb0c1eb0e4afbdc5bb2941d197f513dd596b820b956fef43485876226d65d497bebc15666aa2aa82c679e84f65d5f2bfbf14ee46e32c1 +"detect-indent@npm:^7.0.1": + version: 7.0.2 + resolution: "detect-indent@npm:7.0.2" + checksum: 10c0/adb1334ca3fe516dc6817aff0a777540b88643ab92fe13a72d0f5d12721ca796ffdd0e5fedb7b45e6e82657156c6ad44f5d5758157f0439532ae7d07b595146b languageName: node linkType: hard -"diff@npm:~8.0.2": - version: 8.0.3 - resolution: "diff@npm:8.0.3" - checksum: 10c0/d29321c70d3545fdcb56c5fdd76028c3f04c012462779e062303d4c3c531af80d2c360c26b871e6e2b9a971d2422d47e1779a859106c4cac4b5d2d143df70e20 +"detect-libc@npm:^2.0.3": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 languageName: node linkType: hard -"dot-prop@npm:^5.1.0": - version: 5.3.0 - resolution: "dot-prop@npm:5.3.0" - dependencies: - is-obj: "npm:^2.0.0" - checksum: 10c0/93f0d343ef87fe8869320e62f2459f7e70f49c6098d948cc47e060f4a3f827d0ad61e83cb82f2bd90cd5b9571b8d334289978a43c0f98fea4f0e99ee8faa0599 +"detect-newline@npm:^4.0.1": + version: 4.0.1 + resolution: "detect-newline@npm:4.0.1" + checksum: 10c0/1cc1082e88ad477f30703ae9f23bd3e33816ea2db6a35333057e087d72d466f5a777809b71f560118ecff935d2c712f5b59e1008a8b56a900909d8fd4621c603 + languageName: node + linkType: hard + +"emoji-regex@npm:^10.3.0": + version: 10.6.0 + resolution: "emoji-regex@npm:10.6.0" + checksum: 10c0/1e4aa097bb007301c3b4b1913879ae27327fdc48e93eeefefe3b87e495eb33c5af155300be951b4349ff6ac084f4403dc9eff970acba7c1c572d89396a9a32d7 languageName: node linkType: hard @@ -2032,13 +1642,6 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.5.0": - version: 4.5.0 - resolution: "entities@npm:4.5.0" - checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 - languageName: node - linkType: hard - "env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -2055,99 +1658,24 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^1.7.0": - version: 1.7.0 - resolution: "es-module-lexer@npm:1.7.0" - checksum: 10c0/4c935affcbfeba7fb4533e1da10fa8568043df1e3574b869385980de9e2d475ddc36769891936dbb07036edb3c3786a8b78ccf44964cd130dedc1f2c984b6c7b - languageName: node - linkType: hard - -"esbuild@npm:^0.27.0": - version: 0.27.3 - resolution: "esbuild@npm:0.27.3" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.3" - "@esbuild/android-arm": "npm:0.27.3" - "@esbuild/android-arm64": "npm:0.27.3" - "@esbuild/android-x64": "npm:0.27.3" - "@esbuild/darwin-arm64": "npm:0.27.3" - "@esbuild/darwin-x64": "npm:0.27.3" - "@esbuild/freebsd-arm64": "npm:0.27.3" - "@esbuild/freebsd-x64": "npm:0.27.3" - "@esbuild/linux-arm": "npm:0.27.3" - "@esbuild/linux-arm64": "npm:0.27.3" - "@esbuild/linux-ia32": "npm:0.27.3" - "@esbuild/linux-loong64": "npm:0.27.3" - "@esbuild/linux-mips64el": "npm:0.27.3" - "@esbuild/linux-ppc64": "npm:0.27.3" - "@esbuild/linux-riscv64": "npm:0.27.3" - "@esbuild/linux-s390x": "npm:0.27.3" - "@esbuild/linux-x64": "npm:0.27.3" - "@esbuild/netbsd-arm64": "npm:0.27.3" - "@esbuild/netbsd-x64": "npm:0.27.3" - "@esbuild/openbsd-arm64": "npm:0.27.3" - "@esbuild/openbsd-x64": "npm:0.27.3" - "@esbuild/openharmony-arm64": "npm:0.27.3" - "@esbuild/sunos-x64": "npm:0.27.3" - "@esbuild/win32-arm64": "npm:0.27.3" - "@esbuild/win32-ia32": "npm:0.27.3" - "@esbuild/win32-x64": "npm:0.27.3" +"es-module-lexer@npm:^2.3.2": + version: 2.3.2 + resolution: "es-module-lexer@npm:2.3.2" + checksum: 10c0/5e7389424c43478439f12f9a6aca1750f6f99afa384fc3de329f4a45f152ab156671055008adaafc74960877abf8cc338aeebf6bed8c21297b146fd6eb7a22f8 + languageName: node + linkType: hard + +"es-toolkit@npm:^1.46.0": + version: 1.52.0 + resolution: "es-toolkit@npm:1.52.0" dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/openharmony-arm64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/fdc3f87a3f08b3ef98362f37377136c389a0d180fda4b8d073b26ba930cf245521db0a368f119cc7624bc619248fff1439f5811f062d853576f8ffa3df8ee5f1 + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + vitepress-plugin-sandpack@1.1.4: + unplugged: true + checksum: 10c0/465988c0a6b84b6d1d171287cbbe40c3247a1f94acea210ae14bc66b7d90c93e6839bd6937cbaf2a1d206669f3179eb26141a89d9125969a4b8e58cb7d86a2ca languageName: node linkType: hard @@ -2205,16 +1733,16 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^10.0.3": - version: 10.0.3 - resolution: "eslint@npm:10.0.3" +"eslint@npm:^10.11.0": + version: 10.11.0 + resolution: "eslint@npm:10.11.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.2" - "@eslint/config-array": "npm:^0.23.3" - "@eslint/config-helpers": "npm:^0.5.2" - "@eslint/core": "npm:^1.1.1" - "@eslint/plugin-kit": "npm:^0.6.1" + "@eslint/config-array": "npm:^0.23.5" + "@eslint/config-helpers": "npm:^0.7.0" + "@eslint/core": "npm:^1.2.1" + "@eslint/plugin-kit": "npm:^0.7.3" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" @@ -2225,18 +1753,18 @@ __metadata: escape-string-regexp: "npm:^4.0.0" eslint-scope: "npm:^9.1.2" eslint-visitor-keys: "npm:^5.0.1" - espree: "npm:^11.1.1" + espree: "npm:^11.2.0" esquery: "npm:^1.7.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^8.0.0" + file-entry-cache: "npm:11.1.5 || >11.1.6 <12" find-up: "npm:^5.0.0" glob-parent: "npm:^6.0.2" ignore: "npm:^5.2.0" imurmurhash: "npm:^0.1.4" is-glob: "npm:^4.0.0" json-stable-stringify-without-jsonify: "npm:^1.0.1" - minimatch: "npm:^10.2.4" + minimatch: "npm:^10.2.5" natural-compare: "npm:^1.4.0" optionator: "npm:^0.9.3" peerDependencies: @@ -2246,11 +1774,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/fbbb4d99cb6af5c30b163b7898241dbac1cd1cee0e6746d5732a95e3b1e68b5bea0bc27cb78e8440a39cf4cc98c7f52cf5ed8d7c2bbdf2232662476d113c41fc + checksum: 10c0/c767f45f21d1921b41d70e30b1c8fa7ec4e65c0f43a8d80cc4990ca3d923127fa7b9b3416b8f5be6e877d9286f97d3c51a04ed341bc6aa73c0dba0f463e1f861 languageName: node linkType: hard -"espree@npm:^11.1.1": +"espree@npm:^11.2.0": version: 11.2.0 resolution: "espree@npm:11.2.0" dependencies: @@ -2309,10 +1837,10 @@ __metadata: languageName: node linkType: hard -"expect-type@npm:^1.2.2": - version: 1.3.0 - resolution: "expect-type@npm:1.3.0" - checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd +"expect-type@npm:^1.4.0": + version: 1.4.0 + resolution: "expect-type@npm:1.4.0" + checksum: 10c0/d40d76b8570695d36587beb3cc28494da2ca3ec8f04e67f5622ed2d372d850e401a9adef19c6835e1a8173903f157c79540b34c7b3fbd7cd8ce726cc903c57b7 languageName: node linkType: hard @@ -2351,13 +1879,6 @@ __metadata: languageName: node linkType: hard -"fast-uri@npm:^3.0.1": - version: 3.0.3 - resolution: "fast-uri@npm:3.0.3" - checksum: 10c0/4b2c5ce681a062425eae4f15cdc8fc151fd310b2f69b1f96680677820a8b49c3cd6e80661a406e19d50f0c40a3f8bffdd458791baf66f4a879d80be28e10a320 - languageName: node - linkType: hard - "fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -2370,19 +1891,28 @@ __metadata: languageName: node linkType: hard -"fflate@npm:^0.8.2": - version: 0.8.2 - resolution: "fflate@npm:0.8.2" - checksum: 10c0/03448d630c0a583abea594835a9fdb2aaf7d67787055a761515bf4ed862913cfd693b4c4ffd5c3f3b355a70cf1e19033e9ae5aedcca103188aaff91b8bd6e293 +"fflate@npm:^0.8.3": + version: 0.8.3 + resolution: "fflate@npm:0.8.3" + checksum: 10c0/eab181ca37f5348ae76d4b6f840e0026e30220e33153289ac942222d8b9638237d486507dbcc09878d724095bd354993a2ee48bbee99c8f2c6440d4448719aa7 languageName: node linkType: hard -"file-entry-cache@npm:^8.0.0": - version: 8.0.0 - resolution: "file-entry-cache@npm:8.0.0" +"figures@npm:^6.1.0": + version: 6.1.0 + resolution: "figures@npm:6.1.0" + dependencies: + is-unicode-supported: "npm:^2.0.0" + checksum: 10c0/9159df4264d62ef447a3931537de92f5012210cf5135c35c010df50a2169377581378149abfe1eb238bd6acbba1c0d547b1f18e0af6eee49e30363cedaffcfe4 + languageName: node + linkType: hard + +"file-entry-cache@npm:11.1.5 || >11.1.6 <12": + version: 11.1.5 + resolution: "file-entry-cache@npm:11.1.5" dependencies: - flat-cache: "npm:^4.0.0" - checksum: 10c0/9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638 + flat-cache: "npm:^6.1.23" + checksum: 10c0/d05eca8794b27824d79a0f1a0bc76b81ca7232b6c9634bc086f365a6d9ddac749c4826b2b2d36bb7ef9ed84fdf0097f34979527daeb9255b4f17673a4ae50fc5 languageName: node linkType: hard @@ -2396,38 +1926,31 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^4.0.0": - version: 4.0.1 - resolution: "flat-cache@npm:4.0.1" +"flat-cache@npm:^6.1.23": + version: 6.1.23 + resolution: "flat-cache@npm:6.1.23" dependencies: - flatted: "npm:^3.2.9" - keyv: "npm:^4.5.4" - checksum: 10c0/2c59d93e9faa2523e4fda6b4ada749bed432cfa28c8e251f33b25795e426a1c6dbada777afb1f74fcfff33934fdbdea921ee738fcc33e71adc9d6eca984a1cfc + cacheable: "npm:^2.5.0" + flatted: "npm:^3.4.2" + hookified: "npm:^1.15.0" + checksum: 10c0/c757c24f51334e1917958cd9d62d4ed3d520a3815d5a1ec50d993ac3a93fa81b6de7e28264231914bb0d990babd426e4d713d3e2f3d782dae65c42a2ded1e651 languageName: node linkType: hard -"flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: 10c0/5c91c5a0a21bbc0b07b272231e5b4efe6b822bcb4ad317caf6bb06984be4042a9e9045026307da0fdb4583f1f545e317a67ef1231a59e71f7fced3cc429cfc53 +"flatted@npm:^3.4.2, flatted@npm:^3.4.4": + version: 3.4.4 + resolution: "flatted@npm:3.4.4" + checksum: 10c0/a3a52a88ea5a4c333e5a1f097dcd87a037fa31c236a77cf46222c2aa4036ef895ab9bc76138a66d9dc22bdb3652128f9598cd26e7439561bf19f67276e2bc37e languageName: node linkType: hard -"flatted@npm:^3.3.3": - version: 3.3.4 - resolution: "flatted@npm:3.3.4" - checksum: 10c0/d1f33426e9714063a65a90940acdb2897eceb810230a58e496d90334dcecfa81a90135bbc660df6827939865d57cb4a2afab14dcd3d505e16a8484fd73bf9642 - languageName: node - linkType: hard - -"fs-extra@npm:~11.3.0": - version: 11.3.4 - resolution: "fs-extra@npm:11.3.4" +"foreground-child@npm:^3.3.1": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/e08276f767a62496ae97d711aaa692c6a478177f24a85979b6a2881c9db9c68b8c2ad5da0bcf92c0b2a474cea6e935ec245656441527958fd8372cb647087df0 + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 languageName: node linkType: hard @@ -2440,7 +1963,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -2450,7 +1973,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -2459,13 +1982,6 @@ __metadata: languageName: node linkType: hard -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - "get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -2473,16 +1989,10 @@ __metadata: languageName: node linkType: hard -"git-raw-commits@npm:^4.0.0": - version: 4.0.0 - resolution: "git-raw-commits@npm:4.0.0" - dependencies: - dargs: "npm:^8.0.0" - meow: "npm:^12.0.1" - split2: "npm:^4.0.0" - bin: - git-raw-commits: cli.mjs - checksum: 10c0/ab51335d9e55692fce8e42788013dba7a7e7bf9f5bf0622c8cd7ddc9206489e66bb939563fca4edb3aa87477e2118f052702aad1933b13c6fa738af7f29884f0 +"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.5.0": + version: 1.7.0 + resolution: "get-east-asian-width@npm:1.7.0" + checksum: 10c0/680a5f611a186e4a065291f31821f7e4ad7742625be814e05b8ab5535c6fa53562bc0333a83138fca5f2e1030ed960a561b2fd4629e0cff0dc68b19cf46d7c53 languageName: node linkType: hard @@ -2495,6 +2005,29 @@ __metadata: languageName: node linkType: hard +"glob-to-regexp@npm:0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: 10c0/0486925072d7a916f052842772b61c3e86247f0a80cc0deb9b5a3e8a1a9faad5b04fb6f58986a09f34d3e96cd2a22a24b7e9882fb1cf904c31e9a310de96c429 + languageName: node + linkType: hard + +"glob@npm:^11.0.0": + version: 11.1.0 + resolution: "glob@npm:11.1.0" + dependencies: + foreground-child: "npm:^3.3.1" + jackspeak: "npm:^4.1.1" + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^2.0.0" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/1ceae07f23e316a6fa74581d9a74be6e8c2e590d2f7205034dd5c0435c53f5f7b712c2be00c3b65bf0a49294a1c6f4b98cd84c7637e29453b5aa13b79f1763a2 + languageName: node + linkType: hard + "glob@npm:^13.0.0": version: 13.0.6 resolution: "glob@npm:13.0.6" @@ -2506,23 +2039,23 @@ __metadata: languageName: node linkType: hard -"global-directory@npm:^4.0.1": - version: 4.0.1 - resolution: "global-directory@npm:4.0.1" +"global-directory@npm:^5.0.0": + version: 5.0.0 + resolution: "global-directory@npm:5.0.0" dependencies: - ini: "npm:4.1.1" - checksum: 10c0/f9cbeef41db4876f94dd0bac1c1b4282a7de9c16350ecaaf83e7b2dd777b32704cc25beeb1170b5a63c42a2c9abfade74d46357fe0133e933218bc89e613d4b2 + ini: "npm:6.0.0" + checksum: 10c0/2b90eea8975bb332db7e8c9096ff310f0deb617d17e47e93b921d1c69f7677c1759a07009f2581f050d3ea08a3e079bf4ffdb9c34c94d48dc369c6577b3d45f4 languageName: node linkType: hard -"globals@npm:^17.4.0": - version: 17.4.0 - resolution: "globals@npm:17.4.0" - checksum: 10c0/2be9e8c2b9035836f13d420b22f0247a328db82967d3bebfc01126d888ed609305f06c05895914e969653af5c6ba35fd7a0920f3e6c869afa60666c810630feb +"globals@npm:^17.12.0": + version: 17.12.0 + resolution: "globals@npm:17.12.0" + checksum: 10c0/8325cf8818c848871d17c32974c2c74e9c5f09c1b0e04421886f64f21e77c3e95f3ba25586743895a73acd860ada151132481d87d44a1f12993ae7758a694d03 languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -2536,35 +2069,26 @@ __metadata: languageName: node linkType: hard -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 - languageName: node - linkType: hard - -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hashery@npm:^1.4.0, hashery@npm:^1.5.1": + version: 1.5.1 + resolution: "hashery@npm:1.5.1" dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/5d415b114f410661208c95e7ab4879f1cc2765b8daceff4dc8718317d1cb7b9ffa7c5d1eafd9a4389c9aab7445d6ea88e05f3096cb1e529618b55304956b87fc + hookified: "npm:^1.15.0" + checksum: 10c0/ab4225b655a7b0d05df99b1a59d5b3a51fe433f82422ca25e6f3f4c4ddd30adb49ebd38e0047ef9bded93319c1e9fc857e16aa382e554929c871cb77d39fc463 languageName: node linkType: hard -"he@npm:^1.2.0": - version: 1.2.0 - resolution: "he@npm:1.2.0" - bin: - he: bin/he - checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17 +"hookified@npm:^1.15.0, hookified@npm:^1.15.1": + version: 1.15.1 + resolution: "hookified@npm:1.15.1" + checksum: 10c0/6b691374fa97ae57169fb29f90e723499fda5e85494654fbe55c4768b3ccbf3e14c0adc8d0f365f32c503b60d7c06f907781f5966c03d41c423575eb5e16860c languageName: node linkType: hard -"html-escaper@npm:^2.0.0": - version: 2.0.2 - resolution: "html-escaper@npm:2.0.2" - checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 +"hookified@npm:^2.1.1": + version: 2.2.0 + resolution: "hookified@npm:2.2.0" + checksum: 10c0/7017d2b66945490293a5aba239e7b39f39071dd940fa019348c7ffea92b91b8c267853c4c51680ed0f3687b33352582fa4d2cff6dd4c5a1c5c44b037276f07aa languageName: node linkType: hard @@ -2637,20 +2161,6 @@ __metadata: languageName: node linkType: hard -"import-lazy@npm:~4.0.0": - version: 4.0.0 - resolution: "import-lazy@npm:4.0.0" - checksum: 10c0/a3520313e2c31f25c0b06aa66d167f329832b68a4f957d7c9daf6e0fa41822b6e84948191648b9b9d8ca82f94740cdf15eecf2401a5b42cd1c33fd84f2225cca - languageName: node - linkType: hard - -"import-meta-resolve@npm:^4.0.0": - version: 4.2.0 - resolution: "import-meta-resolve@npm:4.2.0" - checksum: 10c0/3ee8aeecb61d19b49d2703987f977e9d1c7d4ba47db615a570eaa02fe414f40dfa63f7b953e842cbe8470d26df6371332bfcf21b2fd92b0112f9fea80dde2c4c - languageName: node - linkType: hard - "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -2658,10 +2168,10 @@ __metadata: languageName: node linkType: hard -"ini@npm:4.1.1": - version: 4.1.1 - resolution: "ini@npm:4.1.1" - checksum: 10c0/7fddc8dfd3e63567d4fdd5d999d1bf8a8487f1479d0b34a1d01f28d391a9228d261e19abc38e1a6a1ceb3400c727204fce05725d5eb598dfcf2077a1e3afe211 +"ini@npm:6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 10c0/9a7f55f306e2b25b41ae67c8b526e8f4673f057b70852b9025816ef4f15f07bf1ba35ed68ea4471ff7b31718f7ef1bc50d709f8d03cb012e10a3135eb99c7206 languageName: node linkType: hard @@ -2679,15 +2189,6 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" - dependencies: - hasown: "npm:^2.0.0" - checksum: 10c0/2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518 - languageName: node - linkType: hard - "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -2711,13 +2212,6 @@ __metadata: languageName: node linkType: hard -"is-obj@npm:^2.0.0": - version: 2.0.0 - resolution: "is-obj@npm:2.0.0" - checksum: 10c0/85044ed7ba8bd169e2c2af3a178cacb92a97aa75de9569d02efef7f443a824b5e153eba72b9ae3aca6f8ce81955271aa2dc7da67a8b720575d3e38104208cb4e - languageName: node - linkType: hard - "is-plain-obj@npm:^4.1.0": version: 4.1.0 resolution: "is-plain-obj@npm:4.1.0" @@ -2725,6 +2219,13 @@ __metadata: languageName: node linkType: hard +"is-unicode-supported@npm:^2.0.0": + version: 2.1.0 + resolution: "is-unicode-supported@npm:2.1.0" + checksum: 10c0/a0f53e9a7c1fdbcf2d2ef6e40d4736fdffff1c9f8944c75e15425118ff3610172c87bf7bc6c34d3903b04be59790bb2212ddbe21ee65b5a97030fc50370545a5 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -2739,31 +2240,12 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": - version: 3.2.2 - resolution: "istanbul-lib-coverage@npm:3.2.2" - checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b - languageName: node - linkType: hard - -"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": - version: 3.0.1 - resolution: "istanbul-lib-report@npm:3.0.1" - dependencies: - istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^4.0.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.2.0": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" +"jackspeak@npm:^4.1.1": + version: 4.2.3 + resolution: "jackspeak@npm:4.2.3" dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc + "@isaacs/cliui": "npm:^9.0.0" + checksum: 10c0/b5c0c414f1607c2aa0597f4bf2c03b8443897fccd5fd3c2b3e4f77d556b2bc7c3d3413828ba91e0789f6fb40ad90242f7f89fb20aee9e9d705bc1681f7564f67 languageName: node linkType: hard @@ -2776,13 +2258,6 @@ __metadata: languageName: node linkType: hard -"jju@npm:~1.4.0": - version: 1.4.0 - resolution: "jju@npm:1.4.0" - checksum: 10c0/f3f444557e4364cfc06b1abf8331bf3778b26c0c8552ca54429bc0092652172fdea26cbffe33e1017b303d5aa506f7ede8571857400efe459cb7439180e2acad - languageName: node - linkType: hard - "js-tokens@npm:^10.0.0": version: 10.0.0 resolution: "js-tokens@npm:10.0.0" @@ -2808,13 +2283,6 @@ __metadata: languageName: node linkType: hard -"json-buffer@npm:3.0.1": - version: 3.0.1 - resolution: "json-buffer@npm:3.0.1" - checksum: 10c0/0d1c91569d9588e7eef2b49b59851f297f3ab93c7b35c7c221e288099322be6b562767d11e4821da500f3219542b9afd2e54c5dc573107c1126ed1080f8e96d7 - languageName: node - linkType: hard - "json-parse-even-better-errors@npm:^2.3.0": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -2843,25 +2311,12 @@ __metadata: languageName: node linkType: hard -"jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" - dependencies: - graceful-fs: "npm:^4.1.6" - universalify: "npm:^2.0.0" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 - languageName: node - linkType: hard - -"keyv@npm:^4.5.4": - version: 4.5.4 - resolution: "keyv@npm:4.5.4" +"keyv@npm:^5.6.0": + version: 5.6.0 + resolution: "keyv@npm:5.6.0" dependencies: - json-buffer: "npm:3.0.1" - checksum: 10c0/aa52f3c5e18e16bb6324876bb8b59dd02acf782a4b789c7b2ae21107fab95fab3890ed448d4f8dba80ce05391eeac4bfabb4f02a20221342982f806fa2cf271e + "@keyv/serialize": "npm:^1.1.1" + checksum: 10c0/c3ea795b6e03593ca57c8f70928a69bad14c13389a7fb75649a115ff55615244b04d8902798d841c17f0bb4a8a8866c97133b543b93f151b440170bba09176db languageName: node linkType: hard @@ -2882,6 +2337,126 @@ __metadata: languageName: node linkType: hard +"lightningcss-android-arm64@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-android-arm64@npm:1.33.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-arm64@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-darwin-arm64@npm:1.33.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-darwin-x64@npm:1.33.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-freebsd-x64@npm:1.33.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.33.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.33.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.33.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.33.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-linux-x64-musl@npm:1.33.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-arm64-msvc@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-win32-arm64-msvc@npm:1.33.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.33.0": + version: 1.33.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.33.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:^1.33.0": + version: 1.33.0 + resolution: "lightningcss@npm:1.33.0" + dependencies: + detect-libc: "npm:^2.0.3" + lightningcss-android-arm64: "npm:1.33.0" + lightningcss-darwin-arm64: "npm:1.33.0" + lightningcss-darwin-x64: "npm:1.33.0" + lightningcss-freebsd-x64: "npm:1.33.0" + lightningcss-linux-arm-gnueabihf: "npm:1.33.0" + lightningcss-linux-arm64-gnu: "npm:1.33.0" + lightningcss-linux-arm64-musl: "npm:1.33.0" + lightningcss-linux-x64-gnu: "npm:1.33.0" + lightningcss-linux-x64-musl: "npm:1.33.0" + lightningcss-win32-arm64-msvc: "npm:1.33.0" + lightningcss-win32-x64-msvc: "npm:1.33.0" + dependenciesMeta: + lightningcss-android-arm64: + optional: true + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-arm64-msvc: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 10c0/ce1f8279fbae636dbf37fa6e7385d5f98ed881d72af3362f24afbd4685e19c1fcdfecf17e5dd77f2ebee3d0c23ade276230d85842d07292229a2cffba8ff20a3 + languageName: node + linkType: hard + "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -2889,14 +2464,14 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^1.0.0": - version: 1.1.2 - resolution: "local-pkg@npm:1.1.2" +"local-pkg@npm:^1.1.1": + version: 1.2.1 + resolution: "local-pkg@npm:1.2.1" dependencies: mlly: "npm:^1.7.4" pkg-types: "npm:^2.3.0" quansync: "npm:^0.2.11" - checksum: 10c0/1bcfcc5528dea95cba3caa478126a348d3985aad9f69ecf7802c13efef90897e1c5ff7851974332c5e6d4a4698efe610fef758a068c8bc3feb5322aeb35d5993 + checksum: 10c0/d21ccfc2595b2eddf7369f19797533573feb06820d8b5766467902a7a54e36b3a1f2b8cc2aa4481a2ad432c8e798576eabfac2f1ec0646a8e11a68694c2ef9d4 languageName: node linkType: hard @@ -2909,55 +2484,6 @@ __metadata: languageName: node linkType: hard -"lodash.camelcase@npm:^4.3.0": - version: 4.3.0 - resolution: "lodash.camelcase@npm:4.3.0" - checksum: 10c0/fcba15d21a458076dd309fce6b1b4bf611d84a0ec252cb92447c948c533ac250b95d2e00955801ebc367e5af5ed288b996d75d37d2035260a937008e14eaf432 - languageName: node - linkType: hard - -"lodash.kebabcase@npm:^4.1.1": - version: 4.1.1 - resolution: "lodash.kebabcase@npm:4.1.1" - checksum: 10c0/da5d8f41dbb5bc723d4bf9203d5096ca8da804d6aec3d2b56457156ba6c8d999ff448d347ebd97490da853cb36696ea4da09a431499f1ee8deb17b094ecf4e33 - languageName: node - linkType: hard - -"lodash.mergewith@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.mergewith@npm:4.6.2" - checksum: 10c0/4adbed65ff96fd65b0b3861f6899f98304f90fd71e7f1eb36c1270e05d500ee7f5ec44c02ef979b5ddbf75c0a0b9b99c35f0ad58f4011934c4d4e99e5200b3b5 - languageName: node - linkType: hard - -"lodash.snakecase@npm:^4.1.1": - version: 4.1.1 - resolution: "lodash.snakecase@npm:4.1.1" - checksum: 10c0/f0b3f2497eb20eea1a1cfc22d645ecaeb78ac14593eb0a40057977606d2f35f7aaff0913a06553c783b535aafc55b718f523f9eb78f8d5293f492af41002eaf9 - languageName: node - linkType: hard - -"lodash.startcase@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.startcase@npm:4.4.0" - checksum: 10c0/bd82aa87a45de8080e1c5ee61128c7aee77bf7f1d86f4ff94f4a6d7438fc9e15e5f03374b947be577a93804c8ad6241f0251beaf1452bf716064eeb657b3a9f0 - languageName: node - linkType: hard - -"lodash.upperfirst@npm:^4.3.1": - version: 4.3.1 - resolution: "lodash.upperfirst@npm:4.3.1" - checksum: 10c0/435625da4b3ee74e7a1367a780d9107ab0b13ef4359fc074b2a1a40458eb8d91b655af62f6795b7138d493303a98c0285340160341561d6896e4947e077fa975 - languageName: node - linkType: hard - -"lodash@npm:~4.17.23": - version: 4.17.23 - resolution: "lodash@npm:4.17.23" - checksum: 10c0/1264a90469f5bb95d4739c43eb6277d15b6d9e186df4ac68c3620443160fc669e2f14c11e7d8b2ccf078b81d06147c01a8ccced9aab9f9f63d50dcf8cace6bf6 - languageName: node - linkType: hard - "lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": version: 11.2.6 resolution: "lru-cache@npm:11.2.6" @@ -2965,15 +2491,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 - languageName: node - linkType: hard - "magic-string@npm:^0.30.17": version: 0.30.17 resolution: "magic-string@npm:0.30.17" @@ -2983,39 +2500,23 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.21": - version: 0.30.21 - resolution: "magic-string@npm:0.30.21" +"magic-string@npm:^1.2.3": + version: 1.4.2 + resolution: "magic-string@npm:1.4.2" dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.5" - checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + "@jridgewell/sourcemap-codec": "npm:^1.6.0" + checksum: 10c0/d3e222c202f99ec4861e7316f473f9b1cfe335ebdf38d4f67335f842f3fe248f01ee00fd3e1a8206bcbe9855e0c41515d7c210300d8fcf6eefbb982d79e423c6 languageName: node linkType: hard -"magicast@npm:^0.5.1": - version: 0.5.2 - resolution: "magicast@npm:0.5.2" +"magicast@npm:^0.5.4": + version: 0.5.5 + resolution: "magicast@npm:0.5.5" dependencies: - "@babel/parser": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" source-map-js: "npm:^1.2.1" - checksum: 10c0/924af677643c5a0a7d6cdb3247c0eb96fa7611b2ba6a5e720d35d81c503d3d9f5948eb5227f80f90f82ea3e7d38cffd10bb988f3fc09020db428e14f26e960d7 - languageName: node - linkType: hard - -"make-dir@npm:^4.0.0": - version: 4.0.0 - resolution: "make-dir@npm:4.0.0" - dependencies: - semver: "npm:^7.5.3" - checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 - languageName: node - linkType: hard - -"make-error@npm:^1.1.1": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f + checksum: 10c0/d27e94cd1e85f1736f97ab0c6e542170a818c7e573261722d056b3ec4a520e16d836ce4c6b0cd3dd215b1171d83592d48a3736f3da5997a55629a0de05f66e7d languageName: node linkType: hard @@ -3038,21 +2539,16 @@ __metadata: languageName: node linkType: hard -"meow@npm:^12.0.1": - version: 12.1.1 - resolution: "meow@npm:12.1.1" - checksum: 10c0/a125ca99a32e2306e2f4cbe651a0d27f6eb67918d43a075f6e80b35e9bf372ebf0fc3a9fbc201cbbc9516444b6265fb3c9f80c5b7ebd32f548aa93eb7c28e088 - languageName: node - linkType: hard - -"meow@npm:^13.0.0": - version: 13.2.0 - resolution: "meow@npm:13.2.0" - checksum: 10c0/d5b339ae314715bcd0b619dd2f8a266891928e21526b4800d49b4fba1cc3fff7e2c1ff5edd3344149fac841bc2306157f858e8c4d5eaee4d52ce52ad925664ce +"minimatch@npm:^10.1.1, minimatch@npm:^10.2.5": + version: 10.2.6 + resolution: "minimatch@npm:10.2.6" + dependencies: + brace-expansion: "npm:^5.0.8" + checksum: 10c0/4559a836243b98bd4d17ea9f7edae698717c76399eea7be374f3737f33164e4907f19e9726891ddeb122f750a5a7fa80d2ac43e851d6e5984dc4ff42ec127d3a languageName: node linkType: hard -"minimatch@npm:10.2.4, minimatch@npm:^10.2.2, minimatch@npm:^10.2.4": +"minimatch@npm:^10.2.2, minimatch@npm:^10.2.4": version: 10.2.4 resolution: "minimatch@npm:10.2.4" dependencies: @@ -3061,22 +2557,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.7": - version: 9.0.7 - resolution: "minimatch@npm:9.0.7" - dependencies: - brace-expansion: "npm:^5.0.2" - checksum: 10c0/e90f8d8dd1dd3e1257b29c8cb31f554e74e2b89d52391b3903b566a28a287b59e2077a25552bc90a31bbbb79113a59e7422c7783ed9f968fe21c2ccb3c67bdef - languageName: node - linkType: hard - -"minimist@npm:^1.2.8": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 - languageName: node - linkType: hard - "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -3186,19 +2666,12 @@ __metadata: languageName: node linkType: hard -"muggle-string@npm:^0.4.1": - version: 0.4.1 - resolution: "muggle-string@npm:0.4.1" - checksum: 10c0/e914b63e24cd23f97e18376ec47e4ba3aa24365e4776212b666add2e47bb158003212980d732c49abf3719568900af7861873844a6e2d3a7ca7e86952c0e99e9 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.11": - version: 3.3.11 - resolution: "nanoid@npm:3.3.11" +"nanoid@npm:^3.3.18": + version: 3.3.19 + resolution: "nanoid@npm:3.3.19" bin: nanoid: bin/nanoid.cjs - checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b + checksum: 10c0/ce7afa6258bfaa00bdc8de291cfe9913280eaa403b7d9cff3db4e4200c1913e7163577df74897958da144db473a96c67f74f57db0f542fbfe409df677bae3255 languageName: node linkType: hard @@ -3247,10 +2720,28 @@ __metadata: languageName: node linkType: hard -"obug@npm:^2.1.1": - version: 2.1.1 - resolution: "obug@npm:2.1.1" - checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 +"nunjucks@npm:^3.2.4": + version: 3.2.4 + resolution: "nunjucks@npm:3.2.4" + dependencies: + a-sync-waterfall: "npm:^1.0.0" + asap: "npm:^2.0.3" + commander: "npm:^5.1.0" + peerDependencies: + chokidar: ^3.3.0 + peerDependenciesMeta: + chokidar: + optional: true + bin: + nunjucks-precompile: bin/precompile + checksum: 10c0/7fe5197559b7c09972c79e2a86f9c093459b9075bc9b41134cd2bc599ae93567b53bd09d472a748edc736192d9ccd2998aa8c20cfcbe6a3fffd281f91897c888 + languageName: node + linkType: hard + +"obug@npm:^2.1.4": + version: 2.2.1 + resolution: "obug@npm:2.2.1" + checksum: 10c0/8a7c001847d880fa6ba83c7bbee6a80fd271ee628439cd508c8647d53b217abb1759e2d5e4aaeb09a35d0a274bdb225a0a5a78eded3213d63e656153cf411b63 languageName: node linkType: hard @@ -3293,6 +2784,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -3335,14 +2833,7 @@ __metadata: languageName: node linkType: hard -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^2.0.2": +"path-scurry@npm:^2.0.0, path-scurry@npm:^2.0.2": version: 2.0.2 resolution: "path-scurry@npm:2.0.2" dependencies: @@ -3380,6 +2871,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.4, picomatch@npm:^4.0.7": + version: 4.0.7 + resolution: "picomatch@npm:4.0.7" + checksum: 10c0/beb6ae02c43ae44e84883b90830196d9046b1726ead292adcf7f57945e0bb0d992d68563d87e03b484b6f3c9a5c6defda7523477f047d7f0e663f126cc01787f + languageName: node + linkType: hard + "pkg-types@npm:^1.3.1": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" @@ -3402,14 +2900,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.5.6": - version: 8.5.8 - resolution: "postcss@npm:8.5.8" +"postcss@npm:^8.5.28": + version: 8.5.28 + resolution: "postcss@npm:8.5.28" dependencies: - nanoid: "npm:^3.3.11" + nanoid: "npm:^3.3.18" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10c0/dd918f7127ee7c60a0295bae2e72b3787892296e1d1c3c564d7a2a00c68d8df83cadc3178491259daa19ccc54804fb71ed8c937c6787e08d8bd4bedf8d17044c + checksum: 10c0/9fe44215a6628d89c8a75184b92f5b2f77e16f9e5b13b39b9009bb7e8e6eccddf82c8854bae922db1f17ace6ef3445073fe38abff513caeb03e5285b1b55620a languageName: node linkType: hard @@ -3434,6 +2932,15 @@ __metadata: languageName: node linkType: hard +"qified@npm:^0.10.1": + version: 0.10.1 + resolution: "qified@npm:0.10.1" + dependencies: + hookified: "npm:^2.1.1" + checksum: 10c0/4a39d45492c65a4b9795381acede1bd566028ce9764ead5b41d776b391a898bf0855dd2b59d724a6711fe253ba3cacf7c9a8832887cf9dc6d48a2c5e4997c82d + languageName: node + linkType: hard + "quansync@npm:^0.2.11": version: 0.2.11 resolution: "quansync@npm:0.2.11" @@ -3469,32 +2976,6 @@ __metadata: languageName: node linkType: hard -"resolve@npm:~1.22.1, resolve@npm:~1.22.2": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/07e179f4375e1fd072cfb72ad66d78547f86e6196c4014b31cb0b8bb1db5f7ca871f922d08da0fbc05b94e9fd42206f819648fa3b5b873ebbc8e1dc68fec433a - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A~1.22.1#optional!builtin, resolve@patch:resolve@npm%3A~1.22.2#optional!builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/0446f024439cd2e50c6c8fa8ba77eaa8370b4180f401a96abf3d1ebc770ac51c1955e12764cde449fde3fff480a61f84388e3505ecdbab778f4bef5f8212c729 - languageName: node - linkType: hard - "retry@npm:^0.13.1": version: 0.13.1 resolution: "retry@npm:0.13.1" @@ -3502,93 +2983,61 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.43.0": - version: 4.59.0 - resolution: "rollup@npm:4.59.0" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.59.0" - "@rollup/rollup-android-arm64": "npm:4.59.0" - "@rollup/rollup-darwin-arm64": "npm:4.59.0" - "@rollup/rollup-darwin-x64": "npm:4.59.0" - "@rollup/rollup-freebsd-arm64": "npm:4.59.0" - "@rollup/rollup-freebsd-x64": "npm:4.59.0" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.59.0" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.59.0" - "@rollup/rollup-linux-arm64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-arm64-musl": "npm:4.59.0" - "@rollup/rollup-linux-loong64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-loong64-musl": "npm:4.59.0" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-ppc64-musl": "npm:4.59.0" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-riscv64-musl": "npm:4.59.0" - "@rollup/rollup-linux-s390x-gnu": "npm:4.59.0" - "@rollup/rollup-linux-x64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-x64-musl": "npm:4.59.0" - "@rollup/rollup-openbsd-x64": "npm:4.59.0" - "@rollup/rollup-openharmony-arm64": "npm:4.59.0" - "@rollup/rollup-win32-arm64-msvc": "npm:4.59.0" - "@rollup/rollup-win32-ia32-msvc": "npm:4.59.0" - "@rollup/rollup-win32-x64-gnu": "npm:4.59.0" - "@rollup/rollup-win32-x64-msvc": "npm:4.59.0" - "@types/estree": "npm:1.0.8" - fsevents: "npm:~2.3.2" +"rolldown@npm:~1.2.9": + version: 1.2.11 + resolution: "rolldown@npm:1.2.11" + dependencies: + "@oxc-project/types": "npm:=0.151.0" + "@rolldown/binding-android-arm-eabi": "npm:1.2.11" + "@rolldown/binding-android-arm64": "npm:1.2.11" + "@rolldown/binding-darwin-arm64": "npm:1.2.11" + "@rolldown/binding-darwin-x64": "npm:1.2.11" + "@rolldown/binding-freebsd-x64": "npm:1.2.11" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.2.11" + "@rolldown/binding-linux-arm64-gnu": "npm:1.2.11" + "@rolldown/binding-linux-arm64-musl": "npm:1.2.11" + "@rolldown/binding-linux-ppc64-gnu": "npm:1.2.11" + "@rolldown/binding-linux-s390x-gnu": "npm:1.2.11" + "@rolldown/binding-linux-x64-gnu": "npm:1.2.11" + "@rolldown/binding-linux-x64-musl": "npm:1.2.11" + "@rolldown/binding-openharmony-arm64": "npm:1.2.11" + "@rolldown/binding-win32-arm64-msvc": "npm:1.2.11" + "@rolldown/binding-win32-x64-msvc": "npm:1.2.11" + "@rolldown/pluginutils": "npm:^1.0.0" dependenciesMeta: - "@rollup/rollup-android-arm-eabi": - optional: true - "@rollup/rollup-android-arm64": - optional: true - "@rollup/rollup-darwin-arm64": - optional: true - "@rollup/rollup-darwin-x64": - optional: true - "@rollup/rollup-freebsd-arm64": + "@rolldown/binding-android-arm-eabi": optional: true - "@rollup/rollup-freebsd-x64": + "@rolldown/binding-android-arm64": optional: true - "@rollup/rollup-linux-arm-gnueabihf": + "@rolldown/binding-darwin-arm64": optional: true - "@rollup/rollup-linux-arm-musleabihf": + "@rolldown/binding-darwin-x64": optional: true - "@rollup/rollup-linux-arm64-gnu": + "@rolldown/binding-freebsd-x64": optional: true - "@rollup/rollup-linux-arm64-musl": + "@rolldown/binding-linux-arm-gnueabihf": optional: true - "@rollup/rollup-linux-loong64-gnu": + "@rolldown/binding-linux-arm64-gnu": optional: true - "@rollup/rollup-linux-loong64-musl": + "@rolldown/binding-linux-arm64-musl": optional: true - "@rollup/rollup-linux-ppc64-gnu": + "@rolldown/binding-linux-ppc64-gnu": optional: true - "@rollup/rollup-linux-ppc64-musl": + "@rolldown/binding-linux-s390x-gnu": optional: true - "@rollup/rollup-linux-riscv64-gnu": + "@rolldown/binding-linux-x64-gnu": optional: true - "@rollup/rollup-linux-riscv64-musl": + "@rolldown/binding-linux-x64-musl": optional: true - "@rollup/rollup-linux-s390x-gnu": + "@rolldown/binding-openharmony-arm64": optional: true - "@rollup/rollup-linux-x64-gnu": + "@rolldown/binding-win32-arm64-msvc": optional: true - "@rollup/rollup-linux-x64-musl": - optional: true - "@rollup/rollup-openbsd-x64": - optional: true - "@rollup/rollup-openharmony-arm64": - optional: true - "@rollup/rollup-win32-arm64-msvc": - optional: true - "@rollup/rollup-win32-ia32-msvc": - optional: true - "@rollup/rollup-win32-x64-gnu": - optional: true - "@rollup/rollup-win32-x64-msvc": - optional: true - fsevents: + "@rolldown/binding-win32-x64-msvc": optional: true bin: - rollup: dist/bin/rollup - checksum: 10c0/f38742da34cfee5e899302615fa157aa77cb6a2a1495e5e3ce4cc9c540d3262e235bbe60caa31562bbfe492b01fdb3e7a8c43c39d842d3293bcf843123b766fc + rolldown: ./bin/cli.mjs + checksum: 10c0/43dfd083fb625a254c039bddfe04f3dd1d7cf8b84291ead835e3702e8050b7fee5e702c8280d3000b2541c0e24aaa3110bac4251bc2ca50a85fe1c8bbb48d2f5 languageName: node linkType: hard @@ -3608,23 +3057,21 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.5.3, semver@npm:^7.6.0": - version: 7.6.3 - resolution: "semver@npm:7.6.3" +"semver@npm:^7.5.2, semver@npm:^7.7.4": + version: 7.8.5 + resolution: "semver@npm:7.8.5" bin: semver: bin/semver.js - checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + checksum: 10c0/b1f3127a5be8125a94f37188b361c212466c292c6910adce3ec106cff5dc211ccaedc4739c11bb70fda59d6fc1f040a9bca289f4e093451521a2372e5231fe0c languageName: node linkType: hard -"semver@npm:~7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: "npm:^6.0.0" +"semver@npm:^7.6.0": + version: 7.6.3 + resolution: "semver@npm:7.6.3" bin: semver: bin/semver.js - checksum: 10c0/5160b06975a38b11c1ab55950cb5b8a23db78df88275d3d8a42ccf1f29e55112ac995b3a26a522c36e3b5f76b0445f1eef70d696b8c7862a2b4303d7b0e7609e + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf languageName: node linkType: hard @@ -3644,10 +3091,10 @@ __metadata: languageName: node linkType: hard -"siginfo@npm:^2.0.0": - version: 2.0.0 - resolution: "siginfo@npm:2.0.0" - checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 languageName: node linkType: hard @@ -3690,34 +3137,13 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": +"source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf languageName: node linkType: hard -"source-map@npm:~0.6.1": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 - languageName: node - linkType: hard - -"split2@npm:^4.0.0": - version: 4.2.0 - resolution: "split2@npm:4.2.0" - checksum: 10c0/b292beb8ce9215f8c642bb68be6249c5a4c7f332fc8ecadae7be5cbdf1ea95addc95f0459ef2e7ad9d45fd1064698a097e4eb211c83e772b49bc0ee423e91534 - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb - languageName: node - linkType: hard - "ssri@npm:^13.0.0": version: 13.0.1 resolution: "ssri@npm:13.0.1" @@ -3727,24 +3153,10 @@ __metadata: languageName: node linkType: hard -"stackback@npm:0.0.2": - version: 0.0.2 - resolution: "stackback@npm:0.0.2" - checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 - languageName: node - linkType: hard - -"std-env@npm:^3.10.0": - version: 3.10.0 - resolution: "std-env@npm:3.10.0" - checksum: 10c0/1814927a45004d36dde6707eaf17552a546769bc79a6421be2c16ce77d238158dfe5de30910b78ec30d95135cc1c59ea73ee22d2ca170f8b9753f84da34c427f - languageName: node - linkType: hard - -"string-argv@npm:~0.3.1": - version: 0.3.2 - resolution: "string-argv@npm:0.3.2" - checksum: 10c0/75c02a83759ad1722e040b86823909d9a2fc75d15dd71ec4b537c3560746e33b5f5a07f7332d1e3f88319909f82190843aa2f0a0d8c8d591ec08e93d5b8dec82 +"std-env@npm:^4.2.0": + version: 4.2.0 + resolution: "std-env@npm:4.2.0" + checksum: 10c0/40ac525ce7b7c556abc332a7376f14356eeb1a7f17f6ff9a003eb9f52326ff1f3745d3e1b43452675b1ec6fcc319f1b1d6f3b0d386cf3f91058479ad883cff69 languageName: node linkType: hard @@ -3759,6 +3171,27 @@ __metadata: languageName: node linkType: hard +"string-width@npm:^7.0.0, string-width@npm:^7.2.0": + version: 7.2.0 + resolution: "string-width@npm:7.2.0" + dependencies: + emoji-regex: "npm:^10.3.0" + get-east-asian-width: "npm:^1.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 10c0/eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9 + languageName: node + linkType: hard + +"string-width@npm:^8.2.1": + version: 8.3.0 + resolution: "string-width@npm:8.3.0" + dependencies: + get-east-asian-width: "npm:^1.5.0" + strip-ansi: "npm:^7.1.2" + checksum: 10c0/bc354b27772777c314e6792106f01586e959f36abb3d4b8ad46c4d4ee92d5e906acb10c1f3be97a85ae0ba1b11389094bc5672999fc5f03f12d22a4725fa30fe + languageName: node + linkType: hard + "strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" @@ -3768,10 +3201,12 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:~3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd +"strip-ansi@npm:^7.1.0, strip-ansi@npm:^7.1.2": + version: 7.2.0 + resolution: "strip-ansi@npm:7.2.0" + dependencies: + ansi-regex: "npm:^6.2.2" + checksum: 10c0/544d13b7582f8254811ea97db202f519e189e59d35740c46095897e254e4f1aa9fe1524a83ad6bc5ad67d4dd6c0281d2e0219ed62b880a6238a16a17d375f221 languageName: node linkType: hard @@ -3784,31 +3219,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 - languageName: node - linkType: hard - -"supports-color@npm:~8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 - languageName: node - linkType: hard - "tar@npm:^7.5.4": version: 7.5.10 resolution: "tar@npm:7.5.10" @@ -3822,20 +3232,27 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.9.0": - version: 2.9.0 - resolution: "tinybench@npm:2.9.0" - checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c +"tinybench@npm:^6.1.4": + version: 6.2.0 + resolution: "tinybench@npm:6.2.0" + checksum: 10c0/ae821428f0412324611d449290f8497c886c94f04bad8e19aa9b3a5060b4802e738c49f9eb493e4fd17e4d5e792290565e5079be647df1995aea731c82363815 languageName: node linkType: hard -"tinyexec@npm:^1.0.0, tinyexec@npm:^1.0.2": +"tinyexec@npm:^1.0.0": version: 1.0.2 resolution: "tinyexec@npm:1.0.2" checksum: 10c0/1261a8e34c9b539a9aae3b7f0bb5372045ff28ee1eba035a2a059e532198fe1a182ec61ac60fa0b4a4129f0c4c4b1d2d57355b5cb9aa2d17ac9454ecace502ee languageName: node linkType: hard +"tinyexec@npm:^1.3.0": + version: 1.3.1 + resolution: "tinyexec@npm:1.3.1" + checksum: 10c0/c590369cb3fa73cc18a3998caec8a00f9712d91309c881be3ac52b160fb2f80c7b1fbf3591858ab6abab47ad55385b0c86ec19982e32441a01f55298dab9ccd2 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" @@ -3846,17 +3263,20 @@ __metadata: languageName: node linkType: hard -"tinyrainbow@npm:^3.0.3": - version: 3.0.3 - resolution: "tinyrainbow@npm:3.0.3" - checksum: 10c0/1e799d35cd23cabe02e22550985a3051dc88814a979be02dc632a159c393a998628eacfc558e4c746b3006606d54b00bcdea0c39301133956d10a27aa27e988c +"tinyglobby@npm:^0.2.17": + version: 0.2.17 + resolution: "tinyglobby@npm:0.2.17" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.4" + checksum: 10c0/7f7bb0f197c88bc4b20c231e0deca4240ca3bf313a88f5a7fee93a872b84966a4d50220947c0455ad07a60b3b360961c5b7fd979222aeb716a9f99b412002e4c languageName: node linkType: hard -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: 10c0/b214d21dbfb4bce3452b6244b336806ffea9c05297148d32ebb428d5c43ce7545bdfc65a1ceb58c9ef4376a65c0cb2854d645f33961658b3e3b4f84910ddcdd7 +"tinyrainbow@npm:^3.1.1": + version: 3.1.1 + resolution: "tinyrainbow@npm:3.1.1" + checksum: 10c0/f9d2743832c6191f753408f36224fe817620b8abcef572b2e570204c673a901d753ff84ca8e7b88f9c79e934295b3ffc6fcbc56a06f126e24e1ec6186dcad40d languageName: node linkType: hard @@ -3867,50 +3287,12 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.4.0": - version: 2.4.0 - resolution: "ts-api-utils@npm:2.4.0" +"ts-api-utils@npm:^2.5.0": + version: 2.5.0 + resolution: "ts-api-utils@npm:2.5.0" peerDependencies: typescript: ">=4.8.4" - checksum: 10c0/ed185861aef4e7124366a3f6561113557a57504267d4d452a51e0ba516a9b6e713b56b4aeaab9fa13de9db9ab755c65c8c13a777dba9133c214632cb7b65c083 - languageName: node - linkType: hard - -"ts-node@npm:^10.9.2": - version: 10.9.2 - resolution: "ts-node@npm:10.9.2" - dependencies: - "@cspotcode/source-map-support": "npm:^0.8.0" - "@tsconfig/node10": "npm:^1.0.7" - "@tsconfig/node12": "npm:^1.0.7" - "@tsconfig/node14": "npm:^1.0.0" - "@tsconfig/node16": "npm:^1.0.2" - acorn: "npm:^8.4.1" - acorn-walk: "npm:^8.1.1" - arg: "npm:^4.1.0" - create-require: "npm:^1.1.0" - diff: "npm:^4.0.1" - make-error: "npm:^1.1.1" - v8-compile-cache-lib: "npm:^3.0.1" - yn: "npm:3.1.1" - 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 - bin: - ts-node: dist/bin.js - ts-node-cwd: dist/bin-cwd.js - ts-node-esm: dist/bin-esm.js - ts-node-script: dist/bin-script.js - ts-node-transpile-only: dist/bin-transpile.js - ts-script: dist/bin-script-deprecated.js - checksum: 10c0/5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2 + checksum: 10c0/767849383c114e7f1971fa976b20e73ac28fd0c70d8d65c0004790bf4d8f89888c7e4cf6d5949f9c1beae9bc3c64835bef77bbe27fddf45a3c7b60cebcf85c8c languageName: node linkType: hard @@ -3930,58 +3312,38 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.56.1": - version: 8.56.1 - resolution: "typescript-eslint@npm:8.56.1" +"typescript-eslint@npm:^8.70.1": + version: 8.70.1 + resolution: "typescript-eslint@npm:8.70.1" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.56.1" - "@typescript-eslint/parser": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/eslint-plugin": "npm:8.70.1" + "@typescript-eslint/parser": "npm:8.70.1" + "@typescript-eslint/typescript-estree": "npm:8.70.1" + "@typescript-eslint/utils": "npm:8.70.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/c33aeb9a8beab54308412dcd460ab60f845fee30eaed1fdc1083ff53c430a4dcbdfeac862136a21fb3a639538f8712d933fc410680c2a650e67b992720a0d9f6 - languageName: node - linkType: hard - -"typescript@npm:5.8.2": - version: 5.8.2 - resolution: "typescript@npm:5.8.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6 - languageName: node - linkType: hard - -"typescript@npm:^5.5.4": - version: 5.7.2 - resolution: "typescript@npm:5.7.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/a873118b5201b2ef332127ef5c63fb9d9c155e6fdbe211cbd9d8e65877283797cca76546bad742eea36ed7efbe3424a30376818f79c7318512064e8625d61622 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/9d9a01dca7f0663b7dbe496c2e1697f0cf6a44570f7dd53926bf5ea80a54bb0f7ca1c88771d82eabc6083f7983a9dec24f6b4ed1957d0810d9e9e68a250cbc4d languageName: node linkType: hard -"typescript@patch:typescript@npm%3A5.8.2#optional!builtin": - version: 5.8.2 - resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin::version=5.8.2&hash=5786d5" +"typescript@npm:~6.0.3": + version: 6.0.3 + resolution: "typescript@npm:6.0.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/5448a08e595cc558ab321e49d4cac64fb43d1fa106584f6ff9a8d8e592111b373a995a1d5c7f3046211c8a37201eb6d0f1566f15cdb7a62a5e3be01d087848e2 + checksum: 10c0/4a25ff5045b984370f48f196b3a0120779b1b343d40b9a68d114ea5e5fff099809b2bb777576991a63a5cd59cf7bffd96ff6fe10afcefbcb8bd6fb96ad4b6606 languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.5.4#optional!builtin": - version: 5.7.2 - resolution: "typescript@patch:typescript@npm%3A5.7.2#optional!builtin::version=5.7.2&hash=5786d5" +"typescript@patch:typescript@npm%3A~6.0.3#optional!builtin": + version: 6.0.3 + resolution: "typescript@patch:typescript@npm%3A6.0.3#optional!builtin::version=6.0.3&hash=5786d5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/f3b8082c9d1d1629a215245c9087df56cb784f9fb6f27b5d55577a20e68afe2a889c040aacff6d27e35be165ecf9dca66e694c42eb9a50b3b2c451b36b5675cb + checksum: 10c0/2f25c74e65663c248fa1ade2b8459d9ce5372ff9dad07067310f132966ebec1d93f6c42f0baf77a6b6a7a91460463f708e6887013aaade22111037457c6b25df languageName: node linkType: hard @@ -3992,10 +3354,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~7.18.0": - version: 7.18.2 - resolution: "undici-types@npm:7.18.2" - checksum: 10c0/85a79189113a238959d7a647368e4f7c5559c3a404ebdb8fc4488145ce9426fcd82252a844a302798dfc0e37e6fb178ff481ed03bc4caf634c5757d9ef43521d +"undici-types@npm:>=7.24.0 <7.24.7": + version: 7.24.6 + resolution: "undici-types@npm:7.24.6" + checksum: 10c0/d9cd8befb643ac904615c280a095ba4240531f6bb4a5e75a22a7483630ca8d3f1016d2ab6ace6ceda1f63b3a2db2fe037fafe121d6917a0187573aa548ff78ca languageName: node linkType: hard @@ -4017,68 +3379,87 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^2.0.0": - version: 2.0.1 - resolution: "universalify@npm:2.0.1" - checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: "npm:^2.1.0" - checksum: 10c0/4ef57b45aa820d7ac6496e9208559986c665e49447cb072744c13b66925a362d96dd5a46c4530a6b8e203e5db5fe849369444440cb22ecfc26c679359e5dfa3c - languageName: node - linkType: hard - -"v8-compile-cache-lib@npm:^3.0.1": - version: 3.0.1 - resolution: "v8-compile-cache-lib@npm:3.0.1" - checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 - languageName: node - linkType: hard - -"vite-plugin-dts@npm:^4.5.4": - version: 4.5.4 - resolution: "vite-plugin-dts@npm:4.5.4" +"unplugin-dts@npm:^1.1.1": + version: 1.1.1 + resolution: "unplugin-dts@npm:1.1.1" dependencies: - "@microsoft/api-extractor": "npm:^7.50.1" "@rollup/pluginutils": "npm:^5.1.4" - "@volar/typescript": "npm:^2.4.11" - "@vue/language-core": "npm:2.2.0" + "@volar/typescript": "npm:^2.4.26" compare-versions: "npm:^6.1.1" debug: "npm:^4.4.0" + glob-to-regexp: "npm:0.4.1" kolorist: "npm:^1.8.0" - local-pkg: "npm:^1.0.0" + local-pkg: "npm:^1.1.1" magic-string: "npm:^0.30.17" + unplugin: "npm:^2.3.2" peerDependencies: - typescript: "*" - vite: "*" + "@microsoft/api-extractor": ">=7" + "@rspack/core": ^1 + "@vue/language-core": ^3.1.5 + esbuild: "*" + rolldown: "*" + rollup: ">=3" + typescript: ">=4" + vite: ">=3" + webpack: ^4 || ^5 peerDependenciesMeta: + "@microsoft/api-extractor": + optional: true + "@rspack/core": + optional: true + "@vue/language-core": + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true vite: optional: true - checksum: 10c0/5fcb7f3739d115f36195a692c0e9f9fca4e504bbbbabe29e71ee06630dd05ea2920169371e80e548eb4779d2eca14107277497838d7df588d53e1fadf84be861 + webpack: + optional: true + checksum: 10c0/21759ef53f4dd99b2d87af672509ae2c791454cb136bf843d890c7773a9e5a5a13af15c62caaa1020f622da07c23de94ee2a0e0bd23539a9fedb9b461158f975 languageName: node linkType: hard -"vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.3.1": - version: 7.3.1 - resolution: "vite@npm:7.3.1" +"unplugin@npm:^2.3.2": + version: 2.3.11 + resolution: "unplugin@npm:2.3.11" dependencies: - esbuild: "npm:^0.27.0" - fdir: "npm:^6.5.0" - fsevents: "npm:~2.3.3" + "@jridgewell/remapping": "npm:^2.3.5" + acorn: "npm:^8.15.0" picomatch: "npm:^4.0.3" - postcss: "npm:^8.5.6" - rollup: "npm:^4.43.0" - tinyglobby: "npm:^0.2.15" + webpack-virtual-modules: "npm:^0.6.2" + checksum: 10c0/273c1eab0eca4470c7317428689295c31dbe8ab0b306504de9f03cd20c156debb4131bef24b27ac615862958c5dd950a3951d26c0723ea774652ab3624149cff + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: "npm:^2.1.0" + checksum: 10c0/4ef57b45aa820d7ac6496e9208559986c665e49447cb072744c13b66925a362d96dd5a46c4530a6b8e203e5db5fe849369444440cb22ecfc26c679359e5dfa3c + languageName: node + linkType: hard + +"vite@npm:^8.3.1": + version: 8.3.1 + resolution: "vite@npm:8.3.1" + dependencies: + fsevents: "npm:~2.3.3" + lightningcss: "npm:^1.33.0" + picomatch: "npm:^4.0.7" + postcss: "npm:^8.5.28" + rolldown: "npm:~1.2.9" + tinyglobby: "npm:^0.2.17" peerDependencies: "@types/node": ^20.19.0 || >=22.12.0 + "@vitejs/devtools": ^0.7.1 + esbuild: ^0.27.0 || ^0.28.0 jiti: ">=1.21.0" less: ^4.0.0 - lightningcss: ^1.21.0 sass: ^1.70.0 sass-embedded: ^1.70.0 stylus: ">=0.54.8" @@ -4092,12 +3473,14 @@ __metadata: peerDependenciesMeta: "@types/node": optional: true + "@vitejs/devtools": + optional: true + esbuild: + optional: true jiti: optional: true less: optional: true - lightningcss: - optional: true sass: optional: true sass-embedded: @@ -4114,44 +3497,40 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/5c7548f5f43a23533e53324304db4ad85f1896b1bfd3ee32ae9b866bac2933782c77b350eb2b52a02c625c8ad1ddd4c000df077419410650c982cd97fde8d014 + checksum: 10c0/a91f4fee1cd331912ee3ac45f49900044846e28b8632ae734fe1978630e643e503d04181b2aeac59f70556fc51137dd49179fd39cbeb72a3e5f0bce88d2bcd30 languageName: node linkType: hard -"vitest@npm:^4.0.18": - version: 4.0.18 - resolution: "vitest@npm:4.0.18" +"vitest@npm:5.0.2": + version: 5.0.2 + resolution: "vitest@npm:5.0.2" dependencies: - "@vitest/expect": "npm:4.0.18" - "@vitest/mocker": "npm:4.0.18" - "@vitest/pretty-format": "npm:4.0.18" - "@vitest/runner": "npm:4.0.18" - "@vitest/snapshot": "npm:4.0.18" - "@vitest/spy": "npm:4.0.18" - "@vitest/utils": "npm:4.0.18" - es-module-lexer: "npm:^1.7.0" - expect-type: "npm:^1.2.2" - magic-string: "npm:^0.30.21" - obug: "npm:^2.1.1" - pathe: "npm:^2.0.3" - picomatch: "npm:^4.0.3" - std-env: "npm:^3.10.0" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^1.0.2" - tinyglobby: "npm:^0.2.15" - tinyrainbow: "npm:^3.0.3" - vite: "npm:^6.0.0 || ^7.0.0" - why-is-node-running: "npm:^2.3.0" + "@types/chai": "npm:^5.2.2" + "@vitest/mocker": "npm:5.0.2" + chai: "npm:^6.2.2" + es-module-lexer: "npm:^2.3.2" + expect-type: "npm:^1.4.0" + magic-string: "npm:^1.2.3" + obug: "npm:^2.1.4" + picomatch: "npm:^4.0.7" + std-env: "npm:^4.2.0" + tinybench: "npm:^6.1.4" + tinyexec: "npm:^1.3.0" + tinyglobby: "npm:^0.2.17" + why-is-node-running: "npm:^3.2.1" peerDependencies: "@edge-runtime/vm": "*" "@opentelemetry/api": ^1.9.0 - "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.0.18 - "@vitest/browser-preview": 4.0.18 - "@vitest/browser-webdriverio": 4.0.18 - "@vitest/ui": 4.0.18 + "@types/node": ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 5.0.2 + "@vitest/browser-preview": 5.0.2 + "@vitest/browser-webdriverio": ^5.0.0-beta.5 || >=5.0.0 + "@vitest/coverage-istanbul": 5.0.2 + "@vitest/coverage-v8": 5.0.2 + "@vitest/ui": 5.0.2 happy-dom: "*" jsdom: "*" + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: "@edge-runtime/vm": optional: true @@ -4165,15 +3544,21 @@ __metadata: optional: true "@vitest/browser-webdriverio": optional: true + "@vitest/coverage-istanbul": + optional: true + "@vitest/coverage-v8": + optional: true "@vitest/ui": optional: true happy-dom: optional: true jsdom: optional: true + vite: + optional: false bin: - vitest: vitest.mjs - checksum: 10c0/b913cd32032c95f29ff08c931f4b4c6fd6d2da498908d6770952c561a1b8d75c62499a1f04cadf82fb89cc0f9a33f29fb5dfdb899f6dbb27686a9d91571be5fa + vitest: ./vitest.mjs + checksum: 10c0/e86919375db85ddecc6308076341f66a9d51c3b28aa7966ea6bcb0f45234b5e2883602c17e509abfa6d729aaf8113b3adf7b59a8316079c2c9a48dbb1b248897 languageName: node linkType: hard @@ -4184,6 +3569,13 @@ __metadata: languageName: node linkType: hard +"webpack-virtual-modules@npm:^0.6.2": + version: 0.6.2 + resolution: "webpack-virtual-modules@npm:0.6.2" + checksum: 10c0/5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -4206,15 +3598,12 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.3.0": - version: 2.3.0 - resolution: "why-is-node-running@npm:2.3.0" - dependencies: - siginfo: "npm:^2.0.0" - stackback: "npm:0.0.2" +"why-is-node-running@npm:^3.2.1": + version: 3.2.2 + resolution: "why-is-node-running@npm:3.2.2" bin: why-is-node-running: cli.js - checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + checksum: 10c0/47307bfc2f48dd5228a92103dc43a7cadafbc6b6791c114fd27e03ac271a5082849a54f7e5f5cb261ea68f0d4ad40d9cb503b55812a6b62e67de0c57039fb95b languageName: node linkType: hard @@ -4229,6 +3618,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^9.0.0": + version: 9.0.2 + resolution: "wrap-ansi@npm:9.0.2" + dependencies: + ansi-styles: "npm:^6.2.1" + string-width: "npm:^7.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 10c0/3305839b9a0d6fb930cb63a52f34d3936013d8b0682ff3ec133c9826512620f213800ffa19ea22904876d5b7e9a3c1f40682f03597d986a4ca881fa7b033688c + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -4257,9 +3657,16 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.0.0": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" +"yargs-parser@npm:^22.0.0": + version: 22.0.0 + resolution: "yargs-parser@npm:22.0.0" + checksum: 10c0/cb7ef81759c4271cb1d96b9351dbbc9a9ce35d3e1122d2b739bf6c432603824fa02c67cc12dcef6ea80283379d63495686e8f41cc7b06c6576e792aba4d33e1c + languageName: node + linkType: hard + +"yargs@npm:^17.7.2": + version: 17.7.3 + resolution: "yargs@npm:17.7.3" dependencies: cliui: "npm:^8.0.1" escalade: "npm:^3.1.1" @@ -4268,14 +3675,21 @@ __metadata: string-width: "npm:^4.2.3" y18n: "npm:^5.0.5" yargs-parser: "npm:^21.1.1" - checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 + checksum: 10c0/7a28572f7e785a57886e34fdbddb9b28756dec552e1453d5f6e7cdd00ad8721a4e8c4321d33683f5e61cacb36ad43258adbb48396b71ec4ed14abee0fc0d0c1f languageName: node linkType: hard -"yn@npm:3.1.1": - version: 3.1.1 - resolution: "yn@npm:3.1.1" - checksum: 10c0/0732468dd7622ed8a274f640f191f3eaf1f39d5349a1b72836df484998d7d9807fbea094e2f5486d6b0cd2414aad5775972df0e68f8604db89a239f0f4bf7443 +"yargs@npm:^18.0.0": + version: 18.2.0 + resolution: "yargs@npm:18.2.0" + dependencies: + cliui: "npm:^9.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + string-width: "npm:^8.2.1" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^22.0.0" + checksum: 10c0/7419338c3c00f9143ec6b6ab168335061c6f5342d161642aec23ff119e28cac1c417e0eca1d7dc82fd084f07207cc5d34c7d8315f605c0e3dbf12c350e405f3f languageName: node linkType: hard