From 09310aa50a42fb901da736276e39326f66d2ac8b Mon Sep 17 00:00:00 2001 From: Jonathan Gan Date: Sun, 9 Aug 2026 06:13:36 -0400 Subject: [PATCH 1/2] Publish protocol 0.1.1 deletion routing --- .github/workflows/ci.yml | 43 + README.md | 6 +- docs/opendating/PROTOCOL-0.1.1-RELEASE.md | 16 + docs/opendating/PROTOCOL.md | 13 +- docs/opendating/ROADMAP.md | 80 +- package-lock.json | 3277 ++++++++--------- package.json | 6 +- packages/protocol/README.md | 4 + packages/protocol/dist/index.d.ts | 4 +- packages/protocol/dist/index.d.ts.map | 2 +- packages/protocol/dist/index.js | 3 +- packages/protocol/dist/index.js.map | 2 +- .../protocol/dist/protocol/constants.d.ts | 4 +- .../protocol/dist/protocol/constants.d.ts.map | 2 +- packages/protocol/dist/protocol/constants.js | 2 +- .../protocol/dist/protocol/constants.js.map | 2 +- packages/protocol/dist/protocol/routing.d.ts | 108 + .../protocol/dist/protocol/routing.d.ts.map | 1 + packages/protocol/dist/protocol/routing.js | 44 + .../protocol/dist/protocol/routing.js.map | 1 + packages/protocol/package-lock.json | 8 +- packages/protocol/package.json | 2 +- packages/protocol/src/index.ts | 8 +- packages/protocol/src/protocol/constants.ts | 7 +- packages/protocol/src/protocol/routing.ts | 59 + src/protocols/opendating/identities/loader.ts | 3 +- .../opendating/protocol/constants.ts | 7 +- src/protocols/opendating/protocol/routing.ts | 59 + .../opendating/services/block/service.ts | 33 +- tests/opendating/conformance/protocol.test.ts | 33 + tests/opendating/integration/services.test.ts | 70 + .../unit/service-identities.test.ts | 6 + worker.js | 500 ++- 33 files changed, 2393 insertions(+), 2022 deletions(-) create mode 100644 docs/opendating/PROTOCOL-0.1.1-RELEASE.md create mode 100644 packages/protocol/dist/protocol/routing.d.ts create mode 100644 packages/protocol/dist/protocol/routing.d.ts.map create mode 100644 packages/protocol/dist/protocol/routing.js create mode 100644 packages/protocol/dist/protocol/routing.js.map create mode 100644 packages/protocol/src/protocol/routing.ts create mode 100644 src/protocols/opendating/protocol/routing.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee112de..8a456ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [main] +permissions: + contents: read + jobs: ci: runs-on: ubuntu-latest @@ -23,9 +26,15 @@ jobs: - run: npm ci + - name: Production dependency audit + run: npm audit --omit=dev --audit-level=high + - name: Type check run: npm run typecheck + - name: Lint + run: npm run lint + - name: Build run: npm run build @@ -36,6 +45,26 @@ jobs: - name: Tests run: npm test + - name: Install protocol package dependencies + working-directory: packages/protocol + run: npm ci + + - name: Build and pack protocol package + working-directory: packages/protocol + run: | + npm run build + npm pack --dry-run + + - name: Generate SBOM + run: npm sbom --sbom-format cyclonedx > sbom.cdx.json + + - uses: actions/upload-artifact@v4 + with: + name: backend-sbom-cyclonedx + path: sbom.cdx.json + if-no-files-found: error + retention-days: 30 + - name: Verify build output run: | if [ ! -f worker.js ]; then @@ -43,3 +72,17 @@ jobs: exit 1 fi echo "Build output size: $(wc -c < worker.js) bytes" + + dependency-review: + name: Dependency review + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - if: github.event_name == 'pull_request' + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high + - if: github.event_name != 'pull_request' + run: echo "Dependency review applies to pull requests." diff --git a/README.md b/README.md index ec521ec..d8e3d58 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ npm install npm run build # Run tests -npm test # Full suite (82 tests) +npm test # Full suite (245 tests at 0.1.1 branch cut) npm run opendating:test:e2e # Protocol conformance tests # Deploy (requires Cloudflare account + wrangler config) @@ -126,13 +126,13 @@ npm run deploy ## Protocol Package ```bash -npm install opendating-protocol@0.1.0 +npm install opendating-protocol@0.1.1 ``` ```typescript import { createEnvelope, buildGiftWrap, nip44Encrypt, nip44Decrypt, - generateKeypair, validateEnvelope, OPENDATING_PROTOCOL, + generateKeypair, validateEnvelope, getRequestRoute, OPENDATING_PROTOCOL, type OpenDatingEnvelope, type GiftWrapResult, } from 'opendating-protocol'; ``` diff --git a/docs/opendating/PROTOCOL-0.1.1-RELEASE.md b/docs/opendating/PROTOCOL-0.1.1-RELEASE.md new file mode 100644 index 0000000..b8340ae --- /dev/null +++ b/docs/opendating/PROTOCOL-0.1.1-RELEASE.md @@ -0,0 +1,16 @@ +# opendating-protocol 0.1.1 + +Protocol wire version remains `0.1`. Package 0.1.1 is a backward-compatible contract repair. + +## Changes + +- Adds `deletion` to `OpenDatingServiceRole` and `ALL_SERVICE_ROLES`. +- Publishes `REQUEST_ROUTES` and `getRequestRoute()` with the service role and expected result type for every v0.1 request. +- Binds `account.delete` to the `deletion` role and `account.delete.result`. +- Corrects `block.remove` and `unmatch.create` routing to `dm_policy`. +- Implements idempotent `block.remove` in the reference service. +- Advertises `account.delete` and `block.remove` in service capability metadata. + +## Publication gate + +The package builds and the full backend suite passes. Registry publication requires an authenticated npm session and must be followed by a mobile lockfile update to the exact `0.1.1` artifact. diff --git a/docs/opendating/PROTOCOL.md b/docs/opendating/PROTOCOL.md index fe8142d..25ec3f5 100644 --- a/docs/opendating/PROTOCOL.md +++ b/docs/opendating/PROTOCOL.md @@ -109,13 +109,14 @@ The private key signs responses and decrypts incoming requests. | Role | Purpose | Status | |------|---------|--------| | `system` | Protocol-level operations | ✅ V0.1 | -| `profile` | User profiles | Planned | -| `discovery` | Candidate discovery | Planned | -| `matcher` | Like/match logic | Planned | -| `dm_policy` | Messaging policy | Planned | -| `moderation` | Reports and blocks | Planned | +| `profile` | User profiles | ✅ V0.1 baseline | +| `discovery` | Candidate discovery | ✅ V0.1 baseline | +| `matcher` | Like/match logic | ✅ V0.1 baseline | +| `dm_policy` | Messaging policy | ✅ V0.1 baseline | +| `moderation` | Reports and enforcement | ✅ V0.1 baseline; operator console pending | | `verification` | Identity verification | Planned | -| `media` | Image/media handling | Planned | +| `media` | Image/media handling | ✅ Hosted media baseline; revocable references pending | +| `deletion` | Account deletion and vanish | ✅ V0.1.1 | ## 7. Request Lifecycle diff --git a/docs/opendating/ROADMAP.md b/docs/opendating/ROADMAP.md index 0c07e7c..9c37466 100644 --- a/docs/opendating/ROADMAP.md +++ b/docs/opendating/ROADMAP.md @@ -11,57 +11,61 @@ **Status**: COMPLETE (PROTOCOL-CORE-COMPLETE.md) -## Phase 2: Membership + Profile (Next) +> This file tracks protocol implementation, not production readiness. The current backend is a tested beta baseline and still requires the security, trust-and-safety, legal, reliability, and marketplace gates documented in the mobile repository's `docs/RELEASE-STATUS.md`. -- [ ] User membership model -- [ ] Dating profile schema (kind 30078) -- [ ] Profile CRUD service -- [ ] Profile visibility settings -- [ ] Profile validation +## Phase 2: Membership + Profile ✅ baseline -## Phase 3: Location + Discovery +- [x] User membership model +- [x] Dating profile schema +- [x] Profile CRUD service +- [x] Profile visibility settings +- [x] Profile validation -- [ ] Location schema (geohash) -- [ ] Location update service -- [ ] Candidate discovery query -- [ ] Discovery preferences -- [ ] Distance-based filtering +## Phase 3: Location + Discovery ✅ baseline -## Phase 4: Private Likes + Matching +- [x] Location schema (geohash) +- [x] Location update service +- [x] Candidate discovery query +- [x] Discovery preferences +- [x] Distance-based filtering -- [ ] Like intent schema -- [ ] Like service -- [ ] Mutual match detection -- [ ] Match notification -- [ ] Match state management +## Phase 4: Private Likes + Matching ✅ baseline -## Phase 5: Match-Only Messaging (NIP-17) +- [x] Like intent schema +- [x] Like service +- [x] Mutual match detection +- [x] Match notification event +- [x] Match state management -- [ ] Match-gated DM policy -- [ ] NIP-17 sealed direct messages -- [ ] DM policy service -- [ ] Message history +## Phase 5: Match-Only Messaging (NIP-17) ⚠️ transport baseline -## Phase 6: Block + Unmatch +- [x] Match-gated DM policy +- [x] NIP-17 sealed direct messages +- [x] DM policy service +- [ ] Durable 90-day delivery history and client cursor synchronization -- [ ] Block schema -- [ ] Unmatch schema -- [ ] Block/unmatch service -- [ ] Enforcement in discovery and messaging +## Phase 6: Block + Unmatch ✅ backend baseline -## Phase 7: Reporting + Moderation +- [x] Block schema +- [x] Unmatch schema +- [x] Block/unmatch service, including idempotent removal +- [x] Server enforcement in discovery and messaging +- [ ] Global encrypted client persistence and inbound pre-render enforcement -- [ ] Report schema -- [ ] Moderation service -- [ ] Report queue -- [ ] Admin actions +## Phase 7: Reporting + Moderation ⚠️ operations incomplete -## Phase 8: Deletion / Vanish +- [x] Report schema +- [x] Moderation service baseline +- [x] Report queue baseline +- [x] Admin action protocol +- [ ] Production console, appeals, audit access, vendor moderation, and staffed SLAs -- [ ] Account deletion (NIP-62) -- [ ] Profile vanish -- [ ] Message vanish -- [ ] Data retention compliance +## Phase 8: Deletion / Vanish ⚠️ 0.1.1 contract fixed + +- [x] Account deletion service and dedicated advertised role +- [x] Profile/discovery relationship cascade and vanish tombstone +- [ ] Delivery-event and object-storage cascade verification +- [ ] Legal retention policy and 24-hour receipt/SLA ## Phase 9: Verification diff --git a/package-lock.json b/package-lock.json index 6cfc8e1..5ca4a0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20260101.0", - "esbuild": "^0.19.12", + "esbuild": "0.28.0", + "oxlint": "1.77.0", "sql.js": "^1.14.1", "typescript": "^7.0.2", "vitest": "^4.1.10", @@ -190,9 +191,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "cpu": [ "ppc64" ], @@ -203,13 +204,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "cpu": [ "arm" ], @@ -220,13 +221,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "cpu": [ "arm64" ], @@ -237,13 +238,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "cpu": [ "x64" ], @@ -254,13 +255,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "cpu": [ "arm64" ], @@ -271,13 +272,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "cpu": [ "x64" ], @@ -288,13 +289,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "cpu": [ "arm64" ], @@ -305,13 +306,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "cpu": [ "x64" ], @@ -322,13 +323,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "cpu": [ "arm" ], @@ -339,13 +340,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "cpu": [ "arm64" ], @@ -356,13 +357,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "cpu": [ "ia32" ], @@ -373,13 +374,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "cpu": [ "loong64" ], @@ -390,13 +391,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "cpu": [ "mips64el" ], @@ -407,13 +408,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "cpu": [ "ppc64" ], @@ -424,13 +425,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "cpu": [ "riscv64" ], @@ -441,13 +442,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "cpu": [ "s390x" ], @@ -458,13 +459,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "cpu": [ "x64" ], @@ -475,13 +476,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "cpu": [ "arm64" ], @@ -491,15 +492,14 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "cpu": [ "x64" ], @@ -510,13 +510,13 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "cpu": [ "arm64" ], @@ -526,15 +526,14 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "cpu": [ "x64" ], @@ -545,13 +544,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "cpu": [ "arm64" ], @@ -561,15 +560,14 @@ "os": [ "openharmony" ], - "peer": true, "engines": { "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "cpu": [ "x64" ], @@ -580,13 +578,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "cpu": [ "arm64" ], @@ -597,13 +595,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "cpu": [ "ia32" ], @@ -614,13 +612,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "cpu": [ "x64" ], @@ -631,7 +629,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@fastify/busboy": { @@ -1101,10 +1099,27 @@ "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", - "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.77.0.tgz", + "integrity": "sha512-E06sKWS6PiI6HRxS1wyQg22HvApt01hI7fV+T3wUk3OSbaaP4a3hYGY/MIQDmASqCiRjBdpRQYkgMkqH82cWmQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.77.0.tgz", + "integrity": "sha512-NvsKz0KZxTp9cYWPLf+FXaSZwB3oO3peAjtukpOMBgse2vhQSoIIVqeO1yR0lEo/UcdZIDL18uq+kL0LzQ0ytA==", "cpu": [ "arm64" ], @@ -1118,10 +1133,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.77.0.tgz", + "integrity": "sha512-bgjTn6nW4bQCFBvSvuHCpDD+sONvmpo4lGI4PxzMt1quBA+xYxhczk6RiCn3GZ9gY8uhaBbwhj9MdKGfu6T9DA==", "cpu": [ "arm64" ], @@ -1135,10 +1150,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.77.0.tgz", + "integrity": "sha512-aotaIttH1R6j1Rwhx0M0htgeZyGtVQqYNTVEYMN/UcgHPquGA6kmk9OyuDc3a2GKUQBC+3C3GVQCcrRPMYqAFA==", "cpu": [ "x64" ], @@ -1152,10 +1167,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", - "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.77.0.tgz", + "integrity": "sha512-nNx/wta7ksRAdYvq+l4AWjXkLxEXHALhENxjj2cYbQAIR4ybaA5L+hCbE63HOmft5czQ6ks+hb8vmEAnn7YGPg==", "cpu": [ "x64" ], @@ -1169,10 +1184,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", - "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.77.0.tgz", + "integrity": "sha512-tMLLjM7xXtzXisVCzkOTXNCy9bZVId2wteNwjohlFDR/jY6WagpEDA1c1wu4xRc20Hojaxj+V6DSR7gbKxijWA==", "cpu": [ "arm" ], @@ -1186,12 +1201,12 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", - "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.77.0.tgz", + "integrity": "sha512-MiAFDFaqR0tmHTAyo0YDcZ5hyLREdYw/RQhc2R3cbT+8O3tB+zqPM2th9TTQ+Uo3jn/embS+DO+HyX9ztCPkOQ==", "cpu": [ - "arm64" + "arm" ], "dev": true, "license": "MIT", @@ -1203,14 +1218,17 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", - "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.77.0.tgz", + "integrity": "sha512-/xqQ3B16i1T4cyt/9Mn+4CpzhUXoBXp7kVpIwzOXNFLj5JmK1bIjsbSnX296Gg8A/o7oDtKWikFgBx0SLwztkw==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1220,14 +1238,17 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", - "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.77.0.tgz", + "integrity": "sha512-LSbwuRKiNCenPDcbARqAZ5RfBy7gmj7vOvfJRLeCDU3gFtSxWbhv/+VTlaUqzUhNj1gFLHB8h7ALnxa/Az6z6g==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1237,14 +1258,17 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", - "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.77.0.tgz", + "integrity": "sha512-QWdcH31mXEUe5Nq1s0CfCpceaKjIo9uZtwDjAuL681g1axf+5x8xrg/eXWaw//4NCxYZ4V4e5Hu5tvdR+pTBlg==", "cpu": [ - "s390x" + "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1254,14 +1278,17 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", - "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.77.0.tgz", + "integrity": "sha512-GnOfYgJxbcElOiPZaDFDl406ONddwvOWk2jvAAAEjwAl4GofNoHF+/HHUIBYa6bFCArlcGPi0XjC4cU1pkgF/Q==", "cpu": [ - "x64" + "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1271,14 +1298,17 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", - "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.77.0.tgz", + "integrity": "sha512-AyEMTUCf0xY+hHF+IxqXFQIX0yQOIR8ykpY0lJNOw9xYqOzUX8dyZfRvlG0RfXwuQn2eonf/8NrMmDSZJjdqsA==", "cpu": [ - "x64" + "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1288,406 +1318,432 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", - "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.77.0.tgz", + "integrity": "sha512-sPLzEcNvxd/oyVQ5oZo92CiHkFkpBeRop13E/P3TPY+hZfXHKCOWKI70TE2RYwMKFJDc20EMjH16L7NZICtKTw==", "cpu": [ - "arm64" + "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "openharmony" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", - "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.77.0.tgz", + "integrity": "sha512-1Oh2ssH2L7lwyvkdSqaMUfsGfwU2Wfvew+obBUYjRVqhpBcUpwnsPSEr1IzVi9XqkuY10geiLsNKecqaZC34Dw==", "cpu": [ - "arm64" + "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", - "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.77.0.tgz", + "integrity": "sha512-0j/2wRgNGO+Qj/M1uu/p57h/hFTTWWcfie0ufkbabeus2s5+/QqkCflnMOwLLN5m2GsNeWp4xdl4cPa4n7QCOQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript/typescript-aix-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", - "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.77.0.tgz", + "integrity": "sha512-BJ/j54qS0usEnyDkLYURMj2iiD9h5Cyy+ppzeMSXBGRXaGRNWnj1Mw14NqWMR5E/PzdgB30OOCCzLzbRoduafw==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "aix" + "openharmony" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-darwin-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", - "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.77.0.tgz", + "integrity": "sha512-Yh8w+g2Lpx7StrvtYkoz9JJvXjB9wxgFChFNb85nrXm/wj/XTwGWS1hve9+900HL7llrntYB3YP+y32E3tRqzA==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-darwin-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", - "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.77.0.tgz", + "integrity": "sha512-zja5b7+6a7UsRFgAQSrnax5vrzliEyNPLCjfXONu/vTWswaIVZGFajJZptaeRvPE4LghtFdAzVFlexTm7MVTGA==", "cpu": [ - "x64" + "ia32" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-freebsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", - "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.77.0.tgz", + "integrity": "sha512-+teyvPDZ2RjUvo+SuCqS/UhaJl1QtdW5fWT5NJTV61V5MIuIS90Db9LixmtEGvXixyttiK62P96MSu3UlpviBw==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "freebsd" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-freebsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", - "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "freebsd" + "android" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-arm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", - "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", "cpu": [ - "arm" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", - "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-loong64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", - "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", "cpu": [ - "loong64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-mips64el": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", - "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", "cpu": [ - "mips64el" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", - "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-riscv64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", - "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", "cpu": [ - "riscv64" + "ppc64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-s390x": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", - "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", "cpu": [ "s390x" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-linux-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", - "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-netbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", - "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-netbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", - "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "netbsd" + "openharmony" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-openbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", - "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "openbsd" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-openbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", - "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ - "openbsd" + "win32" ], "engines": { - "node": ">=16.20.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@typescript/typescript-sunos-x64": { + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript/typescript-aix-ppc64": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", - "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", "cpu": [ - "x64" + "ppc64" ], "dev": true, "license": "Apache-2.0", "optional": true, "os": [ - "sunos" + "aix" ], "engines": { "node": ">=16.20.0" } }, - "node_modules/@typescript/typescript-win32-arm64": { + "node_modules/@typescript/typescript-darwin-arm64": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", - "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", "cpu": [ "arm64" ], @@ -1695,16 +1751,16 @@ "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "darwin" ], "engines": { "node": ">=16.20.0" } }, - "node_modules/@typescript/typescript-win32-x64": { + "node_modules/@typescript/typescript-darwin-x64": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", - "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", "cpu": [ "x64" ], @@ -1712,1676 +1768,1603 @@ "license": "Apache-2.0", "optional": true, "os": [ - "win32" + "darwin" ], "engines": { "node": ">=16.20.0" } }, - "node_modules/@vitest/expect": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", - "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "chai": "^6.2.2", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", - "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", - "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.1.10", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", - "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "@vitest/utils": "4.1.10", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/@vitest/spy": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", - "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", - "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/as-table": { - "version": "1.0.55", - "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", - "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "printable-characters": "^1.0.42" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12.5.0" + "node": ">=16.20.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "dependencies": { - "color-name": "~1.1.4" - }, + "os": [ + "freebsd" + ], "engines": { - "node": ">=7.0.0" + "node": ">=16.20.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", + "os": [ + "linux" + ], "engines": { - "node": ">= 0.6" + "node": ">=16.20.0" } }, - "node_modules/data-uri-to-buffer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", - "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", - "dev": true, - "license": "MIT" - }, - "node_modules/defu": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", - "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" - } - }, - "node_modules/es-module-lexer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", - "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/exit-hook": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", - "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16.20.0" } }, - "node_modules/expect-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", - "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], "dev": true, "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/exsolve": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.1.tgz", - "integrity": "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=16.20.0" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], "dev": true, - "hasInstallScript": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-source": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", - "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", - "dev": true, - "license": "Unlicense", - "dependencies": { - "data-uri-to-buffer": "^2.0.0", - "source-map": "^0.6.1" + "node": ">=16.20.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/lightningcss": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", - "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.33.0", - "lightningcss-darwin-arm64": "1.33.0", - "lightningcss-darwin-x64": "1.33.0", - "lightningcss-freebsd-x64": "1.33.0", - "lightningcss-linux-arm-gnueabihf": "1.33.0", - "lightningcss-linux-arm64-gnu": "1.33.0", - "lightningcss-linux-arm64-musl": "1.33.0", - "lightningcss-linux-x64-gnu": "1.33.0", - "lightningcss-linux-x64-musl": "1.33.0", - "lightningcss-win32-arm64-msvc": "1.33.0", - "lightningcss-win32-x64-msvc": "1.33.0" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-android-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", - "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", "cpu": [ - "arm64" + "riscv64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "linux" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", - "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", "cpu": [ - "arm64" + "s390x" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", - "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", "cpu": [ "x64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", - "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "freebsd" + "netbsd" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", - "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", "cpu": [ - "arm" + "x64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "netbsd" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", - "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", "cpu": [ "arm64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", - "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", - "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", "cpu": [ "x64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "sunos" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", - "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=16.20.0" } }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", - "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MPL-2.0", + "license": "Apache-2.0", "optional": true, "os": [ "win32" ], "engines": { - "node": ">= 12.0.0" + "node": ">=16.20.0" + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "printable-characters": "^1.0.42" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", - "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", - "cpu": [ - "x64" - ], + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=12" } }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" + "engines": { + "node": ">=18" } }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "dev": true, "license": "MIT", - "bin": { - "mime": "cli.js" + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.5.0" } }, - "node_modules/miniflare": { - "version": "3.20250718.3", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250718.3.tgz", - "integrity": "sha512-JuPrDJhwLrNLEJiNLWO7ZzJrv/Vv9kZuwMYCfv0LskQDM6Eonw4OvywO3CH/wCGjgHzha/qyjUh8JQ068TjDgQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "acorn": "8.14.0", - "acorn-walk": "8.3.2", - "exit-hook": "2.2.1", - "glob-to-regexp": "0.4.1", - "stoppable": "1.1.0", - "undici": "^5.28.5", - "workerd": "1.20250718.0", - "ws": "8.18.0", - "youch": "3.3.4", - "zod": "3.22.3" - }, - "bin": { - "miniflare": "bootstrap.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=16.13" + "node": ">=7.0.0" } }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } + "optional": true }, - "node_modules/nanoid": { - "version": "3.3.17", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", - "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/obug": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], "license": "MIT", "engines": { - "node": ">=12.20.0" + "node": ">= 0.6" } }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "node_modules/data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", "dev": true, "license": "MIT" }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", "dev": true, "license": "MIT" }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", "dev": true, "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "dev": true, - "license": "ISC" + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } }, - "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "dependencies": { - "nanoid": "^3.3.17", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "engines": { + "node": ">=6" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=12.0.0" } }, - "node_modules/printable-characters": { - "version": "1.0.42", - "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", - "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "node_modules/exsolve": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.1.tgz", + "integrity": "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==", "dev": true, - "license": "Unlicense" + "license": "MIT" }, - "node_modules/rolldown": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", - "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.143.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=12.0.0" }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.2.3", - "@rolldown/binding-darwin-arm64": "1.2.3", - "@rolldown/binding-darwin-x64": "1.2.3", - "@rolldown/binding-freebsd-x64": "1.2.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", - "@rolldown/binding-linux-arm64-gnu": "1.2.3", - "@rolldown/binding-linux-arm64-musl": "1.2.3", - "@rolldown/binding-linux-ppc64-gnu": "1.2.3", - "@rolldown/binding-linux-s390x-gnu": "1.2.3", - "@rolldown/binding-linux-x64-gnu": "1.2.3", - "@rolldown/binding-linux-x64-musl": "1.2.3", - "@rolldown/binding-openharmony-arm64": "1.2.3", - "@rolldown/binding-win32-arm64-msvc": "1.2.3", - "@rolldown/binding-win32-x64-msvc": "1.2.3" + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "node_modules/get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", "dev": true, - "license": "MIT", + "license": "Unlicense", "dependencies": { - "rollup-plugin-inject": "^3.0.0" + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" } }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "dev": true, "license": "MIT", + "optional": true + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", "dependencies": { - "estree-walker": "^0.6.1" + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", + "license": "MPL-2.0", "optional": true, - "bin": { - "semver": "bin/semver.js" - }, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", + "license": "MPL-2.0", "optional": true, - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - }, + "os": [ + "darwin" + ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://opencollective.com/libvips" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC" + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, - "dependencies": { - "is-arrayish": "^0.3.1" + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true, - "license": "MIT" - }, - "node_modules/sql.js": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz", - "integrity": "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/stacktracey": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.2.0.tgz", - "integrity": "sha512-ETyQEz+CzXiLjEbyJqpbp+/T79RQD/6wqFucRBIlVNZfYq2Ay7wbretD4cxpbymZlaPWx58aIhPEY1Cr8DlVvg==", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Unlicense", - "dependencies": { - "as-table": "^1.0.36", - "get-source": "^2.0.12" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/std-env": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", - "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", - "dev": true, - "license": "MIT" - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4", - "npm": ">=6" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", - "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.0.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/tinyrainbow": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", - "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.0.0" + "dependencies": { + "sourcemap-codec": "^1.4.8" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, - "node_modules/typescript": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", - "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "bin": { - "tsc": "bin/tsc" + "mime": "cli.js" }, "engines": { - "node": ">=16.20.0" - }, - "optionalDependencies": { - "@typescript/typescript-aix-ppc64": "7.0.2", - "@typescript/typescript-darwin-arm64": "7.0.2", - "@typescript/typescript-darwin-x64": "7.0.2", - "@typescript/typescript-freebsd-arm64": "7.0.2", - "@typescript/typescript-freebsd-x64": "7.0.2", - "@typescript/typescript-linux-arm": "7.0.2", - "@typescript/typescript-linux-arm64": "7.0.2", - "@typescript/typescript-linux-loong64": "7.0.2", - "@typescript/typescript-linux-mips64el": "7.0.2", - "@typescript/typescript-linux-ppc64": "7.0.2", - "@typescript/typescript-linux-riscv64": "7.0.2", - "@typescript/typescript-linux-s390x": "7.0.2", - "@typescript/typescript-linux-x64": "7.0.2", - "@typescript/typescript-netbsd-arm64": "7.0.2", - "@typescript/typescript-netbsd-x64": "7.0.2", - "@typescript/typescript-openbsd-arm64": "7.0.2", - "@typescript/typescript-openbsd-x64": "7.0.2", - "@typescript/typescript-sunos-x64": "7.0.2", - "@typescript/typescript-win32-arm64": "7.0.2", - "@typescript/typescript-win32-x64": "7.0.2" + "node": ">=10.0.0" + } + }, + "node_modules/miniflare": { + "version": "3.20250718.3", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250718.3.tgz", + "integrity": "sha512-JuPrDJhwLrNLEJiNLWO7ZzJrv/Vv9kZuwMYCfv0LskQDM6Eonw4OvywO3CH/wCGjgHzha/qyjUh8JQ068TjDgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "stoppable": "1.1.0", + "undici": "^5.28.5", + "workerd": "1.20250718.0", + "ws": "8.18.0", + "youch": "3.3.4", + "zod": "3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=16.13" } }, - "node_modules/ufo": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", - "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } }, - "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "node_modules/nanoid": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=14.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/unenv": { - "version": "2.0.0-rc.14", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.14.tgz", - "integrity": "sha512-od496pShMen7nOy5VmVJCnq8rptd45vh6Nx/r2iPbrba6pa6p+tS2ywuIHRZ/OBvSbQZB0kWvpO9XBNVFXHD3Q==", + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "exsolve": "^1.0.1", - "ohash": "^2.0.10", - "pathe": "^2.0.3", - "ufo": "^1.5.4" + "engines": { + "node": ">=12.20.0" } }, - "node_modules/vitest": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", - "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/oxlint": { + "version": "1.77.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.77.0.tgz", + "integrity": "sha512-qnGh8XJHaQ0dprrDXNQZgS0FgjI6v+V3+X8DwmaV++5Aamy6jGKfDdQ1TUvhUxtmKFAbEf4/WeO5QZX+5WSngg==", "dev": true, "license": "MIT", - "dependencies": { - "@vitest/expect": "4.1.10", - "@vitest/mocker": "4.1.10", - "@vitest/pretty-format": "4.1.10", - "@vitest/runner": "4.1.10", - "@vitest/snapshot": "4.1.10", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "es-module-lexer": "^2.0.0", - "expect-type": "^1.3.0", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^4.0.0-rc.1", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.1.0", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", - "why-is-node-running": "^2.3.0" - }, "bin": { - "vitest": "vitest.mjs" + "oxlint": "bin/oxlint" }, "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.77.0", + "@oxlint/binding-android-arm64": "1.77.0", + "@oxlint/binding-darwin-arm64": "1.77.0", + "@oxlint/binding-darwin-x64": "1.77.0", + "@oxlint/binding-freebsd-x64": "1.77.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.77.0", + "@oxlint/binding-linux-arm-musleabihf": "1.77.0", + "@oxlint/binding-linux-arm64-gnu": "1.77.0", + "@oxlint/binding-linux-arm64-musl": "1.77.0", + "@oxlint/binding-linux-ppc64-gnu": "1.77.0", + "@oxlint/binding-linux-riscv64-gnu": "1.77.0", + "@oxlint/binding-linux-riscv64-musl": "1.77.0", + "@oxlint/binding-linux-s390x-gnu": "1.77.0", + "@oxlint/binding-linux-x64-gnu": "1.77.0", + "@oxlint/binding-linux-x64-musl": "1.77.0", + "@oxlint/binding-openharmony-arm64": "1.77.0", + "@oxlint/binding-win32-arm64-msvc": "1.77.0", + "@oxlint/binding-win32-ia32-msvc": "1.77.0", + "@oxlint/binding-win32-x64-msvc": "1.77.0" }, "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.10", - "@vitest/browser-preview": "4.1.10", - "@vitest/browser-webdriverio": "4.1.10", - "@vitest/coverage-istanbul": "4.1.10", - "@vitest/coverage-v8": "4.1.10", - "@vitest/ui": "4.1.10", - "happy-dom": "*", - "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + "oxlint-tsgolint": ">=7.0.2001", + "vite-plus": "*" }, "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/coverage-istanbul": { + "oxlint-tsgolint": { "optional": true }, - "@vitest/coverage-v8": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { + "vite-plus": { "optional": true - }, - "vite": { - "optional": false } } }, - "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", - "cpu": [ - "ppc64" - ], + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "peer": true, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vitest/node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", - "cpu": [ - "arm" + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/rolldown": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, + "dependencies": { + "@oxc-project/types": "=0.143.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" } }, - "node_modules/vitest/node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", - "cpu": [ - "arm64" - ], + "node_modules/rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" } }, - "node_modules/vitest/node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", - "cpu": [ - "x64" - ], + "node_modules/rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "rollup-plugin-inject": "^3.0.0" } }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", - "cpu": [ - "arm64" - ], + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "estree-walker": "^0.6.1" } }, - "node_modules/vitest/node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", - "cpu": [ - "x64" - ], + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "license": "MIT", + "license": "ISC", "optional": true, - "os": [ - "darwin" - ], - "peer": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", - "cpu": [ - "arm64" - ], + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", "optional": true, - "os": [ - "freebsd" - ], - "peer": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" } }, - "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", - "cpu": [ - "x64" - ], + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "ISC" }, - "node_modules/vitest/node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", - "cpu": [ - "arm" - ], + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "is-arrayish": "^0.3.1" } }, - "node_modules/vitest/node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", - "cpu": [ - "arm64" - ], + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", - "cpu": [ - "ia32" - ], + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", - "cpu": [ - "loong64" - ], + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", - "cpu": [ - "mips64el" - ], + "node_modules/sql.js": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz", + "integrity": "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", - "cpu": [ - "ppc64" - ], + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", - "cpu": [ - "riscv64" - ], + "node_modules/stacktracey": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.2.0.tgz", + "integrity": "sha512-ETyQEz+CzXiLjEbyJqpbp+/T79RQD/6wqFucRBIlVNZfYq2Ay7wbretD4cxpbymZlaPWx58aIhPEY1Cr8DlVvg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" + "license": "Unlicense", + "dependencies": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" } }, - "node_modules/vitest/node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", - "cpu": [ - "s390x" - ], + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, "engines": { - "node": ">=18" + "node": ">=4", + "npm": ">=6" } }, - "node_modules/vitest/node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", - "cpu": [ - "x64" - ], + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", - "cpu": [ - "x64" - ], + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", - "cpu": [ - "x64" - ], + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, "engines": { - "node": ">=18" + "node": ">=14.0.0" } }, - "node_modules/vitest/node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", - "cpu": [ - "x64" - ], + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "peer": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc" + }, "engines": { - "node": ">=18" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, - "node_modules/vitest/node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", - "cpu": [ - "arm64" - ], + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=14.0" } }, - "node_modules/vitest/node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", - "cpu": [ - "ia32" - ], + "node_modules/unenv": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.14.tgz", + "integrity": "sha512-od496pShMen7nOy5VmVJCnq8rptd45vh6Nx/r2iPbrba6pa6p+tS2ywuIHRZ/OBvSbQZB0kWvpO9XBNVFXHD3Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "defu": "^6.1.4", + "exsolve": "^1.0.1", + "ohash": "^2.0.10", + "pathe": "^2.0.3", + "ufo": "^1.5.4" } }, - "node_modules/vitest/node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", - "cpu": [ - "x64" - ], + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, "engines": { - "node": ">=18" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "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 + } } }, "node_modules/vitest/node_modules/@vitest/mocker": { @@ -3411,50 +3394,6 @@ } } }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" - } - }, "node_modules/vitest/node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", diff --git a/package.json b/package.json index 3315ed4..6d26f86 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dev": "wrangler dev", "deploy": "wrangler deploy", "typecheck": "tsc --noEmit", + "lint": "oxlint src tests packages/protocol/src", "test": "vitest run", "test:watch": "vitest", "test:unit": "vitest run tests/unit", @@ -43,7 +44,7 @@ "test:protocol": "vitest run tests/opendating", "db:migrate:local": "wrangler d1 execute opendating-relay --local --file=migrations/run-all.sql", "db:migrate:remote": "wrangler d1 execute opendating-relay --remote --file=migrations/run-all.sql", - "ci": "npm run typecheck && npm run build && npm test", + "ci": "npm run typecheck && npm run lint && npm run build && npm test", "opendating:test": "vitest run --dir tests/opendating", "opendating:test:conformance": "vitest run --dir tests/opendating/conformance", "opendating:keys:generate": "npx tsx scripts/opendating-keys-generate.ts", @@ -56,7 +57,8 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20260101.0", - "esbuild": "^0.19.12", + "esbuild": "0.28.0", + "oxlint": "1.77.0", "sql.js": "^1.14.1", "typescript": "^7.0.2", "vitest": "^4.1.10", diff --git a/packages/protocol/README.md b/packages/protocol/README.md index ff609fb..fee5bf5 100644 --- a/packages/protocol/README.md +++ b/packages/protocol/README.md @@ -2,6 +2,8 @@ OpenDating protocol — types, constants, validators, crypto helpers. +Current package release: `0.1.1`. Protocol wire version remains experimental `0.1`. + **Zero Cloudflare/Worker/D1/Durable Object dependencies.** ## Install @@ -22,6 +24,7 @@ import { nip44Encrypt, nip44Decrypt, OD_ERROR_CODES, + getRequestRoute, } from 'opendating-protocol'; // Generate a user keypair @@ -60,6 +63,7 @@ import { - `version.ts` — Version compatibility + negotiation - `envelope.ts` — Envelope construction, validation, freshness - `message-types.ts` — Message type registry with payload validators +- `routing.ts` — Canonical request role and expected-result registry - `errors.ts` — Standard error codes + messages - `capabilities.ts` — Capability reporting + NIP-11 advertisement - `validation.ts` — Runtime request validation diff --git a/packages/protocol/dist/index.d.ts b/packages/protocol/dist/index.d.ts index a0fa0ea..de46a45 100644 --- a/packages/protocol/dist/index.d.ts +++ b/packages/protocol/dist/index.d.ts @@ -4,7 +4,7 @@ * OpenDating protocol — types, constants, validators, crypto helpers. * Zero Cloudflare/Worker/D1/Durable Object dependencies. * - * @version 0.1.0 + * @version 0.1.1 */ export { OPENDATING_PROTOCOL, OPENDATING_VERSION, SUPPORTED_VERSIONS, OD_KIND_RUMOR, OD_KIND_GIFT_WRAP, OD_FEATURES, } from './protocol/constants.js'; export type { OpenDatingServiceRole, OpenDatingMessageType, OpenDatingFeature } from './protocol/constants.js'; @@ -16,6 +16,8 @@ export type { SystemPingPayload, SystemPongPayload, SystemCapabilitiesPayload, S export { OD_ERROR_CODES, OD_ERROR_MESSAGES } from './protocol/errors.js'; export type { ODErrorCode } from './protocol/errors.js'; export { buildCapabilities, buildNip11Advertisement } from './protocol/capabilities.js'; +export { REQUEST_ROUTES, getRequestRoute } from './protocol/routing.js'; +export type { OpenDatingRequestType, RequestRoute, } from './protocol/routing.js'; export { validateODRequest } from './protocol/validation.js'; export type { ODValidationResult } from './protocol/validation.js'; export { generateKeypair, getConversationKey, nip44Encrypt, nip44Decrypt, getEventHash, signEvent, bytesToHex, hexToBytes, bytesToBase64, base64ToBytes, } from './crypto/encryption.js'; diff --git a/packages/protocol/dist/index.d.ts.map b/packages/protocol/dist/index.d.ts.map index 3e8453c..08bcab9 100644 --- a/packages/protocol/dist/index.d.ts.map +++ b/packages/protocol/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE/G,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,+BAA+B,EAC/B,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE/G,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,+BAA+B,EAC/B,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxE,YAAY,EACV,qBAAqB,EACrB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC"} \ No newline at end of file diff --git a/packages/protocol/dist/index.js b/packages/protocol/dist/index.js index c457860..c4f17cc 100644 --- a/packages/protocol/dist/index.js +++ b/packages/protocol/dist/index.js @@ -4,7 +4,7 @@ * OpenDating protocol — types, constants, validators, crypto helpers. * Zero Cloudflare/Worker/D1/Durable Object dependencies. * - * @version 0.1.0 + * @version 0.1.1 */ export { OPENDATING_PROTOCOL, OPENDATING_VERSION, SUPPORTED_VERSIONS, OD_KIND_RUMOR, OD_KIND_GIFT_WRAP, OD_FEATURES, } from './protocol/constants.js'; export { isSupportedVersion, isOpenDatingProtocol, negotiateVersion, getServerVersion, } from './protocol/version.js'; @@ -12,6 +12,7 @@ export { createEnvelope, createErrorEnvelope, validateEnvelope, checkRequestFres export { MESSAGE_VALIDATORS, isKnownMessageType, getPayloadValidator, } from './protocol/message-types.js'; export { OD_ERROR_CODES, OD_ERROR_MESSAGES } from './protocol/errors.js'; export { buildCapabilities, buildNip11Advertisement } from './protocol/capabilities.js'; +export { REQUEST_ROUTES, getRequestRoute } from './protocol/routing.js'; export { validateODRequest } from './protocol/validation.js'; export { generateKeypair, getConversationKey, nip44Encrypt, nip44Decrypt, getEventHash, signEvent, bytesToHex, hexToBytes, bytesToBase64, base64ToBytes, } from './crypto/encryption.js'; export { buildGiftWrap, buildServiceResponseGiftWrap } from './crypto/gift-wrap.js'; diff --git a/packages/protocol/dist/index.js.map b/packages/protocol/dist/index.js.map index 70de076..79b3d41 100644 --- a/packages/protocol/dist/index.js.map +++ b/packages/protocol/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAShC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AASrC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGpF,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAShC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AASrC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAMxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGpF,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC"} \ No newline at end of file diff --git a/packages/protocol/dist/protocol/constants.d.ts b/packages/protocol/dist/protocol/constants.d.ts index c5ce113..1beda5c 100644 --- a/packages/protocol/dist/protocol/constants.d.ts +++ b/packages/protocol/dist/protocol/constants.d.ts @@ -18,9 +18,9 @@ export declare const OD_KIND_GIFT_WRAP = 1059; export declare const OD_KIND_AUTH = 22242; /** * OpenDating service roles. - * Only "system" is active in V0.1. Other roles are type-safe placeholders. + * A relay advertises only the roles it actually operates. */ -export type OpenDatingServiceRole = 'system' | 'profile' | 'discovery' | 'matcher' | 'dm_policy' | 'moderation' | 'verification' | 'media'; +export type OpenDatingServiceRole = 'system' | 'profile' | 'discovery' | 'matcher' | 'dm_policy' | 'moderation' | 'verification' | 'media' | 'deletion'; export declare const ALL_SERVICE_ROLES: readonly OpenDatingServiceRole[]; /** Known OpenDating message types (system service only for V0.1) */ export declare const OD_MESSAGE_TYPES: { diff --git a/packages/protocol/dist/protocol/constants.d.ts.map b/packages/protocol/dist/protocol/constants.d.ts.map index c8e0f12..93ba272 100644 --- a/packages/protocol/dist/protocol/constants.d.ts.map +++ b/packages/protocol/dist/protocol/constants.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,EAAG,YAAqB,CAAC;AAEzD,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,EAAG,KAAc,CAAC;AAEjD,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,kBAAmB,CAAC;AAMnD,sDAAsD;AACtD,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,2CAA2C;AAC3C,eAAO,MAAM,YAAY,QAAQ,CAAC;AAMlC;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,SAAS,GACT,WAAW,GACX,SAAS,GACT,WAAW,GACX,YAAY,GACZ,cAAc,GACd,OAAO,CAAC;AAEZ,eAAO,MAAM,iBAAiB,EAAE,SAAS,qBAAqB,EAGpD,CAAC;AAMX,oEAAoE;AACpE,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,OAAO,gBAAgB,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAM3F,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,QAAY,CAAC;AAE9C,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,kEAAkE;AAClE,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,yDAAyD;AACzD,eAAO,MAAM,4BAA4B,QAAe,CAAC;AAMzD,oEAAoE;AACpE,eAAO,MAAM,WAAW,4EAId,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,EAAG,YAAqB,CAAC;AAEzD,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,EAAG,KAAc,CAAC;AAEjD,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,kBAAmB,CAAC;AAMnD,sDAAsD;AACtD,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,2CAA2C;AAC3C,eAAO,MAAM,YAAY,QAAQ,CAAC;AAMlC;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,SAAS,GACT,WAAW,GACX,SAAS,GACT,WAAW,GACX,YAAY,GACZ,cAAc,GACd,OAAO,GACP,UAAU,CAAC;AAEf,eAAO,MAAM,iBAAiB,EAAE,SAAS,qBAAqB,EAGpD,CAAC;AAMX,oEAAoE;AACpE,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,OAAO,gBAAgB,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAM3F,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,QAAY,CAAC;AAE9C,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,kEAAkE;AAClE,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,yDAAyD;AACzD,eAAO,MAAM,4BAA4B,QAAe,CAAC;AAMzD,oEAAoE;AACpE,eAAO,MAAM,WAAW,4EAId,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/protocol/dist/protocol/constants.js b/packages/protocol/dist/protocol/constants.js index a2a3bb0..996b868 100644 --- a/packages/protocol/dist/protocol/constants.js +++ b/packages/protocol/dist/protocol/constants.js @@ -21,7 +21,7 @@ export const OD_KIND_GIFT_WRAP = 1059; export const OD_KIND_AUTH = 22242; export const ALL_SERVICE_ROLES = [ 'system', 'profile', 'discovery', 'matcher', - 'dm_policy', 'moderation', 'verification', 'media', + 'dm_policy', 'moderation', 'verification', 'media', 'deletion', ]; // --------------------------------------------------------------------------- // Message types diff --git a/packages/protocol/dist/protocol/constants.js.map b/packages/protocol/dist/protocol/constants.js.map index 8bb728f..5d7b3b6 100644 --- a/packages/protocol/dist/protocol/constants.js.map +++ b/packages/protocol/dist/protocol/constants.js.map @@ -1 +1 @@ -{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAqB,CAAC;AAEzD,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAc,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAU,CAAC;AAEnD,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,sDAAsD;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEhC,mDAAmD;AACnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAoBlC,MAAM,CAAC,MAAM,iBAAiB,GAAqC;IACjE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS;IAC3C,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO;CAC1C,CAAC;AAEX,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,aAAa,EAAE,aAAa;IAC5B,aAAa,EAAE,aAAa;IAC5B,qBAAqB,EAAE,qBAAqB;IAC5C,4BAA4B,EAAE,4BAA4B;IAC1D,cAAc,EAAE,cAAc;CACtB,CAAC;AAIX,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEvD,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,CAAC;AAE7C,kEAAkE;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,yDAAyD;AACzD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEzD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,0BAA0B;IAC1B,gBAAgB;IAChB,iBAAiB;CACT,CAAC"} \ No newline at end of file +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAqB,CAAC;AAEzD,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAc,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAU,CAAC;AAEnD,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,sDAAsD;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEhC,mDAAmD;AACnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAqBlC,MAAM,CAAC,MAAM,iBAAiB,GAAqC;IACjE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS;IAC3C,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU;CACtD,CAAC;AAEX,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,aAAa,EAAE,aAAa;IAC5B,aAAa,EAAE,aAAa;IAC5B,qBAAqB,EAAE,qBAAqB;IAC5C,4BAA4B,EAAE,4BAA4B;IAC1D,cAAc,EAAE,cAAc;CACtB,CAAC;AAIX,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEvD,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,CAAC;AAE7C,kEAAkE;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,yDAAyD;AACzD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEzD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,0BAA0B;IAC1B,gBAAgB;IAChB,iBAAiB;CACT,CAAC"} \ No newline at end of file diff --git a/packages/protocol/dist/protocol/routing.d.ts b/packages/protocol/dist/protocol/routing.d.ts new file mode 100644 index 0000000..edba9d0 --- /dev/null +++ b/packages/protocol/dist/protocol/routing.d.ts @@ -0,0 +1,108 @@ +/** + * Canonical request routing metadata for protocol 0.1. + * + * Clients use this registry to select the advertised service identity and to + * reject a response whose type does not match the request it claims to answer. + */ +import type { OpenDatingServiceRole } from './constants.js'; +export interface RequestRoute { + role: OpenDatingServiceRole; + resultType: string; +} +export declare const REQUEST_ROUTES: { + readonly 'system.ping': { + readonly role: "system"; + readonly resultType: "system.pong"; + }; + readonly 'system.capabilities': { + readonly role: "system"; + readonly resultType: "system.capabilities.result"; + }; + readonly 'profile.create': { + readonly role: "profile"; + readonly resultType: "profile.create.result"; + }; + readonly 'profile.update': { + readonly role: "profile"; + readonly resultType: "profile.update.result"; + }; + readonly 'profile.get': { + readonly role: "profile"; + readonly resultType: "profile.get.result"; + }; + readonly 'profile.pause': { + readonly role: "profile"; + readonly resultType: "profile.pause.result"; + }; + readonly 'profile.resume': { + readonly role: "profile"; + readonly resultType: "profile.resume.result"; + }; + readonly 'profile.delete': { + readonly role: "profile"; + readonly resultType: "profile.delete.result"; + }; + readonly 'visibility.update': { + readonly role: "profile"; + readonly resultType: "visibility.update.result"; + }; + readonly 'discovery.update_location': { + readonly role: "discovery"; + readonly resultType: "discovery.update_location.result"; + }; + readonly 'discovery.get_candidates': { + readonly role: "discovery"; + readonly resultType: "discovery.get_candidates.result"; + }; + readonly 'discovery.update_preferences': { + readonly role: "discovery"; + readonly resultType: "discovery.update_preferences.result"; + }; + readonly 'intent.like': { + readonly role: "matcher"; + readonly resultType: "intent.like.result"; + }; + readonly 'intent.revoke': { + readonly role: "matcher"; + readonly resultType: "intent.revoke.result"; + }; + readonly 'match.list': { + readonly role: "matcher"; + readonly resultType: "match.list.result"; + }; + readonly 'block.create': { + readonly role: "dm_policy"; + readonly resultType: "block.create.result"; + }; + readonly 'block.remove': { + readonly role: "dm_policy"; + readonly resultType: "block.remove.result"; + }; + readonly 'block.list': { + readonly role: "dm_policy"; + readonly resultType: "block.list.result"; + }; + readonly 'unmatch.create': { + readonly role: "dm_policy"; + readonly resultType: "unmatch.create.result"; + }; + readonly 'report.create': { + readonly role: "moderation"; + readonly resultType: "report.create.result"; + }; + readonly 'moderation.action': { + readonly role: "moderation"; + readonly resultType: "moderation.action.result"; + }; + readonly 'verification.list': { + readonly role: "verification"; + readonly resultType: "verification.list.result"; + }; + readonly 'account.delete': { + readonly role: "deletion"; + readonly resultType: "account.delete.result"; + }; +}; +export type OpenDatingRequestType = keyof typeof REQUEST_ROUTES; +export declare function getRequestRoute(type: string): RequestRoute | undefined; +//# sourceMappingURL=routing.d.ts.map \ No newline at end of file diff --git a/packages/protocol/dist/protocol/routing.d.ts.map b/packages/protocol/dist/protocol/routing.d.ts.map new file mode 100644 index 0000000..07d74d0 --- /dev/null +++ b/packages/protocol/dist/protocol/routing.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/protocol/routing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCsB,CAAC;AAElD,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,cAAc,CAAC;AAEhE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEtE"} \ No newline at end of file diff --git a/packages/protocol/dist/protocol/routing.js b/packages/protocol/dist/protocol/routing.js new file mode 100644 index 0000000..e65dff3 --- /dev/null +++ b/packages/protocol/dist/protocol/routing.js @@ -0,0 +1,44 @@ +export const REQUEST_ROUTES = { + 'system.ping': { role: 'system', resultType: 'system.pong' }, + 'system.capabilities': { role: 'system', resultType: 'system.capabilities.result' }, + 'profile.create': { role: 'profile', resultType: 'profile.create.result' }, + 'profile.update': { role: 'profile', resultType: 'profile.update.result' }, + 'profile.get': { role: 'profile', resultType: 'profile.get.result' }, + 'profile.pause': { role: 'profile', resultType: 'profile.pause.result' }, + 'profile.resume': { role: 'profile', resultType: 'profile.resume.result' }, + 'profile.delete': { role: 'profile', resultType: 'profile.delete.result' }, + 'visibility.update': { role: 'profile', resultType: 'visibility.update.result' }, + 'discovery.update_location': { + role: 'discovery', + resultType: 'discovery.update_location.result', + }, + 'discovery.get_candidates': { + role: 'discovery', + resultType: 'discovery.get_candidates.result', + }, + 'discovery.update_preferences': { + role: 'discovery', + resultType: 'discovery.update_preferences.result', + }, + 'intent.like': { role: 'matcher', resultType: 'intent.like.result' }, + 'intent.revoke': { role: 'matcher', resultType: 'intent.revoke.result' }, + 'match.list': { role: 'matcher', resultType: 'match.list.result' }, + 'block.create': { role: 'dm_policy', resultType: 'block.create.result' }, + 'block.remove': { role: 'dm_policy', resultType: 'block.remove.result' }, + 'block.list': { role: 'dm_policy', resultType: 'block.list.result' }, + 'unmatch.create': { role: 'dm_policy', resultType: 'unmatch.create.result' }, + 'report.create': { role: 'moderation', resultType: 'report.create.result' }, + 'moderation.action': { + role: 'moderation', + resultType: 'moderation.action.result', + }, + 'verification.list': { + role: 'verification', + resultType: 'verification.list.result', + }, + 'account.delete': { role: 'deletion', resultType: 'account.delete.result' }, +}; +export function getRequestRoute(type) { + return REQUEST_ROUTES[type]; +} +//# sourceMappingURL=routing.js.map \ No newline at end of file diff --git a/packages/protocol/dist/protocol/routing.js.map b/packages/protocol/dist/protocol/routing.js.map new file mode 100644 index 0000000..7818a49 --- /dev/null +++ b/packages/protocol/dist/protocol/routing.js.map @@ -0,0 +1 @@ +{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/protocol/routing.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE;IAC5D,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,4BAA4B,EAAE;IACnF,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,uBAAuB,EAAE;IAC1E,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,uBAAuB,EAAE;IAC1E,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE;IACpE,eAAe,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,sBAAsB,EAAE;IACxE,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,uBAAuB,EAAE;IAC1E,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,uBAAuB,EAAE;IAC1E,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,0BAA0B,EAAE;IAChF,2BAA2B,EAAE;QAC3B,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,kCAAkC;KAC/C;IACD,0BAA0B,EAAE;QAC1B,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,iCAAiC;KAC9C;IACD,8BAA8B,EAAE;QAC9B,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,qCAAqC;KAClD;IACD,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE;IACpE,eAAe,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,sBAAsB,EAAE;IACxE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE;IAClE,cAAc,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,qBAAqB,EAAE;IACxE,cAAc,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,qBAAqB,EAAE;IACxE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,mBAAmB,EAAE;IACpE,gBAAgB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,uBAAuB,EAAE;IAC5E,eAAe,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE;IAC3E,mBAAmB,EAAE;QACnB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,0BAA0B;KACvC;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,cAAc;QACpB,UAAU,EAAE,0BAA0B;KACvC;IACD,gBAAgB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,uBAAuB,EAAE;CAC5B,CAAC;AAIlD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,cAAc,CAAC,IAA6B,CAAC,CAAC;AACvD,CAAC"} \ No newline at end of file diff --git a/packages/protocol/package-lock.json b/packages/protocol/package-lock.json index db63f3f..50ec61b 100644 --- a/packages/protocol/package-lock.json +++ b/packages/protocol/package-lock.json @@ -1,12 +1,12 @@ { - "name": "@opendating/protocol", - "version": "0.1.0", + "name": "opendating-protocol", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@opendating/protocol", - "version": "0.1.0", + "name": "opendating-protocol", + "version": "0.1.1", "license": "MIT", "dependencies": { "@noble/ciphers": "^2.2.0", diff --git a/packages/protocol/package.json b/packages/protocol/package.json index ee3c16e..6584cf8 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -1,6 +1,6 @@ { "name": "opendating-protocol", - "version": "0.1.0", + "version": "0.1.1", "description": "OpenDating protocol — types, constants, validators, crypto helpers. Zero Cloudflare/Worker/D1 dependencies.", "type": "module", "main": "./dist/index.js", diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts index a6c237c..0a0fa3e 100644 --- a/packages/protocol/src/index.ts +++ b/packages/protocol/src/index.ts @@ -4,7 +4,7 @@ * OpenDating protocol — types, constants, validators, crypto helpers. * Zero Cloudflare/Worker/D1/Durable Object dependencies. * - * @version 0.1.0 + * @version 0.1.1 */ export { OPENDATING_PROTOCOL, @@ -55,6 +55,12 @@ export type { ODErrorCode } from './protocol/errors.js'; export { buildCapabilities, buildNip11Advertisement } from './protocol/capabilities.js'; +export { REQUEST_ROUTES, getRequestRoute } from './protocol/routing.js'; +export type { + OpenDatingRequestType, + RequestRoute, +} from './protocol/routing.js'; + export { validateODRequest } from './protocol/validation.js'; export type { ODValidationResult } from './protocol/validation.js'; diff --git a/packages/protocol/src/protocol/constants.ts b/packages/protocol/src/protocol/constants.ts index 3a7cf43..f755290 100644 --- a/packages/protocol/src/protocol/constants.ts +++ b/packages/protocol/src/protocol/constants.ts @@ -33,7 +33,7 @@ export const OD_KIND_AUTH = 22242; /** * OpenDating service roles. - * Only "system" is active in V0.1. Other roles are type-safe placeholders. + * A relay advertises only the roles it actually operates. */ export type OpenDatingServiceRole = | 'system' @@ -43,11 +43,12 @@ export type OpenDatingServiceRole = | 'dm_policy' | 'moderation' | 'verification' - | 'media'; + | 'media' + | 'deletion'; export const ALL_SERVICE_ROLES: readonly OpenDatingServiceRole[] = [ 'system', 'profile', 'discovery', 'matcher', - 'dm_policy', 'moderation', 'verification', 'media', + 'dm_policy', 'moderation', 'verification', 'media', 'deletion', ] as const; // --------------------------------------------------------------------------- diff --git a/packages/protocol/src/protocol/routing.ts b/packages/protocol/src/protocol/routing.ts new file mode 100644 index 0000000..116dd29 --- /dev/null +++ b/packages/protocol/src/protocol/routing.ts @@ -0,0 +1,59 @@ +/** + * Canonical request routing metadata for protocol 0.1. + * + * Clients use this registry to select the advertised service identity and to + * reject a response whose type does not match the request it claims to answer. + */ +import type { OpenDatingServiceRole } from './constants.js'; + +export interface RequestRoute { + role: OpenDatingServiceRole; + resultType: string; +} + +export const REQUEST_ROUTES = { + 'system.ping': { role: 'system', resultType: 'system.pong' }, + 'system.capabilities': { role: 'system', resultType: 'system.capabilities.result' }, + 'profile.create': { role: 'profile', resultType: 'profile.create.result' }, + 'profile.update': { role: 'profile', resultType: 'profile.update.result' }, + 'profile.get': { role: 'profile', resultType: 'profile.get.result' }, + 'profile.pause': { role: 'profile', resultType: 'profile.pause.result' }, + 'profile.resume': { role: 'profile', resultType: 'profile.resume.result' }, + 'profile.delete': { role: 'profile', resultType: 'profile.delete.result' }, + 'visibility.update': { role: 'profile', resultType: 'visibility.update.result' }, + 'discovery.update_location': { + role: 'discovery', + resultType: 'discovery.update_location.result', + }, + 'discovery.get_candidates': { + role: 'discovery', + resultType: 'discovery.get_candidates.result', + }, + 'discovery.update_preferences': { + role: 'discovery', + resultType: 'discovery.update_preferences.result', + }, + 'intent.like': { role: 'matcher', resultType: 'intent.like.result' }, + 'intent.revoke': { role: 'matcher', resultType: 'intent.revoke.result' }, + 'match.list': { role: 'matcher', resultType: 'match.list.result' }, + 'block.create': { role: 'dm_policy', resultType: 'block.create.result' }, + 'block.remove': { role: 'dm_policy', resultType: 'block.remove.result' }, + 'block.list': { role: 'dm_policy', resultType: 'block.list.result' }, + 'unmatch.create': { role: 'dm_policy', resultType: 'unmatch.create.result' }, + 'report.create': { role: 'moderation', resultType: 'report.create.result' }, + 'moderation.action': { + role: 'moderation', + resultType: 'moderation.action.result', + }, + 'verification.list': { + role: 'verification', + resultType: 'verification.list.result', + }, + 'account.delete': { role: 'deletion', resultType: 'account.delete.result' }, +} as const satisfies Record; + +export type OpenDatingRequestType = keyof typeof REQUEST_ROUTES; + +export function getRequestRoute(type: string): RequestRoute | undefined { + return REQUEST_ROUTES[type as OpenDatingRequestType]; +} diff --git a/src/protocols/opendating/identities/loader.ts b/src/protocols/opendating/identities/loader.ts index c647138..c6c2332 100644 --- a/src/protocols/opendating/identities/loader.ts +++ b/src/protocols/opendating/identities/loader.ts @@ -134,8 +134,9 @@ function getSupportedTypesForRole(role: string): string[] { case 'profile': return ['profile.create', 'profile.update', 'profile.get', 'profile.pause', 'profile.resume', 'profile.delete']; case 'discovery': return ['discovery.update_location', 'discovery.get_candidates', 'discovery.update_preferences']; case 'matcher': return ['intent.like', 'intent.revoke', 'match.list']; - case 'dm_policy': return ['block.create', 'block.list', 'unmatch.create']; + case 'dm_policy': return ['block.create', 'block.remove', 'block.list', 'unmatch.create']; case 'moderation': return ['report.create', 'moderation.action']; + case 'deletion': return ['account.delete']; default: return []; } } diff --git a/src/protocols/opendating/protocol/constants.ts b/src/protocols/opendating/protocol/constants.ts index 3a7cf43..f755290 100644 --- a/src/protocols/opendating/protocol/constants.ts +++ b/src/protocols/opendating/protocol/constants.ts @@ -33,7 +33,7 @@ export const OD_KIND_AUTH = 22242; /** * OpenDating service roles. - * Only "system" is active in V0.1. Other roles are type-safe placeholders. + * A relay advertises only the roles it actually operates. */ export type OpenDatingServiceRole = | 'system' @@ -43,11 +43,12 @@ export type OpenDatingServiceRole = | 'dm_policy' | 'moderation' | 'verification' - | 'media'; + | 'media' + | 'deletion'; export const ALL_SERVICE_ROLES: readonly OpenDatingServiceRole[] = [ 'system', 'profile', 'discovery', 'matcher', - 'dm_policy', 'moderation', 'verification', 'media', + 'dm_policy', 'moderation', 'verification', 'media', 'deletion', ] as const; // --------------------------------------------------------------------------- diff --git a/src/protocols/opendating/protocol/routing.ts b/src/protocols/opendating/protocol/routing.ts new file mode 100644 index 0000000..a3806a0 --- /dev/null +++ b/src/protocols/opendating/protocol/routing.ts @@ -0,0 +1,59 @@ +/** + * Canonical request routing metadata for protocol 0.1. + * + * Keep this runtime copy byte-for-byte aligned with the published package + * until the relay consumes opendating-protocol directly. + */ +import type { OpenDatingServiceRole } from './constants.js'; + +export interface RequestRoute { + role: OpenDatingServiceRole; + resultType: string; +} + +export const REQUEST_ROUTES = { + 'system.ping': { role: 'system', resultType: 'system.pong' }, + 'system.capabilities': { role: 'system', resultType: 'system.capabilities.result' }, + 'profile.create': { role: 'profile', resultType: 'profile.create.result' }, + 'profile.update': { role: 'profile', resultType: 'profile.update.result' }, + 'profile.get': { role: 'profile', resultType: 'profile.get.result' }, + 'profile.pause': { role: 'profile', resultType: 'profile.pause.result' }, + 'profile.resume': { role: 'profile', resultType: 'profile.resume.result' }, + 'profile.delete': { role: 'profile', resultType: 'profile.delete.result' }, + 'visibility.update': { role: 'profile', resultType: 'visibility.update.result' }, + 'discovery.update_location': { + role: 'discovery', + resultType: 'discovery.update_location.result', + }, + 'discovery.get_candidates': { + role: 'discovery', + resultType: 'discovery.get_candidates.result', + }, + 'discovery.update_preferences': { + role: 'discovery', + resultType: 'discovery.update_preferences.result', + }, + 'intent.like': { role: 'matcher', resultType: 'intent.like.result' }, + 'intent.revoke': { role: 'matcher', resultType: 'intent.revoke.result' }, + 'match.list': { role: 'matcher', resultType: 'match.list.result' }, + 'block.create': { role: 'dm_policy', resultType: 'block.create.result' }, + 'block.remove': { role: 'dm_policy', resultType: 'block.remove.result' }, + 'block.list': { role: 'dm_policy', resultType: 'block.list.result' }, + 'unmatch.create': { role: 'dm_policy', resultType: 'unmatch.create.result' }, + 'report.create': { role: 'moderation', resultType: 'report.create.result' }, + 'moderation.action': { + role: 'moderation', + resultType: 'moderation.action.result', + }, + 'verification.list': { + role: 'verification', + resultType: 'verification.list.result', + }, + 'account.delete': { role: 'deletion', resultType: 'account.delete.result' }, +} as const satisfies Record; + +export type OpenDatingRequestType = keyof typeof REQUEST_ROUTES; + +export function getRequestRoute(type: string): RequestRoute | undefined { + return REQUEST_ROUTES[type as OpenDatingRequestType]; +} diff --git a/src/protocols/opendating/services/block/service.ts b/src/protocols/opendating/services/block/service.ts index c2617d1..6f3c016 100644 --- a/src/protocols/opendating/services/block/service.ts +++ b/src/protocols/opendating/services/block/service.ts @@ -21,7 +21,7 @@ export class BlockService implements OpenDatingService { } supports(type: string): boolean { - return ['block.create', 'block.list', 'unmatch.create'].includes(type); + return ['block.create', 'block.remove', 'block.list', 'unmatch.create'].includes(type); } async handle(request: OpenDatingEnvelope, ctx: OpenDatingServiceContext): Promise { @@ -29,6 +29,7 @@ export class BlockService implements OpenDatingService { switch (request.type) { case 'block.create': return this.createBlock(member.memberId, request, ctx); + case 'block.remove': return this.removeBlock(member.memberId, request); case 'block.list': return this.listBlocks(member.memberId, request); case 'unmatch.create': return this.createUnmatch(member.memberId, request, ctx); default: @@ -36,6 +37,36 @@ export class BlockService implements OpenDatingService { } } + private async removeBlock(memberId: string, request: OpenDatingEnvelope): Promise { + const payload = request.payload as Record; + const targetPubkey = payload.target_pubkey; + if (typeof targetPubkey !== 'string' || targetPubkey.length === 0) { + return { + response: createErrorEnvelope( + request.request_id, + 'invalid_envelope', + 'Missing target_pubkey', + ), + }; + } + + const targetMemberId = this.membership.getMemberId(targetPubkey); + const now = Math.floor(Date.now() / 1000); + await this.db.withSession('first-primary').prepare( + `DELETE FROM od_blocks + WHERE blocker_member_id = ? AND blocked_member_id = ?`, + ).bind(memberId, targetMemberId).run(); + + // Removing a block never recreates a match, candidate grant, or intent. + // Those relationships can only be established again through their normal + // explicit user flows. + return { + response: createEnvelope('block.remove.result', request.request_id, { + removed_at: now, + }), + }; + } + private async createBlock(memberId: string, request: OpenDatingEnvelope, ctx: OpenDatingServiceContext): Promise { const payload = request.payload as Record; const targetPubkey = payload.target_pubkey as string; diff --git a/tests/opendating/conformance/protocol.test.ts b/tests/opendating/conformance/protocol.test.ts index 4bf75f9..3056770 100644 --- a/tests/opendating/conformance/protocol.test.ts +++ b/tests/opendating/conformance/protocol.test.ts @@ -8,11 +8,16 @@ import { OPENDATING_PROTOCOL, OPENDATING_VERSION, SUPPORTED_VERSIONS, + ALL_SERVICE_ROLES, } from '../../../src/protocols/opendating/protocol/constants.js'; import { isSupportedVersion, isOpenDatingProtocol, negotiateVersion } from '../../../src/protocols/opendating/protocol/version.js'; import { createEnvelope, validateEnvelope, checkRequestFreshness } from '../../../src/protocols/opendating/protocol/envelope.js'; import { validateODRequest } from '../../../src/protocols/opendating/protocol/validation.js'; import { OD_ERROR_CODES } from '../../../src/protocols/opendating/protocol/errors.js'; +import { + getRequestRoute, + REQUEST_ROUTES, +} from '../../../src/protocols/opendating/protocol/routing.js'; describe('protocol constants', () => { it('should use canonical protocol identifier', () => { @@ -26,6 +31,34 @@ describe('protocol constants', () => { it('should support only 0.1', () => { expect(SUPPORTED_VERSIONS).toEqual(['0.1']); }); + + it('declares every service role advertised by the reference relay', () => { + expect(ALL_SERVICE_ROLES).toContain('deletion'); + }); +}); + +describe('request routing', () => { + it('routes account deletion only to the deletion service', () => { + expect(getRequestRoute('account.delete')).toEqual({ + role: 'deletion', + resultType: 'account.delete.result', + }); + }); + + it('routes block removal and unmatch to the policy service', () => { + expect(getRequestRoute('block.remove')?.role).toBe('dm_policy'); + expect(getRequestRoute('unmatch.create')?.role).toBe('dm_policy'); + }); + + it('gives every registered request an existing validator', async () => { + const { MESSAGE_VALIDATORS } = await import( + '../../../src/protocols/opendating/protocol/message-types.js' + ); + for (const [requestType, route] of Object.entries(REQUEST_ROUTES)) { + expect(MESSAGE_VALIDATORS).toHaveProperty(requestType); + expect(MESSAGE_VALIDATORS).toHaveProperty(route.resultType); + } + }); }); describe('version negotiation', () => { diff --git a/tests/opendating/integration/services.test.ts b/tests/opendating/integration/services.test.ts index 2aeed99..e2fdf65 100644 --- a/tests/opendating/integration/services.test.ts +++ b/tests/opendating/integration/services.test.ts @@ -13,6 +13,9 @@ import { initMembershipKeys, resetMembershipKeys, deriveMemberId } from '../../. import { initOpenDatingExtension } from '../../../src/protocols/opendating/extension.js'; import { grantToken, clampAge, publicProfile } from '../../../src/protocols/opendating/services/discovery/service.js'; import { validateProfileContent } from '../../../src/protocols/opendating/services/profile/service.js'; +import { BlockService } from '../../../src/protocols/opendating/services/block/service.js'; +import { createEnvelope } from '../../../src/protocols/opendating/protocol/envelope.js'; +import type { OpenDatingServiceContext } from '../../../src/protocols/opendating/services/interface.js'; let db: D1Adapter; @@ -263,3 +266,70 @@ describe('Matcher SQL (D1)', () => { expect(quota.daily_reset_at).toBe(newReset); }); }); + +// --------------------------------------------------------------------------- +// Safety policy — block lifecycle +// --------------------------------------------------------------------------- + +describe('Block service (D1)', () => { + const alicePubkey = 'a'.repeat(64); + const bobPubkey = 'b'.repeat(64); + const servicePubkey = 'c'.repeat(64); + + function context(requestId: string): OpenDatingServiceContext { + return { + authenticatedPubkey: alicePubkey, + senderPubkey: alicePubkey, + servicePubkey, + protocolVersion: '0.1', + receivedAt: Math.floor(Date.now() / 1000), + requestId, + }; + } + + it('supports idempotent block removal without restoring relationships', async () => { + const service = new BlockService( + 'dm_policy', + servicePubkey, + db as unknown as D1Database, + ); + expect(service.supports('block.remove')).toBe(true); + + const createRequestId = 'block-create-request'; + await service.handle( + createEnvelope('block.create', createRequestId, { target_pubkey: bobPubkey }), + context(createRequestId), + ); + + const aliceId = deriveMemberId(alicePubkey); + const bobId = deriveMemberId(bobPubkey); + expect( + db.prepare( + `SELECT 1 FROM od_blocks + WHERE blocker_member_id = ? AND blocked_member_id = ?`, + ).bind(aliceId, bobId).first(), + ).not.toBeNull(); + + const removeRequestId = 'block-remove-request'; + const result = await service.handle( + createEnvelope('block.remove', removeRequestId, { target_pubkey: bobPubkey }), + context(removeRequestId), + ); + expect(result.response.type).toBe('block.remove.result'); + expect( + db.prepare( + `SELECT 1 FROM od_blocks + WHERE blocker_member_id = ? AND blocked_member_id = ?`, + ).bind(aliceId, bobId).first(), + ).toBeNull(); + + await expect( + service.handle( + createEnvelope('block.remove', 'block-remove-again', { target_pubkey: bobPubkey }), + context('block-remove-again'), + ), + ).resolves.toMatchObject({ + response: { type: 'block.remove.result' }, + }); + }); +}); diff --git a/tests/opendating/unit/service-identities.test.ts b/tests/opendating/unit/service-identities.test.ts index 1b61248..346d06d 100644 --- a/tests/opendating/unit/service-identities.test.ts +++ b/tests/opendating/unit/service-identities.test.ts @@ -79,6 +79,12 @@ describe('loadServiceIdentitiesFromEnv', () => { expect(LOADABLE_SERVICE_ROLES).not.toContain('verification' as never); expect(LOADABLE_SERVICE_ROLES).not.toContain('media' as never); }); + + it('loads the dedicated deletion identity', () => { + const signers = loadServiceIdentitiesFromEnv(envWithRoles(['deletion'])); + expect(signers).toHaveLength(1); + expect(signers[0].role).toBe('deletion'); + }); }); describe('initMembershipKeys', () => { diff --git a/worker.js b/worker.js index 36adf4a..1cf2286 100644 --- a/worker.js +++ b/worker.js @@ -1300,37 +1300,37 @@ function Field(ORDER, bitLenOrOpts, isLE2 = false, opts = {}) { ZERO: _0n2, ONE: _1n2, allowedLengths, - create: (num2) => mod(num2, ORDER), - isValid: (num2) => { + create: /* @__PURE__ */ __name((num2) => mod(num2, ORDER), "create"), + isValid: /* @__PURE__ */ __name((num2) => { if (typeof num2 !== "bigint") throw new Error("invalid field element: expected bigint, got " + typeof num2); return _0n2 <= num2 && num2 < ORDER; - }, - is0: (num2) => num2 === _0n2, + }, "isValid"), + is0: /* @__PURE__ */ __name((num2) => num2 === _0n2, "is0"), // is valid and invertible - isValidNot0: (num2) => !f.is0(num2) && f.isValid(num2), - isOdd: (num2) => (num2 & _1n2) === _1n2, - neg: (num2) => mod(-num2, ORDER), - eql: (lhs, rhs) => lhs === rhs, - sqr: (num2) => mod(num2 * num2, ORDER), - add: (lhs, rhs) => mod(lhs + rhs, ORDER), - sub: (lhs, rhs) => mod(lhs - rhs, ORDER), - mul: (lhs, rhs) => mod(lhs * rhs, ORDER), - pow: (num2, power) => FpPow(f, num2, power), - div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + isValidNot0: /* @__PURE__ */ __name((num2) => !f.is0(num2) && f.isValid(num2), "isValidNot0"), + isOdd: /* @__PURE__ */ __name((num2) => (num2 & _1n2) === _1n2, "isOdd"), + neg: /* @__PURE__ */ __name((num2) => mod(-num2, ORDER), "neg"), + eql: /* @__PURE__ */ __name((lhs, rhs) => lhs === rhs, "eql"), + sqr: /* @__PURE__ */ __name((num2) => mod(num2 * num2, ORDER), "sqr"), + add: /* @__PURE__ */ __name((lhs, rhs) => mod(lhs + rhs, ORDER), "add"), + sub: /* @__PURE__ */ __name((lhs, rhs) => mod(lhs - rhs, ORDER), "sub"), + mul: /* @__PURE__ */ __name((lhs, rhs) => mod(lhs * rhs, ORDER), "mul"), + pow: /* @__PURE__ */ __name((num2, power) => FpPow(f, num2, power), "pow"), + div: /* @__PURE__ */ __name((lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), "div"), // Same as above, but doesn't normalize - sqrN: (num2) => num2 * num2, - addN: (lhs, rhs) => lhs + rhs, - subN: (lhs, rhs) => lhs - rhs, - mulN: (lhs, rhs) => lhs * rhs, - inv: (num2) => invert(num2, ORDER), + sqrN: /* @__PURE__ */ __name((num2) => num2 * num2, "sqrN"), + addN: /* @__PURE__ */ __name((lhs, rhs) => lhs + rhs, "addN"), + subN: /* @__PURE__ */ __name((lhs, rhs) => lhs - rhs, "subN"), + mulN: /* @__PURE__ */ __name((lhs, rhs) => lhs * rhs, "mulN"), + inv: /* @__PURE__ */ __name((num2) => invert(num2, ORDER), "inv"), sqrt: _sqrt || ((n) => { if (!sqrtP) sqrtP = FpSqrt(ORDER); return sqrtP(f, n); }), - toBytes: (num2) => isLE2 ? numberToBytesLE(num2, BYTES) : numberToBytesBE(num2, BYTES), - fromBytes: (bytes, skipValidation = true) => { + toBytes: /* @__PURE__ */ __name((num2) => isLE2 ? numberToBytesLE(num2, BYTES) : numberToBytesBE(num2, BYTES), "toBytes"), + fromBytes: /* @__PURE__ */ __name((bytes, skipValidation = true) => { if (allowedLengths) { if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) { throw new Error("Field.fromBytes: expected " + allowedLengths + " bytes, got " + bytes.length); @@ -1349,12 +1349,12 @@ function Field(ORDER, bitLenOrOpts, isLE2 = false, opts = {}) { throw new Error("invalid field element: outside of range 0..ORDER"); } return scalar; - }, + }, "fromBytes"), // TODO: we don't need it here, move out to separate fn - invertBatch: (lst) => FpInvertBatch(f, lst), + invertBatch: /* @__PURE__ */ __name((lst) => FpInvertBatch(f, lst), "invertBatch"), // We can't move this out because Fp6, Fp12 implement it // and it's unclear what to return in there. - cmov: (a, b, c) => c ? b : a + cmov: /* @__PURE__ */ __name((a, b, c) => c ? b : a, "cmov") }); return Object.freeze(f); } @@ -2321,7 +2321,7 @@ function ecdh(Point, ecdhOpts = {}) { // TODO: remove isValidPrivateKey: isValidSecretKey, randomPrivateKey: randomSecretKey, - normPrivateKeyToScalar: (key) => _normFnElement(Fn, key), + normPrivateKeyToScalar: /* @__PURE__ */ __name((key) => _normFnElement(Fn, key), "normPrivateKeyToScalar"), precompute(windowSize = 8, point = Point.BASE) { return point.precompute(windowSize, false); } @@ -2689,7 +2689,7 @@ var init_weierstrass = __esm({ Err: DERErr, // Basic building block is TLV (Tag-Length-Value) _tlv: { - encode: (tag, data) => { + encode: /* @__PURE__ */ __name((tag, data) => { const { Err: E } = DER; if (tag < 0 || tag > 256) throw new E("tlv.encode: wrong tag"); @@ -2702,7 +2702,7 @@ var init_weierstrass = __esm({ const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : ""; const t = numberToHexUnpadded(tag); return t + lenLen + len + data; - }, + }, "encode"), // v - value, l - left bytes (unparsed) decode(tag, data) { const { Err: E } = DER; @@ -3592,8 +3592,7 @@ function signEvent(event, privateKeyHex) { return { id, sig }; } function constantTimeEqual(a, b) { - if (a.length !== b.length) - return false; + if (a.length !== b.length) return false; let diff = 0; for (let i = 0; i < a.length; i++) { diff |= a[i] ^ b[i]; @@ -3604,8 +3603,7 @@ function bytesToHex2(bytes) { return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join(""); } function hexToBytes2(hex) { - if (hex.length % 2 !== 0) - throw new Error("Invalid hex string"); + if (hex.length % 2 !== 0) throw new Error("Invalid hex string"); const bytes = new Uint8Array(hex.length / 2); for (let i = 0; i < bytes.length; i++) { bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16); @@ -3681,8 +3679,7 @@ function isValidPingPayload(p) { return typeof p === "object" && p !== null && Object.keys(p).length === 0; } function isValidPongPayload(p) { - if (typeof p !== "object" || p === null) - return false; + if (typeof p !== "object" || p === null) return false; const o = p; return typeof o.server_time === "number" && typeof o.protocol_version === "string"; } @@ -3690,8 +3687,7 @@ function isValidCapabilitiesPayload(p) { return typeof p === "object" && p !== null && Object.keys(p).length === 0; } function isValidCapabilitiesResultPayload(p) { - if (typeof p !== "object" || p === null) - return false; + if (typeof p !== "object" || p === null) return false; const o = p; return Array.isArray(o.versions) && Array.isArray(o.services) && Array.isArray(o.features); } @@ -3715,63 +3711,63 @@ var init_message_types = __esm({ "system.pong": isValidPongPayload, "system.capabilities": isValidCapabilitiesPayload, "system.capabilities.result": isValidCapabilitiesResultPayload, - "system.error": (p) => typeof p === "object" && p !== null && typeof p.code === "string", + "system.error": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null && typeof p.code === "string", "system.error"), // Profile - "profile.create": (p) => typeof p === "object" && p !== null, - "profile.create.result": (p) => typeof p === "object" && p !== null, - "profile.update": (p) => typeof p === "object" && p !== null, - "profile.update.result": (p) => typeof p === "object" && p !== null, - "profile.get": (p) => typeof p === "object" && p !== null, - "profile.get.result": (p) => typeof p === "object" && p !== null, - "profile.pause": (p) => typeof p === "object" && p !== null, - "profile.pause.result": (p) => typeof p === "object" && p !== null, - "profile.resume": (p) => typeof p === "object" && p !== null, - "profile.resume.result": (p) => typeof p === "object" && p !== null, - "profile.delete": (p) => typeof p === "object" && p !== null, - "profile.delete.result": (p) => typeof p === "object" && p !== null, + "profile.create": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.create"), + "profile.create.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.create.result"), + "profile.update": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.update"), + "profile.update.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.update.result"), + "profile.get": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.get"), + "profile.get.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.get.result"), + "profile.pause": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.pause"), + "profile.pause.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.pause.result"), + "profile.resume": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.resume"), + "profile.resume.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.resume.result"), + "profile.delete": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.delete"), + "profile.delete.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "profile.delete.result"), // Discovery - "discovery.update_location": (p) => typeof p === "object" && p !== null, - "discovery.update_location.result": (p) => typeof p === "object" && p !== null, - "discovery.get_candidates": (p) => typeof p === "object" && p !== null, - "discovery.get_candidates.result": (p) => typeof p === "object" && p !== null, - "discovery.update_preferences": (p) => typeof p === "object" && p !== null, - "discovery.update_preferences.result": (p) => typeof p === "object" && p !== null, + "discovery.update_location": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.update_location"), + "discovery.update_location.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.update_location.result"), + "discovery.get_candidates": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.get_candidates"), + "discovery.get_candidates.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.get_candidates.result"), + "discovery.update_preferences": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.update_preferences"), + "discovery.update_preferences.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "discovery.update_preferences.result"), // Intents + Matches - "intent.like": (p) => typeof p === "object" && p !== null, - "intent.like.result": (p) => typeof p === "object" && p !== null, - "intent.revoke": (p) => typeof p === "object" && p !== null, - "intent.revoke.result": (p) => typeof p === "object" && p !== null, - "match.list": (p) => typeof p === "object" && p !== null, - "match.list.result": (p) => typeof p === "object" && p !== null, + "intent.like": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "intent.like"), + "intent.like.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "intent.like.result"), + "intent.revoke": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "intent.revoke"), + "intent.revoke.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "intent.revoke.result"), + "match.list": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "match.list"), + "match.list.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "match.list.result"), // Blocks - "block.create": (p) => typeof p === "object" && p !== null, - "block.create.result": (p) => typeof p === "object" && p !== null, - "block.list": (p) => typeof p === "object" && p !== null, - "block.list.result": (p) => typeof p === "object" && p !== null, - "unmatch.create": (p) => typeof p === "object" && p !== null, - "unmatch.create.result": (p) => typeof p === "object" && p !== null, + "block.create": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.create"), + "block.create.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.create.result"), + "block.list": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.list"), + "block.list.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.list.result"), + "unmatch.create": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "unmatch.create"), + "unmatch.create.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "unmatch.create.result"), // Reports + Moderation - "report.create": (p) => typeof p === "object" && p !== null, - "report.create.result": (p) => typeof p === "object" && p !== null, - "moderation.action": (p) => typeof p === "object" && p !== null, - "moderation.action.result": (p) => typeof p === "object" && p !== null, + "report.create": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "report.create"), + "report.create.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "report.create.result"), + "moderation.action": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "moderation.action"), + "moderation.action.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "moderation.action.result"), // Visibility - "visibility.update": (p) => typeof p === "object" && p !== null, - "visibility.update.result": (p) => typeof p === "object" && p !== null, + "visibility.update": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "visibility.update"), + "visibility.update.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "visibility.update.result"), // Block remove - "block.remove": (p) => typeof p === "object" && p !== null, - "block.remove.result": (p) => typeof p === "object" && p !== null, + "block.remove": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.remove"), + "block.remove.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "block.remove.result"), // Report received ack - "report.received": (p) => typeof p === "object" && p !== null, + "report.received": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "report.received"), // Verification - "verification.list": (p) => typeof p === "object" && p !== null, - "verification.list.result": (p) => typeof p === "object" && p !== null, + "verification.list": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "verification.list"), + "verification.list.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "verification.list.result"), // Account delete - "account.delete": (p) => typeof p === "object" && p !== null, - "account.delete.result": (p) => typeof p === "object" && p !== null, + "account.delete": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "account.delete"), + "account.delete.result": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "account.delete.result"), // Service-level - "service.ack": (p) => typeof p === "object" && p !== null, - "service.error": (p) => typeof p === "object" && p !== null && typeof p.code === "string" + "service.ack": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null, "service.ack"), + "service.error": /* @__PURE__ */ __name((p) => typeof p === "object" && p !== null && typeof p.code === "string", "service.error") }; __name(isKnownMessageType, "isKnownMessageType"); __name(getPayloadValidator, "getPayloadValidator"); @@ -4302,13 +4298,10 @@ function formatLog(entry) { `[${entry.timestamp}]`, `[${entry.level.toUpperCase()}]` ]; - if (entry.sessionId) - parts.push(`[sess:${entry.sessionId.substring(0, 8)}]`); - if (entry.pubkey) - parts.push(`[pk:${entry.pubkey.substring(0, 8)}]`); + if (entry.sessionId) parts.push(`[sess:${entry.sessionId.substring(0, 8)}]`); + if (entry.pubkey) parts.push(`[pk:${entry.pubkey.substring(0, 8)}]`); parts.push(entry.message); - if (entry.data) - parts.push(JSON.stringify(entry.data)); + if (entry.data) parts.push(JSON.stringify(entry.data)); return parts.join(" "); } function log(level, message, context) { @@ -4342,11 +4335,11 @@ var init_logger = __esm({ __name(formatLog, "formatLog"); __name(log, "log"); logger = { - debug: (msg, ctx) => log("debug", msg, ctx), - info: (msg, ctx) => log("info", msg, ctx), - warn: (msg, ctx) => log("warn", msg, ctx), - error: (msg, ctx) => log("error", msg, ctx), - security: (msg, ctx) => log("security", msg, ctx) + debug: /* @__PURE__ */ __name((msg, ctx) => log("debug", msg, ctx), "debug"), + info: /* @__PURE__ */ __name((msg, ctx) => log("info", msg, ctx), "info"), + warn: /* @__PURE__ */ __name((msg, ctx) => log("warn", msg, ctx), "warn"), + error: /* @__PURE__ */ __name((msg, ctx) => log("error", msg, ctx), "error"), + security: /* @__PURE__ */ __name((msg, ctx) => log("security", msg, ctx), "security") }; } }); @@ -4424,8 +4417,7 @@ function initOpenDatingExtension(db) { idempotencyStore = new D1IdempotencyStore(db); } function isAddressedToService(event) { - if (event.kind !== 1059) - return null; + if (event.kind !== 1059) return null; const pTags = event.tags.filter((t) => t[0] === "p").map((t) => t[1]); for (const pTag of pTags) { if (serviceIdentityRegistry.isServicePubkey(pTag)) { @@ -4518,16 +4510,13 @@ async function screenProfileContent(envelope, senderPubkey, context) { try { const payload = envelope.payload; const profile = payload?.profile; - if (!profile) - return; + if (!profile) return; const bio = typeof profile.bio === "string" ? profile.bio : ""; const name = typeof profile.display_name === "string" ? profile.display_name : ""; const text = [name, bio].filter(Boolean).join(" "); - if (text.length < 3) - return; + if (text.length < 3) return; const env = context._env; - if (!env?.AI) - return; + if (!env?.AI) return; const result = await moderateContent(env.AI, text, "profile_bio"); if (shouldBlock(result)) { logger.warn("[moderation] Blocked profile content", { @@ -4544,8 +4533,7 @@ async function screenProfileContent(envelope, senderPubkey, context) { }); } } catch (err) { - if (err.message?.startsWith("Profile content rejected:")) - throw err; + if (err.message?.startsWith("Profile content rejected:")) throw err; logger.error("[moderation] screenProfileContent error"); } } @@ -4729,9 +4717,11 @@ function getSupportedTypesForRole(role) { case "matcher": return ["intent.like", "intent.revoke", "match.list"]; case "dm_policy": - return ["block.create", "block.list", "unmatch.create"]; + return ["block.create", "block.remove", "block.list", "unmatch.create"]; case "moderation": return ["report.create", "moderation.action"]; + case "deletion": + return ["account.delete"]; default: return []; } @@ -4851,18 +4841,12 @@ var init_service = __esm({ // src/protocols/opendating/storage/d1/membership.ts function profileCompleteness(content) { let score = 0; - if (content.display_name && String(content.display_name).trim()) - score += 25; - if (typeof content.age === "number") - score += 15; - if (content.gender) - score += 10; - if (content.bio && String(content.bio).trim().length >= 20) - score += 20; - if (Array.isArray(content.photos) && content.photos.length > 0) - score += 20; - if (Array.isArray(content.interests) && content.interests.length >= 3) - score += 10; + if (content.display_name && String(content.display_name).trim()) score += 25; + if (typeof content.age === "number") score += 15; + if (content.gender) score += 10; + if (content.bio && String(content.bio).trim().length >= 20) score += 20; + if (Array.isArray(content.photos) && content.photos.length > 0) score += 20; + if (Array.isArray(content.interests) && content.interests.length >= 3) score += 10; return Math.min(score, 100); } function initMembershipKeys(env) { @@ -4964,8 +4948,7 @@ var init_membership = __esm({ this.dataKey = null; } async ensureDataKey() { - if (!this.dataKey) - this.dataKey = await getDataKey(); + if (!this.dataKey) this.dataKey = await getDataKey(); return this.dataKey; } getMemberId(pubkey) { @@ -4980,8 +4963,7 @@ var init_membership = __esm({ const row = await session.prepare( "SELECT * FROM od_members WHERE member_id = ?" ).bind(memberId).first(); - if (!row) - return null; + if (!row) return null; const dk = await this.ensureDataKey(); const pubkeyDecrypted = await decryptString(row.encrypted_pubkey, dk); return { @@ -5032,10 +5014,8 @@ var init_membership = __esm({ async ensureMember(pubkey) { const existing = await this.getMember(pubkey); if (existing) { - if (existing.status === "deleted") - throw new Error("Member has been deleted"); - if (existing.status === "banned") - throw new Error("Member is banned"); + if (existing.status === "deleted") throw new Error("Member has been deleted"); + if (existing.status === "banned") throw new Error("Member is banned"); return existing; } return this.createMember(pubkey); @@ -5088,8 +5068,7 @@ var init_membership = __esm({ const row = await session.prepare( "SELECT * FROM od_profiles WHERE member_id = ?" ).bind(memberId).first(); - if (!row) - return null; + if (!row) return null; return { memberId: row.member_id, profileVersion: row.profile_version, @@ -5161,8 +5140,7 @@ var init_membership = __esm({ const row = await session.prepare( `SELECT encrypted_pubkey FROM od_members WHERE member_id = ? AND status = 'active'` ).bind(memberId).first(); - if (typeof row?.encrypted_pubkey !== "string") - return null; + if (typeof row?.encrypted_pubkey !== "string") return null; try { const dk = await this.ensureDataKey(); return await decryptString(row.encrypted_pubkey, dk); @@ -5184,8 +5162,7 @@ var init_membership = __esm({ "SELECT encrypted_profile_payload FROM od_profiles WHERE member_id = ?" ).bind(memberId).first(); const blob = row?.encrypted_profile_payload; - if (typeof blob !== "string" || blob.length === 0) - return null; + if (typeof blob !== "string" || blob.length === 0) return null; try { const dk = await this.ensureDataKey(); return JSON.parse(await decryptString(blob, dk)); @@ -5201,8 +5178,7 @@ var init_membership = __esm({ */ async getPubkeysByMemberIds(memberIds) { const result = /* @__PURE__ */ new Map(); - if (memberIds.length === 0) - return result; + if (memberIds.length === 0) return result; const placeholders = memberIds.map(() => "?").join(","); const session = this.db.withSession("first-unconstrained"); const rows = await session.prepare( @@ -5226,8 +5202,7 @@ var init_membership = __esm({ */ async getProfileContentsByMemberIds(memberIds) { const result = /* @__PURE__ */ new Map(); - if (memberIds.length === 0) - return result; + if (memberIds.length === 0) return result; const placeholders = memberIds.map(() => "?").join(","); const session = this.db.withSession("first-unconstrained"); const rows = await session.prepare( @@ -5237,8 +5212,7 @@ var init_membership = __esm({ const dk = await this.ensureDataKey(); for (const row of rows.results ?? []) { const blob = row.encrypted_profile_payload; - if (typeof blob !== "string" || blob.length === 0) - continue; + if (typeof blob !== "string" || blob.length === 0) continue; try { result.set(row.member_id, JSON.parse(await decryptString(blob, dk))); } catch { @@ -5264,8 +5238,7 @@ var init_membership = __esm({ FROM od_members m LEFT JOIN od_profiles p ON p.member_id = m.member_id WHERE m.member_id = ?` ).bind(memberId).first(); - if (!row) - return; + if (!row) return; const visible = row.status === "active" && row.visibility_state === "discoverable" ? 1 : 0; await session.prepare( `INSERT INTO od_discovery_index @@ -5317,18 +5290,14 @@ function validateProfileContent(profile) { } const p = profile; const name = typeof p.display_name === "string" ? p.display_name.trim() : ""; - if (name.length === 0) - return "display_name is required"; - if (name.length > 80) - return "display_name must be 80 characters or fewer"; + if (name.length === 0) return "display_name is required"; + if (name.length > 80) return "display_name must be 80 characters or fewer"; if (p.age !== void 0) { if (typeof p.age !== "number" || !Number.isInteger(p.age)) { return "age must be a whole number"; } - if (p.age < MIN_AGE) - return `age must be at least ${MIN_AGE}`; - if (p.age > MAX_AGE) - return `age must be ${MAX_AGE} or under`; + if (p.age < MIN_AGE) return `age must be at least ${MIN_AGE}`; + if (p.age > MAX_AGE) return `age must be ${MAX_AGE} or under`; } if (p.bio !== void 0 && typeof p.bio === "string" && p.bio.length > MAX_BIO_LENGTH) { return `bio must be ${MAX_BIO_LENGTH} characters or fewer`; @@ -5429,8 +5398,7 @@ var init_service2 = __esm({ } async handleGet(request, ctx) { const member = await this.membership.getMember(ctx.senderPubkey); - if (!member) - return { response: createErrorEnvelope(request.request_id, "unauthorized", "No membership") }; + if (!member) return { response: createErrorEnvelope(request.request_id, "unauthorized", "No membership") }; const profile = await this.membership.getProfile(ctx.senderPubkey); const content = await this.membership.getProfileContent(ctx.senderPubkey); return { response: createEnvelope("profile.get.result", request.request_id, { @@ -5477,13 +5445,11 @@ function encodeBase64url(input) { } function decodeBase64url(input) { let base64 = input.replace(/-/g, "+").replace(/_/g, "/"); - while (base64.length % 4) - base64 += "="; + while (base64.length % 4) base64 += "="; return atob(base64); } function clampAge(value, fallback) { - if (typeof value !== "number" || !Number.isFinite(value)) - return fallback; + if (typeof value !== "number" || !Number.isFinite(value)) return fallback; return Math.min(Math.max(Math.round(value), 18), 120); } function grantToken(viewerId, candidateId, now) { @@ -5701,8 +5667,7 @@ var init_service3 = __esm({ const row = await session.prepare( `SELECT geo_cell_p5, geo_cell_p4, geo_cell_p3 FROM od_discovery_index WHERE member_id = ?` ).bind(memberId).first(); - if (!row || !row.geo_cell_p3) - return null; + if (!row || !row.geo_cell_p3) return null; const prefRow = await session.prepare( `SELECT age_min, age_max, max_distance_km, genders, intent FROM od_discovery_prefs WHERE member_id = ?` @@ -5711,8 +5676,7 @@ var init_service3 = __esm({ if (typeof prefRow?.genders === "string") { try { const parsed = JSON.parse(prefRow.genders); - if (Array.isArray(parsed) && parsed.length > 0) - genders = parsed; + if (Array.isArray(parsed) && parsed.length > 0) genders = parsed; } catch { } } @@ -5762,17 +5726,13 @@ var init_service3 = __esm({ const session = this.db.withSession("first-unconstrained"); const maxPrecision = viewer.prefs.maxDistanceKm <= 10 ? 5 : viewer.prefs.maxDistanceKm <= 50 ? 4 : 3; for (const tier of GEO_TIERS) { - if (collected.length >= want) - break; - if (tier.precision < maxPrecision) - break; + if (collected.length >= want) break; + if (tier.precision < maxPrecision) break; const cell = viewer.cells[tier.column]; - if (!cell) - continue; + if (!cell) continue; const genderFilter = viewer.prefs.genders ? ` AND di.gender_category IN (${viewer.prefs.genders.map(() => "?").join(",")})` : ""; const binds = [cell, viewer.prefs.ageMin, viewer.prefs.ageMax]; - if (viewer.prefs.genders) - binds.push(...viewer.prefs.genders); + if (viewer.prefs.genders) binds.push(...viewer.prefs.genders); binds.push( memberId, // di.member_id != ? @@ -5812,8 +5772,7 @@ var init_service3 = __esm({ LIMIT ?` ).bind(...binds).all(); for (const raw of rows.results ?? []) { - if (excluded.has(raw.member_id)) - continue; + if (excluded.has(raw.member_id)) continue; excluded.add(raw.member_id); collected.push({ candidate_id: raw.member_id, @@ -5821,8 +5780,7 @@ var init_service3 = __esm({ distance_bucket: tier.bucket, granted_at: now }); - if (collected.length >= want) - break; + if (collected.length >= want) break; } } if (collected.length > 0) { @@ -5861,8 +5819,7 @@ var init_service3 = __esm({ * Batch-hydrates in 2 D1 queries regardless of page size (was 2N). */ async hydrate(grants) { - if (grants.length === 0) - return []; + if (grants.length === 0) return []; const memberIds = [...new Set(grants.map((g) => g.candidate_id))]; const [pubkeyMap, profileMap] = await Promise.all([ this.membership.getPubkeysByMemberIds(memberIds), @@ -5871,11 +5828,9 @@ var init_service3 = __esm({ const out = []; for (const grant of grants) { const pubkey = pubkeyMap.get(grant.candidate_id); - if (!pubkey) - continue; + if (!pubkey) continue; const content = profileMap.get(grant.candidate_id); - if (!content) - continue; + if (!content) continue; out.push({ pubkey, profile: publicProfile(content), @@ -5893,8 +5848,7 @@ var init_service3 = __esm({ const row = await session.prepare( "SELECT daily_candidates_served, daily_reset_at FROM od_discovery_quotas WHERE member_id = ?" ).bind(memberId).first(); - if (!row) - return { exhausted: false, servedToday: 0, resetAt: now + DAY_SEC }; + if (!row) return { exhausted: false, servedToday: 0, resetAt: now + DAY_SEC }; const resetAt = row.daily_reset_at ?? 0; if (now > resetAt) { return { exhausted: false, servedToday: 0, resetAt: now + DAY_SEC }; @@ -5979,19 +5933,24 @@ var init_service4 = __esm({ const candidateGrant = payload.candidate_grant; const now = Math.floor(Date.now() / 1e3); const session = this.db.withSession("first-primary"); - if (candidateGrant) { - const grant = await session.prepare( - `SELECT grant_token FROM od_candidate_grants - WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? - AND (expires_at IS NULL OR expires_at > ?)` - ).bind(memberId, targetMemberId, candidateGrant, now).first(); - if (!grant) { - return { response: createErrorEnvelope( - request.request_id, - "invalid_candidate_grant", - "No valid grant found \u2014 this profile may no longer be available" - ) }; - } + if (!candidateGrant) { + return { response: createErrorEnvelope( + request.request_id, + "invalid_candidate_grant", + "This profile is no longer available." + ) }; + } + const grant = await session.prepare( + `SELECT grant_token FROM od_candidate_grants + WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? + AND (expires_at IS NULL OR expires_at > ?)` + ).bind(memberId, targetMemberId, candidateGrant, now).first(); + if (!grant) { + return { response: createErrorEnvelope( + request.request_id, + "invalid_candidate_grant", + "No valid grant found \u2014 this profile may no longer be available" + ) }; } const likeQuota = await session.prepare( `SELECT daily_likes_sent, daily_reset_at FROM od_discovery_quotas WHERE member_id = ?` @@ -6019,11 +5978,9 @@ var init_service4 = __esm({ daily_reset_at = CASE WHEN daily_reset_at < ? THEN ? ELSE daily_reset_at END, updated_at = ?` ).bind(memberId, newResetAt, now, now, newResetAt, now, now).run(); - if (candidateGrant) { - await session.prepare( - `DELETE FROM od_candidate_grants WHERE viewer_id = ? AND candidate_id = ?` - ).bind(memberId, targetMemberId).run(); - } + await session.prepare( + `DELETE FROM od_candidate_grants WHERE viewer_id = ? AND candidate_id = ?` + ).bind(memberId, targetMemberId).run(); const reciprocal = await session.prepare( `SELECT id FROM od_intents WHERE from_member_id = ? AND to_member_id = ? AND intent_type = 'like' AND state = 'active'` @@ -6107,13 +6064,15 @@ var init_service5 = __esm({ this.membership = new D1MembershipStore(db); } supports(type) { - return ["block.create", "block.list", "unmatch.create"].includes(type); + return ["block.create", "block.remove", "block.list", "unmatch.create"].includes(type); } async handle(request, ctx) { const member = await this.membership.ensureMember(ctx.senderPubkey); switch (request.type) { case "block.create": return this.createBlock(member.memberId, request, ctx); + case "block.remove": + return this.removeBlock(member.memberId, request); case "block.list": return this.listBlocks(member.memberId, request); case "unmatch.create": @@ -6122,6 +6081,30 @@ var init_service5 = __esm({ throw new Error(`Block service does not support: ${request.type}`); } } + async removeBlock(memberId, request) { + const payload = request.payload; + const targetPubkey = payload.target_pubkey; + if (typeof targetPubkey !== "string" || targetPubkey.length === 0) { + return { + response: createErrorEnvelope( + request.request_id, + "invalid_envelope", + "Missing target_pubkey" + ) + }; + } + const targetMemberId = this.membership.getMemberId(targetPubkey); + const now = Math.floor(Date.now() / 1e3); + await this.db.withSession("first-primary").prepare( + `DELETE FROM od_blocks + WHERE blocker_member_id = ? AND blocked_member_id = ?` + ).bind(memberId, targetMemberId).run(); + return { + response: createEnvelope("block.remove.result", request.request_id, { + removed_at: now + }) + }; + } async createBlock(memberId, request, ctx) { const payload = request.payload; const targetPubkey = payload.target_pubkey; @@ -6351,8 +6334,7 @@ var init_service7 = __esm({ // src/protocols/opendating/index.ts function initOpenDating(env, db) { - if (initialized) - return; + if (initialized) return; console.log("[OpenDating] Initializing protocol core..."); try { initMembershipKeys(env || {}); @@ -6367,13 +6349,13 @@ function initOpenDating(env, db) { return; } const factories = { - system: (pk) => odServiceRegistry.register(new SystemService("system", pk)), - profile: (pk) => odServiceRegistry.register(new ProfileService("profile", pk, db)), - discovery: (pk) => odServiceRegistry.register(new DiscoveryService("discovery", pk, db)), - matcher: (pk) => odServiceRegistry.register(new MatcherService("matcher", pk, db)), - dm_policy: (pk) => odServiceRegistry.register(new BlockService("dm_policy", pk, db)), - moderation: (pk) => odServiceRegistry.register(new ModerationService("moderation", pk, db)), - deletion: (pk) => odServiceRegistry.register(new DeletionService("deletion", pk, db)) + system: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new SystemService("system", pk)), "system"), + profile: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new ProfileService("profile", pk, db)), "profile"), + discovery: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new DiscoveryService("discovery", pk, db)), "discovery"), + matcher: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new MatcherService("matcher", pk, db)), "matcher"), + dm_policy: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new BlockService("dm_policy", pk, db)), "dm_policy"), + moderation: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new ModerationService("moderation", pk, db)), "moderation"), + deletion: /* @__PURE__ */ __name((pk) => odServiceRegistry.register(new DeletionService("deletion", pk, db)), "deletion") }; for (const signer of signers) { const factory = factories[signer.role]; @@ -6436,24 +6418,20 @@ function computeEventId(event) { return bytesToHex2(sha2562(new TextEncoder().encode(serialized))); } function parseAuthHeader(header) { - if (!header) - return null; + if (!header) return null; const match = /^Nostr\s+(.+)$/i.exec(header.trim()); - if (!match) - return null; + if (!match) return null; try { const json2 = atob(match[1]); const parsed = JSON.parse(json2); - if (typeof parsed?.pubkey !== "string" || !Array.isArray(parsed?.tags)) - return null; + if (typeof parsed?.pubkey !== "string" || !Array.isArray(parsed?.tags)) return null; return parsed; } catch { return null; } } function verifyAuth(event, verb, now, blobHash) { - if (!event) - return { ok: false, error: "Missing Authorization header" }; + if (!event) return { ok: false, error: "Missing Authorization header" }; if (event.kind !== BLOSSOM_AUTH_KIND) { return { ok: false, error: `Authorization must be kind ${BLOSSOM_AUTH_KIND}` }; } @@ -6495,8 +6473,7 @@ function verifyAuth(event, verb, now, blobHash) { hexToBytes2(event.id), hexToBytes2(event.pubkey) ); - if (!valid) - return { ok: false, error: "Invalid signature" }; + if (!valid) return { ok: false, error: "Invalid signature" }; } catch { return { ok: false, error: "Invalid signature" }; } @@ -6595,8 +6572,7 @@ async function handleUpload(request, bucket, origin) { return error(`Blob exceeds ${MAX_BLOB_BYTES} bytes`, 413); } const body = new Uint8Array(await request.arrayBuffer()); - if (body.byteLength === 0) - return error("Empty body", 400); + if (body.byteLength === 0) return error("Empty body", 400); if (body.byteLength > MAX_BLOB_BYTES) { return error(`Blob exceeds ${MAX_BLOB_BYTES} bytes`, 413); } @@ -6630,8 +6606,7 @@ async function handleUpload(request, bucket, origin) { } async function handleGet(hash, bucket, headOnly) { const object = headOnly ? await bucket.head(hash) : await bucket.get(hash); - if (!object) - return error("Blob not found", 404); + if (!object) return error("Blob not found", 404); const headers = new Headers({ "Content-Type": object.httpMetadata?.contentType ?? "application/octet-stream", "Content-Length": String(object.size), @@ -6639,20 +6614,17 @@ async function handleGet(hash, bucket, headOnly) { "Access-Control-Allow-Origin": "*", ETag: object.httpEtag }); - if (headOnly) - return new Response(null, { status: 200, headers }); + if (headOnly) return new Response(null, { status: 200, headers }); return new Response(object.body, { status: 200, headers }); } async function handleList(url, bucket) { const pubkey = url.pathname.slice("/list/".length).toLowerCase(); - if (!/^[0-9a-f]{64}$/.test(pubkey)) - return error("Malformed pubkey", 400); + if (!/^[0-9a-f]{64}$/.test(pubkey)) return error("Malformed pubkey", 400); const listed = await bucket.list({ limit: 1e3 }); const blobs = []; for (const entry of listed.objects) { const object = await bucket.head(entry.key); - if (object?.customMetadata?.uploader !== pubkey) - continue; + if (object?.customMetadata?.uploader !== pubkey) continue; const type = object.httpMetadata?.contentType ?? "application/octet-stream"; blobs.push({ url: blobUrl(url.origin, object.key, type), @@ -6672,8 +6644,7 @@ async function handleDelete(request, hash, bucket) { return error(authResult.error ?? "Unauthorized", 401); } const object = await bucket.head(hash); - if (!object) - return error("Blob not found", 404); + if (!object) return error("Blob not found", 404); if (object.customMetadata?.uploader !== authResult.pubkey) { return error("Only the uploader may delete this blob", 403); } @@ -6742,8 +6713,7 @@ async function processTask(message, db, ai) { } async function processReportCreated(db, payload) { const { reportId } = payload; - if (!reportId) - return; + if (!reportId) return; await db.prepare( `UPDATE od_reports SET status = 'triaging' WHERE report_id = ? AND status = 'pending'` ).bind(reportId).run(); @@ -6751,8 +6721,7 @@ async function processReportCreated(db, payload) { } async function processMatchNotification(db, payload) { const { matchId, memberA, memberB } = payload; - if (!matchId) - return; + if (!matchId) return; await db.prepare( `INSERT OR IGNORE INTO od_match_notifications (match_id, member_id, notified_at) VALUES (?, ?, ?), (?, ?, ?)` @@ -6768,8 +6737,7 @@ async function processMatchNotification(db, payload) { } async function processMemberDeleted(db, payload) { const { memberId } = payload; - if (!memberId) - return; + if (!memberId) return; const now = Math.floor(Date.now() / 1e3); const tables = [ "od_profiles", @@ -6800,8 +6768,7 @@ async function processMemberDeleted(db, payload) { } async function processProfileUpdated(db, payload) { const { memberId } = payload; - if (!memberId) - return; + if (!memberId) return; const now = Math.floor(Date.now() / 1e3); await db.prepare( `UPDATE od_discovery_index SET updated_at = ? WHERE member_id = ?` @@ -6824,8 +6791,7 @@ function nip11Key() { return "cache:nip11"; } async function getCachedNip11(kv) { - if (!kv) - return null; + if (!kv) return null; try { return await kv.get(nip11Key()); } catch (err) { @@ -6834,8 +6800,7 @@ async function getCachedNip11(kv) { } } async function setCachedNip11(kv, json2) { - if (!kv) - return; + if (!kv) return; try { await kv.put(nip11Key(), json2, { expirationTtl: NIP11_CACHE_TTL }); } catch (err) { @@ -7035,8 +7000,7 @@ async function initializeDatabase(db) { try { await session.prepare(`ALTER TABLE events ADD COLUMN ${col} TEXT`).run(); } catch (e) { - if (!e.message?.includes("duplicate column")) - throw e; + if (!e.message?.includes("duplicate column")) throw e; } } await session.prepare(` @@ -7063,8 +7027,7 @@ async function initializeDatabase(db) { try { await session.prepare(`ALTER TABLE events ADD COLUMN ${col} TEXT`).run(); } catch (e) { - if (!e.message?.includes("duplicate column")) - throw e; + if (!e.message?.includes("duplicate column")) throw e; } } await session.prepare(` @@ -7145,8 +7108,7 @@ function serializeEventForSigning(event) { ]); } function hexToBytes3(hexString) { - if (hexString.length % 2 !== 0) - throw new Error("Invalid hex string"); + if (hexString.length % 2 !== 0) throw new Error("Invalid hex string"); const bytes = new Uint8Array(hexString.length / 2); for (let i = 0; i < bytes.length; i++) { bytes[i] = parseInt(hexString.substr(i * 2, 2), 16); @@ -7166,8 +7128,7 @@ function shouldCheckForDuplicates(kind) { return enableAntiSpam2 && antiSpamKinds2.has(kind); } async function hasPaidForRelay(pubkey, env) { - if (!PAY_TO_RELAY_ENABLED2) - return true; + if (!PAY_TO_RELAY_ENABLED2) return true; try { const session = env.RELAY_DATABASE.withSession("first-unconstrained"); const result = await session.prepare( @@ -7444,24 +7405,15 @@ async function saveEventToDatabase(event, env) { name: tag[0], value: tag[1] || "" }); - if (tag[0] === "p" && !tagP) - tagP = tag[1]; - if (tag[0] === "e" && !tagE) - tagE = tag[1]; - if (tag[0] === "a" && !tagA) - tagA = tag[1]; - if (tag[0] === "t" && !tagT) - tagT = tag[1]; - if (tag[0] === "d" && !tagD) - tagD = tag[1]; - if (tag[0] === "r" && !tagR) - tagR = tag[1]; - if (tag[0] === "L" && !tagL) - tagL = tag[1]; - if (tag[0] === "s" && !tagS) - tagS = tag[1]; - if (tag[0] === "u" && !tagU) - tagU = tag[1]; + if (tag[0] === "p" && !tagP) tagP = tag[1]; + if (tag[0] === "e" && !tagE) tagE = tag[1]; + if (tag[0] === "a" && !tagA) tagA = tag[1]; + if (tag[0] === "t" && !tagT) tagT = tag[1]; + if (tag[0] === "d" && !tagD) tagD = tag[1]; + if (tag[0] === "r" && !tagR) tagR = tag[1]; + if (tag[0] === "L" && !tagL) tagL = tag[1]; + if (tag[0] === "s" && !tagS) tagS = tag[1]; + if (tag[0] === "u" && !tagU) tagU = tag[1]; } } const eTags = tagInserts.filter((t) => t.name === "e").map((t) => t.value); @@ -8133,8 +8085,7 @@ async function queryEvents(filters, bookmark, env) { console.log(`Filter has arrays >${CHUNK_SIZE} items, using chunked query...`); const chunkedResult = await queryDatabaseChunked(filter, bookmark, env); for (const event of chunkedResult.events) { - if (totalEventsRead >= GLOBAL_MAX_EVENTS) - break; + if (totalEventsRead >= GLOBAL_MAX_EVENTS) break; eventSet.set(event.id, event); totalEventsRead++; } @@ -8177,8 +8128,7 @@ async function queryEvents(filters, bookmark, env) { } if (result.success && result.results) { for (const row of result.results) { - if (totalEventsRead >= GLOBAL_MAX_EVENTS) - break; + if (totalEventsRead >= GLOBAL_MAX_EVENTS) break; allRows.push(row); totalEventsRead++; } @@ -10161,8 +10111,7 @@ var init_durable_object = __esm({ const activeWebSockets = this.state.getWebSockets(); for (const ws of activeWebSockets) { const attachment = ws.deserializeAttachment(); - if (!attachment) - continue; + if (!attachment) continue; let session = this.sessions.get(attachment.sessionId); if (!session) { const subscriptions = await this.loadSubscriptions(attachment.sessionId); @@ -10198,8 +10147,7 @@ var init_durable_object = __esm({ async broadcastToOtherDOs(event) { const broadcasts = []; for (const endpoint of _RelayWebSocket.ALLOWED_ENDPOINTS) { - if (endpoint === this.doName) - continue; + if (endpoint === this.doName) continue; broadcasts.push(this.sendToSpecificDO(endpoint, event)); } const results = await Promise.allSettled( @@ -10376,20 +10324,10 @@ export { (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *) @noble/curves/esm/utils.js: - (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) - @noble/curves/esm/abstract/modular.js: - (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) - @noble/curves/esm/abstract/curve.js: - (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) - @noble/curves/esm/abstract/weierstrass.js: - (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) - @noble/curves/esm/_shortw_utils.js: - (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) - @noble/curves/esm/secp256k1.js: (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *) From 2c79d124c335899d15c262be7e4452611e97d4d9 Mon Sep 17 00:00:00 2001 From: Jonathan Gan Date: Sun, 9 Aug 2026 06:52:13 -0400 Subject: [PATCH 2/2] Fix protocol review findings --- .github/workflows/ci.yml | 7 +- README.md | 6 +- packages/protocol/README.md | 4 +- src/protocols/opendating/identities/loader.ts | 2 +- .../opendating/services/block/service.ts | 4 +- .../opendating/services/matcher/service.ts | 27 +++---- tests/opendating/integration/services.test.ts | 77 +++++++++++++++++++ .../unit/service-identities.test.ts | 10 +++ worker.js | 33 ++++---- 9 files changed, 131 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a456ad..6eb1d2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/setup-node@v4 with: @@ -79,7 +81,10 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - if: github.event_name == 'pull_request' + uses: actions/checkout@v4 + with: + persist-credentials: false - if: github.event_name == 'pull_request' uses: actions/dependency-review-action@v4 with: diff --git a/README.md b/README.md index d8e3d58..e1b6789 100644 --- a/README.md +++ b/README.md @@ -126,9 +126,13 @@ npm run deploy ## Protocol Package ```bash -npm install opendating-protocol@0.1.1 +npm install opendating-protocol@0.1.0 ``` +`0.1.0` is the current npm registry release. The `0.1.1` contract repair is +implemented on this branch but must not be referenced by install instructions +until the package has been published and its registry artifact verified. + ```typescript import { createEnvelope, buildGiftWrap, nip44Encrypt, nip44Decrypt, diff --git a/packages/protocol/README.md b/packages/protocol/README.md index fee5bf5..3d0ba4b 100644 --- a/packages/protocol/README.md +++ b/packages/protocol/README.md @@ -2,7 +2,9 @@ OpenDating protocol — types, constants, validators, crypto helpers. -Current package release: `0.1.1`. Protocol wire version remains experimental `0.1`. +Current source version: `0.1.1`. The npm registry release remains `0.1.0` until +the 0.1.1 artifact is published and verified. Protocol wire version remains +experimental `0.1`. **Zero Cloudflare/Worker/D1/Durable Object dependencies.** diff --git a/src/protocols/opendating/identities/loader.ts b/src/protocols/opendating/identities/loader.ts index c6c2332..08f8bf5 100644 --- a/src/protocols/opendating/identities/loader.ts +++ b/src/protocols/opendating/identities/loader.ts @@ -131,7 +131,7 @@ export function getServiceIdentitiesForCapabilities(): Array<{ function getSupportedTypesForRole(role: string): string[] { switch (role) { case 'system': return ['system.ping', 'system.capabilities']; - case 'profile': return ['profile.create', 'profile.update', 'profile.get', 'profile.pause', 'profile.resume', 'profile.delete']; + case 'profile': return ['profile.create', 'profile.update', 'profile.get', 'profile.pause', 'profile.resume', 'profile.delete', 'visibility.update']; case 'discovery': return ['discovery.update_location', 'discovery.get_candidates', 'discovery.update_preferences']; case 'matcher': return ['intent.like', 'intent.revoke', 'match.list']; case 'dm_policy': return ['block.create', 'block.remove', 'block.list', 'unmatch.create']; diff --git a/src/protocols/opendating/services/block/service.ts b/src/protocols/opendating/services/block/service.ts index 6f3c016..1aaed17 100644 --- a/src/protocols/opendating/services/block/service.ts +++ b/src/protocols/opendating/services/block/service.ts @@ -40,12 +40,12 @@ export class BlockService implements OpenDatingService { private async removeBlock(memberId: string, request: OpenDatingEnvelope): Promise { const payload = request.payload as Record; const targetPubkey = payload.target_pubkey; - if (typeof targetPubkey !== 'string' || targetPubkey.length === 0) { + if (typeof targetPubkey !== 'string' || !/^[0-9a-f]{64}$/i.test(targetPubkey)) { return { response: createErrorEnvelope( request.request_id, 'invalid_envelope', - 'Missing target_pubkey', + 'Invalid target_pubkey', ), }; } diff --git a/src/protocols/opendating/services/matcher/service.ts b/src/protocols/opendating/services/matcher/service.ts index e365317..b1a97a3 100644 --- a/src/protocols/opendating/services/matcher/service.ts +++ b/src/protocols/opendating/services/matcher/service.ts @@ -70,16 +70,6 @@ export class MatcherService implements OpenDatingService { return { response: createErrorEnvelope(request.request_id, 'invalid_candidate_grant', 'This profile is no longer available.') }; } - const grant = await session.prepare( - `SELECT grant_token FROM od_candidate_grants - WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? - AND (expires_at IS NULL OR expires_at > ?)` - ).bind(memberId, targetMemberId, candidateGrant, now).first(); - if (!grant) { - return { response: createErrorEnvelope(request.request_id, 'invalid_candidate_grant', - 'No valid grant found — this profile may no longer be available') }; - } - // Enforce daily like quota const likeQuota = await session.prepare( `SELECT daily_likes_sent, daily_reset_at FROM od_discovery_quotas WHERE member_id = ?` @@ -91,6 +81,18 @@ export class MatcherService implements OpenDatingService { 'Daily like limit reached') }; } + // Atomically consume the exact, unexpired grant before any side effect. + // D1 serializes writes, so concurrent replays cannot both observe success. + const consumedGrant = await session.prepare( + `DELETE FROM od_candidate_grants + WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? + AND (expires_at IS NULL OR expires_at > ?)` + ).bind(memberId, targetMemberId, candidateGrant, now).run(); + if ((consumedGrant.meta.changes ?? 0) !== 1) { + return { response: createErrorEnvelope(request.request_id, 'invalid_candidate_grant', + 'No valid grant found — this profile may no longer be available') }; + } + const iid = intentId(ctx.senderPubkey, targetPubkey, 'like'); // Record the intent @@ -110,11 +112,6 @@ export class MatcherService implements OpenDatingService { updated_at = ?` ).bind(memberId, newResetAt, now, now, newResetAt, now, now).run(); - // Consume the grant — one-time use - await session.prepare( - `DELETE FROM od_candidate_grants WHERE viewer_id = ? AND candidate_id = ?` - ).bind(memberId, targetMemberId).run(); - // Check for reciprocal match const reciprocal = await session.prepare( `SELECT id FROM od_intents diff --git a/tests/opendating/integration/services.test.ts b/tests/opendating/integration/services.test.ts index e2fdf65..9324517 100644 --- a/tests/opendating/integration/services.test.ts +++ b/tests/opendating/integration/services.test.ts @@ -14,6 +14,7 @@ import { initOpenDatingExtension } from '../../../src/protocols/opendating/exten import { grantToken, clampAge, publicProfile } from '../../../src/protocols/opendating/services/discovery/service.js'; import { validateProfileContent } from '../../../src/protocols/opendating/services/profile/service.js'; import { BlockService } from '../../../src/protocols/opendating/services/block/service.js'; +import { MatcherService } from '../../../src/protocols/opendating/services/matcher/service.js'; import { createEnvelope } from '../../../src/protocols/opendating/protocol/envelope.js'; import type { OpenDatingServiceContext } from '../../../src/protocols/opendating/services/interface.js'; @@ -162,6 +163,64 @@ describe('Discovery SQL (D1)', () => { // --------------------------------------------------------------------------- describe('Matcher SQL (D1)', () => { + const alicePubkey = 'a'.repeat(64); + const bobPubkey = 'b'.repeat(64); + const servicePubkey = 'c'.repeat(64); + + function context(requestId: string): OpenDatingServiceContext { + return { + authenticatedPubkey: alicePubkey, + senderPubkey: alicePubkey, + servicePubkey, + protocolVersion: '0.1', + receivedAt: Math.floor(Date.now() / 1000), + requestId, + }; + } + + it('consumes a candidate grant exactly once before like side effects', async () => { + const service = new MatcherService( + 'matcher', + servicePubkey, + db as unknown as D1Database, + ); + const aliceId = deriveMemberId(alicePubkey); + const bobId = deriveMemberId(bobPubkey); + const grant = 'single-use-candidate-grant'; + + await db.prepare( + `INSERT INTO od_candidate_grants + (viewer_id, candidate_id, grant_token, grant_type, distance_bucket, granted_at, expires_at) + VALUES (?, ?, ?, 'discovery', 'nearby', ?, ?)`, + ).bind(aliceId, bobId, grant, 1, Math.floor(Date.now() / 1000) + 3_600).run(); + + const requests = ['like-one', 'like-two'].map((requestId) => + service.handle( + createEnvelope('intent.like', requestId, { + target_pubkey: bobPubkey, + candidate_grant: grant, + }), + context(requestId), + ), + ); + const results = await Promise.all(requests); + + expect(results.map((result) => result.response.type).sort()).toEqual([ + 'intent.like.result', + 'system.error', + ]); + expect( + db.prepare( + 'SELECT COUNT(*) AS count FROM od_intents WHERE from_member_id = ? AND to_member_id = ?', + ).bind(aliceId, bobId).first<{ count: number }>()?.count, + ).toBe(1); + expect( + db.prepare( + 'SELECT daily_likes_sent FROM od_discovery_quotas WHERE member_id = ?', + ).bind(aliceId).first<{ daily_likes_sent: number }>()?.daily_likes_sent, + ).toBe(1); + }); + it('grant verification rejects wrong token', async () => { await db.prepare(`INSERT INTO od_members (member_id, encrypted_pubkey, status, created_at, updated_at) VALUES ('alice', 'enc-alice-x-32-bytes-xxxxx', 'active', 1000, 1000)`).run(); @@ -332,4 +391,22 @@ describe('Block service (D1)', () => { response: { type: 'block.remove.result' }, }); }); + + it('rejects malformed pubkeys before deriving a member ID', async () => { + const service = new BlockService( + 'dm_policy', + servicePubkey, + db as unknown as D1Database, + ); + const requestId = 'block-remove-malformed'; + const result = await service.handle( + createEnvelope('block.remove', requestId, { target_pubkey: 'not-a-pubkey' }), + context(requestId), + ); + + expect(result.response).toMatchObject({ + type: 'system.error', + payload: { code: 'invalid_envelope' }, + }); + }); }); diff --git a/tests/opendating/unit/service-identities.test.ts b/tests/opendating/unit/service-identities.test.ts index 346d06d..4667753 100644 --- a/tests/opendating/unit/service-identities.test.ts +++ b/tests/opendating/unit/service-identities.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect, afterEach } from 'vitest'; import { + getServiceIdentitiesForCapabilities, LOADABLE_SERVICE_ROLES, loadServiceIdentitiesFromEnv, secretNameForRole, @@ -85,6 +86,15 @@ describe('loadServiceIdentitiesFromEnv', () => { expect(signers).toHaveLength(1); expect(signers[0].role).toBe('deletion'); }); + + it('advertises visibility updates on the profile identity', () => { + loadServiceIdentitiesFromEnv(envWithRoles(['profile'])); + const profile = getServiceIdentitiesForCapabilities().find( + (identity) => identity.role === 'profile', + ); + + expect(profile?.supportedTypes).toContain('visibility.update'); + }); }); describe('initMembershipKeys', () => { diff --git a/worker.js b/worker.js index 1cf2286..214bedf 100644 --- a/worker.js +++ b/worker.js @@ -4711,7 +4711,7 @@ function getSupportedTypesForRole(role) { case "system": return ["system.ping", "system.capabilities"]; case "profile": - return ["profile.create", "profile.update", "profile.get", "profile.pause", "profile.resume", "profile.delete"]; + return ["profile.create", "profile.update", "profile.get", "profile.pause", "profile.resume", "profile.delete", "visibility.update"]; case "discovery": return ["discovery.update_location", "discovery.get_candidates", "discovery.update_preferences"]; case "matcher": @@ -5940,18 +5940,6 @@ var init_service4 = __esm({ "This profile is no longer available." ) }; } - const grant = await session.prepare( - `SELECT grant_token FROM od_candidate_grants - WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? - AND (expires_at IS NULL OR expires_at > ?)` - ).bind(memberId, targetMemberId, candidateGrant, now).first(); - if (!grant) { - return { response: createErrorEnvelope( - request.request_id, - "invalid_candidate_grant", - "No valid grant found \u2014 this profile may no longer be available" - ) }; - } const likeQuota = await session.prepare( `SELECT daily_likes_sent, daily_reset_at FROM od_discovery_quotas WHERE member_id = ?` ).bind(memberId).first(); @@ -5964,6 +5952,18 @@ var init_service4 = __esm({ "Daily like limit reached" ) }; } + const consumedGrant = await session.prepare( + `DELETE FROM od_candidate_grants + WHERE viewer_id = ? AND candidate_id = ? AND grant_token = ? + AND (expires_at IS NULL OR expires_at > ?)` + ).bind(memberId, targetMemberId, candidateGrant, now).run(); + if ((consumedGrant.meta.changes ?? 0) !== 1) { + return { response: createErrorEnvelope( + request.request_id, + "invalid_candidate_grant", + "No valid grant found \u2014 this profile may no longer be available" + ) }; + } const iid = intentId(ctx.senderPubkey, targetPubkey, "like"); await session.prepare( `INSERT OR IGNORE INTO od_intents (id, from_member_id, to_member_id, intent_type, state, created_at, expires_at) @@ -5978,9 +5978,6 @@ var init_service4 = __esm({ daily_reset_at = CASE WHEN daily_reset_at < ? THEN ? ELSE daily_reset_at END, updated_at = ?` ).bind(memberId, newResetAt, now, now, newResetAt, now, now).run(); - await session.prepare( - `DELETE FROM od_candidate_grants WHERE viewer_id = ? AND candidate_id = ?` - ).bind(memberId, targetMemberId).run(); const reciprocal = await session.prepare( `SELECT id FROM od_intents WHERE from_member_id = ? AND to_member_id = ? AND intent_type = 'like' AND state = 'active'` @@ -6084,12 +6081,12 @@ var init_service5 = __esm({ async removeBlock(memberId, request) { const payload = request.payload; const targetPubkey = payload.target_pubkey; - if (typeof targetPubkey !== "string" || targetPubkey.length === 0) { + if (typeof targetPubkey !== "string" || !/^[0-9a-f]{64}$/i.test(targetPubkey)) { return { response: createErrorEnvelope( request.request_id, "invalid_envelope", - "Missing target_pubkey" + "Invalid target_pubkey" ) }; }