From 542211ec69201db80798b973c12ceff9774369d1 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 15 Nov 2024 09:20:11 +0100 Subject: [PATCH 01/83] chore: intro of local cloud tests chore: cloud now generated pre-signed-urls chore: fix signature chore: remove env version chore: remove console.log chore: now we have cloud-backend tests chore: the ng redirecting backend chore: everything except subscript --- .dockerignore | 2 +- .gitignore | 1 + package-cloud-backend.json | 22 ++ package.json | 18 +- pnpm-lock.yaml | 250 +++++++++---- setup.cloud.ts | 12 +- src/aws/gateway.ts | 2 +- src/cloud/backend/env.d.ts | 36 ++ src/cloud/backend/fp-meta-groups.ts | 46 +++ src/cloud/backend/server.ts | 159 ++++++++ src/cloud/backend/wrangler.toml | 24 ++ src/cloud/{ => client}/README.md | 0 src/cloud/client/cli-pre-signed-url.ts | 119 ++++++ src/cloud/client/gateway.ts | 342 +++++++++++++++++ src/cloud/{ => client}/index.ts | 26 +- src/cloud/cloud-gateway.test.ts | 139 ------- src/cloud/cloud.test.ts | 354 ++++++++++++++++++ src/cloud/gateway.ts | 339 ----------------- src/cloud/msg-types.ts | 107 ++++++ src/cloud/new-websocket.ts | 11 + src/connection-from-store.ts | 22 +- src/netlify/server.ts | 4 +- tests/Dockerfile.connect-cloud | 19 + .../app/netlify/edge-functions/fireproof.ts | 4 +- tests/start-cloud.sh | 13 + tests/waiton.ts | 8 +- tsconfig.json | 6 +- tsup.config.ts | 4 +- version-copy-package.ts | 147 ++++---- vitest.cloud.config.ts | 9 +- wrangler.toml | 5 - 31 files changed, 1600 insertions(+), 650 deletions(-) create mode 100644 package-cloud-backend.json create mode 100644 src/cloud/backend/env.d.ts create mode 100644 src/cloud/backend/fp-meta-groups.ts create mode 100644 src/cloud/backend/server.ts create mode 100644 src/cloud/backend/wrangler.toml rename src/cloud/{ => client}/README.md (100%) create mode 100644 src/cloud/client/cli-pre-signed-url.ts create mode 100644 src/cloud/client/gateway.ts rename src/cloud/{ => client}/index.ts (85%) delete mode 100644 src/cloud/cloud-gateway.test.ts create mode 100644 src/cloud/cloud.test.ts delete mode 100644 src/cloud/gateway.ts create mode 100644 src/cloud/msg-types.ts create mode 100644 src/cloud/new-websocket.ts create mode 100644 tests/Dockerfile.connect-cloud create mode 100644 tests/start-cloud.sh delete mode 100644 wrangler.toml diff --git a/.dockerignore b/.dockerignore index e11eebdf..3c8af178 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,2 @@ -**/node_modules/* **/.wrangler/* +**/node_modules/ diff --git a/.gitignore b/.gitignore index ef92d8f2..738c10ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Files +.wrangler .vscode .idea .DS_Store diff --git a/package-cloud-backend.json b/package-cloud-backend.json new file mode 100644 index 00000000..cd4c3be0 --- /dev/null +++ b/package-cloud-backend.json @@ -0,0 +1,22 @@ +{ + "name": "@fireproof/fireproof-cloud", + "version": "0.0.0", + "private": true, + "scripts": { + "deploy": "wrangler deploy --keep-vars", + "dev": "wrangler dev", + "start": "(env | grep -vi npm) > .dev.vars && wrangler dev --port 1968 --ip '::'", + "test": "vitest", + "cf-typegen": "wrangler types" + }, + "dependencies": { + "@adviser/cement": "from-main-package-json", + "@cloudflare/workers-types": "from-main-package-json", + "aws4fetch": "from-main-package-json", + "partyserver": "from-main-package-json", + "partysocket": "from-main-package-json", + "valibot": "from-main-package-json", + "wrangler": "from-main-package-json" + }, + "devDependencies": {} +} diff --git a/package.json b/package.json index 4e6e31a5..cef3b078 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build:tsup": "tsup", "pub:noop": "echo", "pub:aws": "tsx ./version-copy-package.ts ./dist/aws/package-aws.json && cp ./src/aws/README.md ./dist/aws/", - "pub:cloud": "tsx ./version-copy-package.ts ./dist/cloud/package-cloud.json && cp ./src/cloud/README.md ./dist/cloud/", + "pub:cloud": "tsx ./version-copy-package.ts ./dist/cloud/package-cloud.json && cp ./src/cloud/client/README.md ./dist/cloud/", "pub:netlify": "tsx ./version-copy-package.ts ./dist/netlify/package-netlify.json && cp ./src/netlify/server.ts ./dist/netlify/ && cp ./src/netlify/README.md ./dist/netlify/", "pub:s3": "tsx ./version-copy-package.ts ./dist/s3/package-s3.json && cp ./src/s3/README.md ./dist/s3/", "pub:partykit": "tsx ./version-copy-package.ts ./dist/partykit/package-partykit.json && cp ./src/partykit/server.ts ./dist/partykit/ && cp ./src/partykit/README.md ./dist/partykit/", @@ -33,8 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", + "pretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", + "posttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -94,11 +96,16 @@ "url": "https://github.com/fireproof-storage/connect/issues" }, "homepage": "https://github.com/fireproof-storage/connect#readme", + "peerDependencies": { + "@adviser/cement": "^0.2.38" + }, "dependencies": { "@adviser/cement": "^0.2.40", "@aws-sdk/client-s3": "^3.703.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", + "@cloudflare/workers-types": "^4.20241112.0", + "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", @@ -115,18 +122,27 @@ "@web3-storage/w3up-client": "^16.5.2", "assert": "^2.1.0", "better-sqlite3": "^11.6.0", + "aws4fetch": "^1.0.20", "cborg": "^4.2.6", + "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", + "dotenv": "^16.4.5", "events": "^3.3.0", + "hono": "^4.6.11", "idb-keyval": "^6.2.1", "is-deep-strict-equal-x": "^1.1.2", "multiformats": "^13.3.1", "node-sqlite3-wasm": "^0.8.28", "partykit": "^0.0.111", + "partyserver": "^0.0.57", "partysocket": "^1.0.2", "path": "^0.12.7", + "smol-toml": "^1.3.1", "util": "^0.12.5", + "valibot": "1.0.0-beta.7", + "vitest-pool-workers": "^0.0.1", "wait-on": "^8.0.1", + "wrangler": "^3.87.0", "ws": "^8.18.0" }, "exports": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 111f4e03..82f87dcf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,12 +14,18 @@ importers: '@aws-sdk/client-s3': specifier: ^3.703.0 version: 3.703.0 + '@cloudflare/workers-types': + specifier: ^4.20241112.0 + version: 4.20241205.0 '@fireproof/core': specifier: 0.19.116 version: 0.19.116(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 + '@hono/node-ws': + specifier: ^1.0.4 + version: 1.0.4(@hono/node-server@1.13.7(hono@4.6.13)) '@jspm/core': specifier: ^2.1.0 version: 2.1.0 @@ -65,18 +71,30 @@ importers: assert: specifier: ^2.1.0 version: 2.1.0 + aws4fetch: + specifier: ^1.0.20 + version: 1.0.20 better-sqlite3: specifier: ^11.6.0 version: 11.6.0 cborg: specifier: ^4.2.6 version: 4.2.6 + cmd-ts: + specifier: ^0.13.0 + version: 0.13.0 cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) + dotenv: + specifier: ^16.4.5 + version: 16.4.7 events: specifier: ^3.3.0 version: 3.3.0 + hono: + specifier: ^4.6.11 + version: 4.6.13 idb-keyval: specifier: ^6.2.1 version: 6.2.1 @@ -92,18 +110,33 @@ importers: partykit: specifier: ^0.0.111 version: 0.0.111 + partyserver: + specifier: ^0.0.57 + version: 0.0.57(@cloudflare/workers-types@4.20241205.0) partysocket: specifier: ^1.0.2 version: 1.0.2 path: specifier: ^0.12.7 version: 0.12.7 + smol-toml: + specifier: ^1.3.1 + version: 1.3.1 util: specifier: ^0.12.5 version: 0.12.5 + valibot: + specifier: 1.0.0-beta.7 + version: 1.0.0-beta.7(typescript@5.7.2) + vitest-pool-workers: + specifier: ^0.0.1 + version: 0.0.1 wait-on: specifier: ^8.0.1 version: 8.0.1 + wrangler: + specifier: ^3.87.0 + version: 3.91.0(@cloudflare/workers-types@4.20241205.0) ws: specifier: ^8.18.0 version: 8.18.0 @@ -173,10 +206,7 @@ importers: version: 5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.6 - version: 2.1.6(@types/node@22.10.1) - wrangler: - specifier: ^3.91.0 - version: 3.91.0 + version: 2.1.8(@types/node@22.10.1) zx: specifier: ^8.2.4 version: 8.2.4 @@ -421,6 +451,9 @@ packages: '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} + '@cloudflare/workers-types@4.20241205.0': + resolution: {integrity: sha512-pj1VKRHT/ScQbHOIMFODZaNAlJHQHdBSZXNIdr9ebJzwBff9Qz8VdqhbhggV7f+aUEh8WSbrsPIo4a+WtgjUvw==} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -1045,6 +1078,18 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@hono/node-server@1.13.7': + resolution: {integrity: sha512-kTfUMsoloVKtRA2fLiGSd9qBddmru9KadNyhJCwgKBxTiNkaAJEwkVN9KV/rS4HtmmNRtUh6P+YpmjRMl0d9vQ==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@hono/node-ws@1.0.4': + resolution: {integrity: sha512-0j1TMp67U5ym0CIlvPKcKtD0f2ZjaS/EnhOxFLs3bVfV+/4WInBE7hVe2x/7PLEsNIUK9+jVL8lPd28rzTAcZg==} + engines: {node: '>=18.14.1'} + peerDependencies: + '@hono/node-server': ^1.11.1 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1634,34 +1679,34 @@ packages: '@ucanto/validator@9.0.2': resolution: {integrity: sha512-LxhRbDMIoLt9LYHq/Rz1WCEH8AtmdsBTS/it28Ij/A3W0zyoSwUpAUxBtXaKRh/gpbxdWmjxX+nVfFJYL//b4g==} - '@vitest/expect@2.1.6': - resolution: {integrity: sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==} + '@vitest/expect@2.1.8': + resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==} - '@vitest/mocker@2.1.6': - resolution: {integrity: sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==} + '@vitest/mocker@2.1.8': + resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@2.1.6': - resolution: {integrity: sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==} + '@vitest/pretty-format@2.1.8': + resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} - '@vitest/runner@2.1.6': - resolution: {integrity: sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==} + '@vitest/runner@2.1.8': + resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==} - '@vitest/snapshot@2.1.6': - resolution: {integrity: sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==} + '@vitest/snapshot@2.1.8': + resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==} - '@vitest/spy@2.1.6': - resolution: {integrity: sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==} + '@vitest/spy@2.1.8': + resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==} - '@vitest/utils@2.1.6': - resolution: {integrity: sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==} + '@vitest/utils@2.1.8': + resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} '@web3-storage/access@20.1.0': resolution: {integrity: sha512-IY6ICPRWE8++2jxvy+LzAiFvwAOIHR8cu9eNt+VT5sAFE796o4ma7GSU0eXRCiShmV2n6iSWAwWRT6XD5zIqPA==} @@ -1832,6 +1877,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + aws4fetch@1.0.20: + resolution: {integrity: sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==} + axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} @@ -1953,6 +2001,9 @@ packages: resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} engines: {node: '>=18'} + cmd-ts@0.13.0: + resolution: {integrity: sha512-nsnxf6wNIM/JAS7T/x/1JmbEsjH0a8tezXqqpaL0O6+eV0/aDEnRxwjxpu0VzDdRcaC1ixGSbRlUuf/IU59I4g==} + collections-x@3.1.2: resolution: {integrity: sha512-UBj0YBtdMhubwaYnbfmCA8PHS79mbvCPYTw7YzUGhQzuyH3jf7Bc8RXQHqiZrTDtcl8+4oSbehFyu4jUH8PGag==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -2051,10 +2102,17 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dot-prop@7.2.0: resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2432,6 +2490,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hono@4.6.13: + resolution: {integrity: sha512-haV0gaMdSjy9URCRN9hxBPlqHa7fMm/T72kAImIxvw4eQLbNz1rgjN4hHElLJSieDiNuiIAXC//cC6YGz2KCbg==} + engines: {node: '>=16.9.0'} + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -2933,6 +2995,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.0.9: + resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} + engines: {node: ^18 || >=20} + hasBin: true + napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} @@ -3098,6 +3165,11 @@ packages: resolution: {integrity: sha512-pbUzJmulPTqZWgtH++eClnLlddTWS0RPKOAQyexYiSqGEg2/Ff84Ep0qWFqy+53wiz098DPFekRI375Qy2GsZw==} hasBin: true + partyserver@0.0.57: + resolution: {integrity: sha512-AVoNcslX+z8XjcESoNFC0WLYIH0WdxtnbaRKOHqHfzVOmEDvOlh/WUsWxeRY38f5v6aFH/gyUHNcxiW1KXlabw==} + peerDependencies: + '@cloudflare/workers-types': ^4.20240729.0 + partysocket@1.0.2: resolution: {integrity: sha512-rAFOUKImaq+VBk2B+2RTBsWEvlnarEP53nchoUHzpVs8V6fG2/estihOTslTQUWHVuHEKDL5k8htG8K3TngyFA==} @@ -3170,10 +3242,6 @@ packages: yaml: optional: true - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.4.49: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} @@ -3383,6 +3451,10 @@ packages: resolution: {integrity: sha512-omskIMJiH/urw+5mzLDYsV7yVFigo5LHTA24CHAFkh+HmZ53eQtfoeh4nkGI03JFCacAnL1uhNCyMlJTecXvzg==} engines: {node: '>=8.11.4', npm: 6.10.1} + smol-toml@1.3.1: + resolution: {integrity: sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==} + engines: {node: '>= 18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -3741,12 +3813,20 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + valibot@1.0.0-beta.7: + resolution: {integrity: sha512-8CsDu3tqyg7quEHMzCOYdQ/d9NlmVQKtd4AlFje6oJpvqo70EIZjSakKIeWltJyNAiUtdtLe0LAk4625gavoeQ==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + varint@6.0.0: resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - vite-node@2.1.6: - resolution: {integrity: sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite-node@2.1.8: + resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true vite-tsconfig-paths@5.1.3: @@ -3828,15 +3908,18 @@ packages: yaml: optional: true - vitest@2.1.6: - resolution: {integrity: sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest-pool-workers@0.0.1: + resolution: {integrity: sha512-h8kyBR+e3lh0b2iGg56MEFSlHiByRiLIBJwEifvkacrzh38sB16tsGn6cfuIYF23iH72hE+EHM3aqvt3sqdInA==} + + vitest@2.1.8: + resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 2.1.6 - '@vitest/ui': 2.1.6 + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.8 + '@vitest/ui': 2.1.8 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -4528,6 +4611,8 @@ snapshots: '@cloudflare/workers-types@4.20240718.0': {} + '@cloudflare/workers-types@4.20241205.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -4903,6 +4988,18 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 + '@hono/node-server@1.13.7(hono@4.6.13)': + dependencies: + hono: 4.6.13 + + '@hono/node-ws@1.0.4(@hono/node-server@1.13.7(hono@4.6.13))': + dependencies: + '@hono/node-server': 1.13.7(hono@4.6.13) + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -5653,43 +5750,43 @@ snapshots: '@ucanto/interface': 10.0.1 multiformats: 11.0.2 - '@vitest/expect@2.1.6': + '@vitest/expect@2.1.8': dependencies: - '@vitest/spy': 2.1.6 - '@vitest/utils': 2.1.6 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.6(vite@5.4.11(@types/node@22.10.1))': + '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.1))': dependencies: - '@vitest/spy': 2.1.6 + '@vitest/spy': 2.1.8 estree-walker: 3.0.3 magic-string: 0.30.12 optionalDependencies: vite: 5.4.11(@types/node@22.10.1) - '@vitest/pretty-format@2.1.6': + '@vitest/pretty-format@2.1.8': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@2.1.6': + '@vitest/runner@2.1.8': dependencies: - '@vitest/utils': 2.1.6 + '@vitest/utils': 2.1.8 pathe: 1.1.2 - '@vitest/snapshot@2.1.6': + '@vitest/snapshot@2.1.8': dependencies: - '@vitest/pretty-format': 2.1.6 + '@vitest/pretty-format': 2.1.8 magic-string: 0.30.12 pathe: 1.1.2 - '@vitest/spy@2.1.6': + '@vitest/spy@2.1.8': dependencies: tinyspy: 3.0.2 - '@vitest/utils@2.1.6': + '@vitest/utils@2.1.8': dependencies: - '@vitest/pretty-format': 2.1.6 + '@vitest/pretty-format': 2.1.8 loupe: 3.1.2 tinyrainbow: 1.2.0 @@ -5988,6 +6085,8 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + aws4fetch@1.0.20: {} + axios@1.7.7: dependencies: follow-redirects: 1.15.9 @@ -6135,6 +6234,15 @@ snapshots: is-wsl: 3.1.0 is64bit: 2.0.0 + cmd-ts@0.13.0: + dependencies: + chalk: 4.1.2 + debug: 4.3.7 + didyoumean: 1.2.2 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + collections-x@3.1.2: dependencies: array-for-each-x: 3.1.2 @@ -6252,10 +6360,14 @@ snapshots: detect-libc@2.0.3: {} + didyoumean@1.2.2: {} + dot-prop@7.2.0: dependencies: type-fest: 2.19.0 + dotenv@16.4.7: {} + eastasianwidth@0.2.0: {} electron-fetch@1.9.1: @@ -6756,6 +6868,8 @@ snapshots: dependencies: function-bind: 1.1.2 + hono@4.6.13: {} + human-signals@5.0.0: {} hyperdyperid@1.2.0: {} @@ -7340,6 +7454,8 @@ snapshots: nanoid@3.3.7: {} + nanoid@5.0.9: {} + napi-build-utils@1.0.2: {} native-fetch@3.0.0(node-fetch@2.7.0(encoding@0.1.13)): @@ -7545,6 +7661,11 @@ snapshots: - supports-color - utf-8-validate + partyserver@0.0.57(@cloudflare/workers-types@4.20241205.0): + dependencies: + '@cloudflare/workers-types': 4.20241205.0 + nanoid: 5.0.9 + partysocket@1.0.2: dependencies: event-target-shim: 6.0.2 @@ -7591,12 +7712,6 @@ snapshots: tsx: 4.19.2 yaml: 2.5.1 - postcss@8.4.47: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.4.49: dependencies: nanoid: 3.3.7 @@ -7850,6 +7965,8 @@ snapshots: simple-call-x: 1.0.3 util-pusher-x: 1.0.3 + smol-toml@1.3.1: {} + source-map-js@1.2.1: {} source-map@0.6.1: {} @@ -8228,9 +8345,13 @@ snapshots: uuid@9.0.1: {} + valibot@1.0.0-beta.7(typescript@5.7.2): + optionalDependencies: + typescript: 5.7.2 + varint@6.0.0: {} - vite-node@2.1.6(@types/node@22.10.1): + vite-node@2.1.8(@types/node@22.10.1): dependencies: cac: 6.7.14 debug: 4.3.7 @@ -8262,7 +8383,7 @@ snapshots: vite@5.4.11(@types/node@22.10.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 + postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: '@types/node': 22.10.1 @@ -8279,15 +8400,17 @@ snapshots: tsx: 4.19.2 yaml: 2.5.1 - vitest@2.1.6(@types/node@22.10.1): + vitest-pool-workers@0.0.1: {} + + vitest@2.1.8(@types/node@22.10.1): dependencies: - '@vitest/expect': 2.1.6 - '@vitest/mocker': 2.1.6(vite@5.4.11(@types/node@22.10.1)) - '@vitest/pretty-format': 2.1.6 - '@vitest/runner': 2.1.6 - '@vitest/snapshot': 2.1.6 - '@vitest/spy': 2.1.6 - '@vitest/utils': 2.1.6 + '@vitest/expect': 2.1.8 + '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.1)) + '@vitest/pretty-format': 2.1.8 + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 chai: 5.1.2 debug: 4.3.7 expect-type: 1.1.0 @@ -8299,7 +8422,7 @@ snapshots: tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.11(@types/node@22.10.1) - vite-node: 2.1.6(@types/node@22.10.1) + vite-node: 2.1.8(@types/node@22.10.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.10.1 @@ -8386,7 +8509,7 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241106.1 '@cloudflare/workerd-windows-64': 1.20241106.1 - wrangler@3.91.0: + wrangler@3.91.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 '@cloudflare/workers-shared': 0.9.0 @@ -8408,6 +8531,7 @@ snapshots: workerd: 1.20241106.1 xxhash-wasm: 1.0.2 optionalDependencies: + '@cloudflare/workers-types': 4.20241205.0 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil diff --git a/setup.cloud.ts b/setup.cloud.ts index 19721655..07650fdb 100644 --- a/setup.cloud.ts +++ b/setup.cloud.ts @@ -1,6 +1,14 @@ -import { registerFireproofCloudStoreProtocol } from "./src/cloud/gateway.ts"; +import { BuildURI } from "@adviser/cement"; +import { registerFireproofCloudStoreProtocol } from "./src/cloud/client/gateway.ts"; +import dotenv from "dotenv"; registerFireproofCloudStoreProtocol(); -process.env.FP_STORAGE_URL = "fireproof://cloud.fireproof.direct?getBaseUrl=https://storage.fireproof.direct/"; +dotenv.config(); + +process.env.FP_STORAGE_URL = BuildURI.from("fireproof://localhost:1968") + // .setParam("testMode", "true") + // .setParam("getBaseUrl", "https://storage.fireproof.direct/") + .setParam("protocol", "ws") + .toString(); process.env.FP_KEYBAG_URL = "file://./dist/kb-dir-fireproof-cloud?extractKey=_deprecated_internal_api"; diff --git a/src/aws/gateway.ts b/src/aws/gateway.ts index e997fb86..9cecadc8 100644 --- a/src/aws/gateway.ts +++ b/src/aws/gateway.ts @@ -137,7 +137,7 @@ export class AWSGateway implements bs.Gateway { return this.logger.Error().Any({ resp: done }).Msg("failed to upload meta").ResultError(); } - const doneJson = await done.json(); + const doneJson = await done.json<{ uploadURL?: string }>(); if (!doneJson.uploadURL) { return this.logger.Error().Url(fetchUrl).Msg("Upload URL not found in the response").ResultError(); } diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts new file mode 100644 index 00000000..03cdd64c --- /dev/null +++ b/src/cloud/backend/env.d.ts @@ -0,0 +1,36 @@ +// Generated by Wrangler on Fri Aug 16 2024 13:55:06 GMT+0200 (Central European Summer Time) +// by running `wrangler types` + +import type { DurableObjectNamespace } from "@cloudflare/workers-types"; +import { FPMetaGroups } from "./fp-meta-groups.js"; + +export interface Env { + // bucket: R2Bucket; + // kv_store: KVNamespace; + + ACCESS_KEY_ID: string; + ACCOUNT_ID: string; + BUCKET_NAME: string; + CLOUDFLARE_API_TOKEN: string; + EMAIL: string; + FIREPROOF_SERVICE_PRIVATE_KEY: string; + POSTMARK_TOKEN: string; + SECRET_ACCESS_KEY: string; + SERVICE_ID: string; + STORAGE_URL: string; + REGION: string; + VERSION: string; + FP_DEBUG: string; + FP_STACK: string; + FP_FORMAT: string; + TEST_DATE?: string; + + FP_META_GROUPS: DurableObjectNamespace; +} + +// declare module "cloudflare:test" { +// // ...or if you have an existing `Env` type... +// interface ProvidedEnv extends Env { +// readonly test: boolean; +// } +// } diff --git a/src/cloud/backend/fp-meta-groups.ts b/src/cloud/backend/fp-meta-groups.ts new file mode 100644 index 00000000..786c2fea --- /dev/null +++ b/src/cloud/backend/fp-meta-groups.ts @@ -0,0 +1,46 @@ + +import { DurableObject } from "cloudflare:workers"; +import { Env } from './env'; + +export class FPMetaGroups extends DurableObject { + currentlyConnectedWebSockets: number; + + constructor(ctx: DurableObjectState, env: Env) { + // This is reset whenever the constructor runs because + // regular WebSockets do not survive Durable Object resets. + // + // WebSockets accepted via the Hibernation API can survive + // a certain type of eviction, but we will not cover that here. + super(ctx, env); + this.currentlyConnectedWebSockets = 0; + } + + async fetch(request: Request): Promise { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `accept()` tells the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + server.accept(); + this.currentlyConnectedWebSockets += 1; + + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + server.addEventListener('message', (event: MessageEvent) => { + server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`); + }); + + // If the client closes the connection, the runtime will close the connection too. + server.addEventListener('close', (cls: CloseEvent) => { + this.currentlyConnectedWebSockets -= 1; + server.close(cls.code, "Durable Object is closing WebSocket"); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } + } diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts new file mode 100644 index 00000000..d19c9e3d --- /dev/null +++ b/src/cloud/backend/server.ts @@ -0,0 +1,159 @@ +import type { Env } from "./env"; +import { AwsClient } from "aws4fetch"; +import { BuildURI, exception2Result, LoggerImpl, Result, URI } from "@adviser/cement"; +import { buildErrorMsg, buildResSignedUrl, MsgBase, MsgIsError, ReqSignedUrl } from "../msg-types"; +import { Hono } from "hono"; +import { NotFoundError } from "@fireproof/core"; +import { upgradeWebSocket } from "hono/cloudflare-workers"; +import { a } from "@adviser/cement/txt-en-decoder-CZYJUju2"; + +const CORS = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET,POST,OPTIONS,PUT,DELETE", + "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours +}; + +function json(data: T, status = 200) { + return Response.json(data, { status, headers: CORS }); +} + +// function ok() { +// return json({ ok: true }); +// } + +// class FireProofWSockConnection extends DurableObject { +// } + + + + +const app = new Hono<{ Bindings: Env }>(); + +function getLogger(env: Env) { + return ( + new LoggerImpl() + .With() + .Module("Fireproof") + .SetDebug(env.FP_DEBUG) + // .SetFormatter((env.FP_FORMAT || "json") as LogFormatter) + .SetExposeStack(!!env.FP_STACK || false) + .Logger() + ); +} + +async function doMsg(decodeFn: () => Promise, env: Env): Promise { + const rReqMsg = await exception2Result(async () => (await decodeFn()) as MsgBase); + const logger = getLogger(env); + if (rReqMsg.isErr()) { + return buildErrorMsg(logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); + } + const reqMsg = rReqMsg.Ok(); + switch (reqMsg.type) { + case "reqSignedUrl": { + const rSignedUrl = await calculatePreSignedUrl(reqMsg as ReqSignedUrl, env); + if (rSignedUrl.isErr()) { + return buildErrorMsg(logger, reqMsg as ReqSignedUrl, rSignedUrl.Err()); + } + const resSignedUrl = buildResSignedUrl(reqMsg as ReqSignedUrl, rSignedUrl.Ok().toString()); + return resSignedUrl; + } + } + return buildErrorMsg(logger, { tid: "internal" } as ReqSignedUrl, new Error(`unknown msg.type=${reqMsg.type}`)); +} + +app.put("/get-signed-url", async (c) => { + c.env = c.env || {}; + const rRes = await doMsg(() => c.req.json(), c.env); + return json(rRes, MsgIsError(rRes) ? 422 : 200); +}); + +app.get("/ws", async (c) => { + const upgradeHeader = c.req.header('Upgrade'); + if (!upgradeHeader || upgradeHeader !== 'websocket') { + return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); + } + const id = c.env.FP_META_GROUPS.idFromName("foo"); + const stub = c.env.FP_META_GROUPS.get(id); + + return stub.fetch(c.req.raw) as unknown as Promise; + + + // upgradeWebSocket((c) => { + // return { + // onMessage(event, ws) { + // // console.log('Received message', event.data.toString()) + // doMsg(() => JSON.parse(event.data.toString()), c.env).then((msg) => { + // // console.log('Sending', msg) + // ws.send(JSON.stringify(msg)); + // }); + // }, + // onClose: () => { + // getLogger(c.env).Debug().Msg("Connection closed"); + // }, + // }; + // }) +}); + +app.notFound(async (c) => { + c.env = c.env || {}; + const logger = getLogger(c.env); + return json( + buildErrorMsg( + logger, + { + tid: "internal", + } as ReqSignedUrl, + new NotFoundError(`Notfound:${c.req.path}`) + ), + 404 + ); +}); +export default app; + +export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env): Promise> { + let store: string = req.params.store; + if (req.params.index?.length) { + store = `${store}-${req.params.index}`; + } + const expiresInSeconds = req.params.expires || 60 * 60; + + let suffix = ""; + switch (req.params.store) { + case "wal": + case "meta": + suffix = ".json"; + break; + default: + break; + } + + const opUrl = BuildURI.from(env.STORAGE_URL) + // .protocol(vals.protocol === "ws" ? "http:" : "https:") + .setParam("X-Amz-Expires", expiresInSeconds.toString()) + .setParam("tid", req.tid) + .appendRelative(req.params.tendantId) + .appendRelative(req.params.name) + .appendRelative(store) + .appendRelative(`${req.params.key}${suffix}`) + .URI(); + const a4f = new AwsClient({ + accessKeyId: env.ACCESS_KEY_ID, + secretAccessKey: env.SECRET_ACCESS_KEY, + region: env.REGION || "us-east-1", + service: "s3", + }); + const signedUrl = await a4f + .sign( + new Request(opUrl.toString(), { + method: req.params.method, + }), + { + aws: { + signQuery: true, + // datetime: env.TEST_DATE, + }, + } + ) + .then((res) => res.url); + return Result.Ok(URI.from(signedUrl)); +} diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml new file mode 100644 index 00000000..0ef0daa5 --- /dev/null +++ b/src/cloud/backend/wrangler.toml @@ -0,0 +1,24 @@ +name = "fireproof-cloud" +main = "server.ts" +compatibility_date = "2024-04-19" +# compatibility_flags = ["nodejs_compat"] +# upload_source_maps = true + +[[durable_objects.bindings]] +name = "FP_META_GROUPS" +class_name = "FPMetaGroups" + +[[migrations]] +tag = "v1" # Should be unique for each entry +new_classes = ["FPMetaGroups"] + +[observability] +enabled = true +head_sampling_rate = 1 + +[env.test.vars] +VERSION = "FP-MSG-1.0" +STORAGE_URL = "http://localhost:9000/testbucket" +ACCESS_KEY_ID = "minioadmin" +SECRET_ACCESS_KEY = "minioadmin" +# TEST_DATE = "20241121T225359Z" diff --git a/src/cloud/README.md b/src/cloud/client/README.md similarity index 100% rename from src/cloud/README.md rename to src/cloud/client/README.md diff --git a/src/cloud/client/cli-pre-signed-url.ts b/src/cloud/client/cli-pre-signed-url.ts new file mode 100644 index 00000000..b89e7185 --- /dev/null +++ b/src/cloud/client/cli-pre-signed-url.ts @@ -0,0 +1,119 @@ +// small tool to generate pre-signed url for cloud storage +// curl $(npx tsx src/cloud/client/cli-pre-signed-url.ts GET) +// curl -X PUT --data-binary @/etc/protocols $(npx tsx src/cloud/client/cli-pre-signed-url.ts) +import { BuildURI } from "@adviser/cement"; +import { mockSuperThis } from "../../../node_modules/@fireproof/core/tests/helpers.js"; +import { AwsClient } from "aws4fetch"; +import dotenv from "dotenv"; +import { command, run, option, oneOf, string } from "cmd-ts"; +// import * as t from 'io-ts'; + +(async () => { + dotenv.config(); + const sthis = mockSuperThis(); + const cmd = command({ + name: "cli-pre-signed-url", + description: "sign a url for cloud storage", + version: "1.0.0", + args: { + method: option({ + long: "method", + type: oneOf(["GET", "PUT", "POST", "DELETE"]), + defaultValue: () => "PUT", + defaultValueIsSerializable: true, + }), + accessKeyId: option({ + long: "accessKeyId", + type: string, + defaultValue: () => sthis.env.get("CF_ACCESS_KEY_ID") || "accessKeyId", + defaultValueIsSerializable: true, + }), + secretAccessKey: option({ + long: "secretAccessKey", + type: string, + defaultValue: () => sthis.env.get("CF_SECRET_ACCESS_KEY") || "secretAccessKey", + defaultValueIsSerializable: true, + }), + region: option({ + long: "region", + type: string, + defaultValue: () => "us-east-1", + defaultValueIsSerializable: true, + }), + service: option({ + long: "service", + type: string, + defaultValue: () => "s3", + defaultValueIsSerializable: true, + }), + storageURL: option({ + long: "storageURL", + type: string, + defaultValue: () => sthis.env.get("CF_STORAGE_URL") || "https://bucket.example.com/db/main", + defaultValueIsSerializable: true, + }), + path: option({ + long: "path", + type: string, + defaultValue: () => "db/main", + defaultValueIsSerializable: true, + }), + expires: option({ + long: "expires", + type: string, + defaultValue: () => "3600", + defaultValueIsSerializable: true, + }), + now: option({ + long: "now", + type: { + async from(str): Promise { + const decoded = new Date(str); + if (isNaN(decoded.getTime())) { + throw new Error("invalid date"); + } + // 2021-09-01T12:34:56Z + return decoded + .toISOString() + .replace(/[-:]/g, "") + .replace(/\.\d+Z$/, "Z"); + }, + displayName: "WithoutMillis", + description: "without milliseconds", + }, + // 2021-09-01T12:34:56Z + // 2024-11-17T07:21:10.958Z + defaultValue: () => + new Date() + .toISOString() + .replace(/[-:]/g, "") + .replace(/\.\d+Z$/, "Z"), + defaultValueIsSerializable: true, + }), + }, + handler: async (args) => { + const a4f = new AwsClient({ + accessKeyId: args.accessKeyId, + secretAccessKey: args.secretAccessKey, + region: args.region, + service: args.service, + }); + const buildUrl = BuildURI.from(args.storageURL).appendRelative(args.path).setParam("X-Amz-Expires", args.expires); + + // eslint-disable-next-line no-console + console.log( + await a4f + .sign(new Request(buildUrl.toString(), { method: args.method }), { + aws: { + signQuery: true, + datetime: args.now, + }, + }) + .then((res) => res.url) + ); + }, + }); + + await run(cmd, process.argv.slice(2)); + // eslint-disable-next-line no-console +})().catch(console.error); diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts new file mode 100644 index 00000000..f9fd5511 --- /dev/null +++ b/src/cloud/client/gateway.ts @@ -0,0 +1,342 @@ +// import PartySocket, { PartySocketOptions } from "partysocket"; +import { Result, URI, KeyedResolvOnce, exception2Result, Future } from "@adviser/cement"; +import { bs, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; +import { buildReqSignedUrl, ConnectionKey, FPStoreTypes, HttpMethods, MsgBase, ResSignedUrl } from "../msg-types.js"; +import { newWebSocket } from "../new-websocket.js"; + +const VERSION = "v0.1-fp-cloud"; + +interface Connection { + readonly ws: WebSocket; + readonly params: ConnectionKey; + request(msg: MsgBase): Promise>; +} + +export class ConnectionImpl implements Connection { + readonly ws: WebSocket; + readonly params: ConnectionKey; + readonly waitForTid = new Map>(); + constructor(logger: Logger, ws: WebSocket, params: ConnectionKey) { + this.ws = ws; + this.params = params; + ws.onmessage = async (event) => { + const rMsg = await exception2Result(() => JSON.parse(event.data)); + if (rMsg.isErr()) { + logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); + return; + } + const msg = rMsg.Ok() as MsgBase; + const future = this.waitForTid.get(msg.tid); + if (future) { + this.waitForTid.delete(msg.tid); + future.resolve(msg); + } + }; + } + async request(msg: MsgBase): Promise> { + const future = new Future(); + this.waitForTid.set(msg.tid, future); + this.ws.send(JSON.stringify(msg)); + // add timeout handling + return future + .asPromise() + .then((msg) => { + return Result.Ok(msg as T); + }) + .catch((err) => { + return Result.Err(err); + }); + } +} + +export class FireproofCloudGateway implements bs.Gateway { + readonly logger: Logger; + readonly sthis: SuperThis; + readonly id: string; + // party?: PartySocket; + url?: URI; + + readonly trackPuts = new Set(); + + constructor(sthis: SuperThis) { + this.sthis = sthis; + this.id = sthis.nextId().str; + this.logger = ensureLogger(sthis, "FireproofCloudGateway", { + url: () => this.url?.toString(), + this: this.id, + }); //.EnableLevel(Level.DEBUG); + // this.logger.Debug().Msg("constructor"); + } + + async buildUrl(baseUrl: URI, key: string): Promise> { + return Result.Ok(baseUrl.build().setParam("key", key).URI()); + } + + // pso?: PartySocketOptions; + async start(uri: URI): Promise> { + this.url = uri; + // this.logger.Debug().Msg("Starting FireproofCloudGateway"); + + await this.sthis.start(); + + const ret = uri.build().defParam("version", VERSION); + + const rName = uri.getParamResult("name"); + if (rName.isErr()) { + return this.logger.Error().Err(rName).Msg("name not found").ResultError(); + } + ret.defParam("protocol", "wss"); + this.url = ret.URI(); + return Result.Ok(this.url); + } + + async close(_uri: URI): Promise { + // console.log("close:gateway"); + // await this.ready(); + // this.logger.Debug().Msg("close"); + // this.party?.close(); + return Result.Ok(undefined); + } + + // fireproof://localhost:1999/?name=test-public-api&protocol=ws&store=meta + async getCloudConnection(uri: URI): Promise> { + const rParams = uri.getParamsResult({ + name: 0, + protocol: 0, + store: 0, + key: 0, + storekey: 0, + }); + if (rParams.isErr()) { + return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); + } + const params = rParams.Ok(); + const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); + const kb = await rt.kb.getKeyBag(this.sthis); + const rfingerprint = await kb.getNamedKey(dataKey); + if (rfingerprint.isErr()) { + return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); + } + const connectionKey = { + tendantId: uri.build().getParam("tendenId", rfingerprint.Ok().fingerPrint) as string, + name: params.name, + // protocol: params.protocol as ConnectionKey["protocol"], + } satisfies ConnectionKey; + return Result.Ok( + await wsSockets.get(pkKey(connectionKey)).once(async (cKey) => { + const wsUrl = uri + .build() + .protocol(params.protocol === "ws" ? "ws" : "wss") + .appendRelative("ws") + .URI(); + const ws = await newWebSocket(wsUrl); + const waitOpen = new Future(); + ws.onopen = () => { + this.logger.Debug().Url(wsUrl).Msg("ws open"); + waitOpen.resolve(); + }; + ws.onclose = () => { + wsSockets.unget(cKey); + this.logger.Debug().Url(wsUrl).Msg("ws close"); + }; + await waitOpen.asPromise(); + return new ConnectionImpl(this.logger, ws, connectionKey); + }) + ); + } + + async getResSignedUrl(uri: URI, method: HttpMethods): Promise> { + const rParams = uri.getParamsResult({ + store: 0, + key: 0, + }); + if (rParams.isErr()) { + return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); + } + const rConn = await this.getCloudConnection(uri); + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in getCloudConnection").ResultError(); + } + const conn = rConn.Ok(); + + const { store, key } = rParams.Ok(); + + return conn.request( + buildReqSignedUrl(this.sthis, { + params: { + ...conn.params, + store: store as FPStoreTypes, + key, + method, + }, + }) + ); + } + + async put(uri: URI, body: Uint8Array): Promise> { + const rResSignedUrl = await this.getResSignedUrl(uri, "PUT"); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { + signedUrl: uploadUrl, + params: { store }, + } = rResSignedUrl.Ok(); + if (store === "meta") { + const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); + if (bodyRes.isErr()) { + return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); + } + body = bodyRes.Ok(); + } + this.logger.Debug().Any("url", { uri, uploadUrl }).Msg("put-fetch-url"); + const rUpload = await exception2Result(async () => fetch(uploadUrl, { method: "PUT", body })); + if (rUpload.isErr()) { + return this.logger.Error().Url(uploadUrl, "uploadUrl").Err(rUpload).Msg("Error in put fetch").ResultError(); + } + if (!rUpload.Ok().ok) { + return this.logger.Error().Url(uploadUrl, "uploadUrl").Http(rUpload.Ok()).Msg("Error in put fetch").ResultError(); + } + if (uri.getParam("testMode")) { + this.trackPuts.add(uri.toString()); + } + return Result.Ok(undefined); + } + + private readonly subscriberCallbacks = new Set<(data: Uint8Array) => void>(); + + private notifySubscribers(data: Uint8Array): void { + console.log("notifySubscribers", data); + for (const callback of this.subscriberCallbacks) { + try { + callback(data); + } catch (error) { + this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); + } + } + } + async subscribe(uri: URI, callback: (meta: Uint8Array) => void): Promise { + const store = uri.getParam("store"); + if (store !== "meta") { + return Result.Err(new Error("store must be meta")); + } + this.subscriberCallbacks.add(callback); + + // only ask for meta url if we are connected + // if (this.party) { + // const rSignedUrl = await SignedUrl.from(this.sthis, this.logger, uri, "GET"); + // if (rSignedUrl.isErr()) { + // return this.logger.Error().Err(rSignedUrl).Msg("Error in getOpUrl").ResultError(); + // } + // await this.sendReqSignedMetaUrl(rSignedUrl.Ok()); + // } + return Result.Ok(() => { + this.subscriberCallbacks.delete(callback); + }); + } + + async get(uri: URI): Promise { + const rResSignedUrl = await this.getResSignedUrl(uri, "GET"); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { signedUrl: downloadUrl } = rResSignedUrl.Ok(); + this.logger.Debug().Url(downloadUrl).Msg("get-fetch-url"); + const rDownload = await exception2Result(async () => fetch(downloadUrl.toString(), { method: "GET" })); + if (rDownload.isErr()) { + return this.logger + .Error() + .Url(downloadUrl, "uploadUrl") + .Err(rDownload) + .Msg("Error in get downloadUrl") + .ResultError(); + } + const download = rDownload.Ok(); + if (!download.ok) { + if (download.status === 404) { + return Result.Err(new NotFoundError("Not found")); + } + return this.logger.Error().Url(downloadUrl, "uploadUrl").Err(rDownload).Msg("Error in get fetch").ResultError(); + } + return Result.Ok(new Uint8Array(await download.arrayBuffer())); + } + + async delete(uri: URI): Promise { + const rResSignedUrl = await this.getResSignedUrl(uri, "DELETE"); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { signedUrl: deleteUrl } = rResSignedUrl.Ok(); + this.logger.Debug().Url(deleteUrl).Msg("delete-fetch-url"); + const rDelete = await exception2Result(async () => fetch(deleteUrl.toString(), { method: "DELETE" })); + if (rDelete.isErr()) { + return this.logger.Error().Url(deleteUrl, "uploadUrl").Err(rDelete).Msg("Error in get deleteURL").ResultError(); + } + const download = rDelete.Ok(); + if (!download.ok) { + if (download.status === 404) { + return Result.Err(new NotFoundError("Not found")); + } + return this.logger.Error().Url(deleteUrl, "uploadUrl").Err(rDelete).Msg("Error in del fetch").ResultError(); + } + this.trackPuts.delete(uri.toString()); + return Result.Ok(undefined); + } + + async destroy(_uri: URI): Promise> { + // await this.ready(); + for (const key of this.trackPuts) { + await this.delete(URI.from(key)); + } + return Result.Ok(undefined); + } +} + +const wsSockets = new KeyedResolvOnce(); + +function pkKey(set?: ConnectionKey): string { + const ret = JSON.stringify( + Object.entries(set || {}) + .sort(([a], [b]) => a.localeCompare(b)) + .filter(([k]) => k !== "id") + .map(([k, v]) => ({ [k]: v })) + ); + return ret; +} + +export class FireproofCloudTestStore implements bs.TestGateway { + readonly logger: Logger; + readonly sthis: SuperThis; + readonly gateway: bs.Gateway; + constructor(gw: bs.Gateway, sthis: SuperThis) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "FireproofCloudTestStore"); + this.gateway = gw; + } + async get(uri: URI, key: string): Promise { + const url = uri.build().setParam("key", key).URI(); + const dbFile = this.sthis.pathOps.join(rt.getPath(url, this.sthis), rt.getFileName(url, this.sthis)); + this.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get"); + const buffer = await this.gateway.get(url); + this.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got"); + return buffer.Ok(); + } +} + +const onceRegisterFireproofCloudStoreProtocol = new KeyedResolvOnce<() => void>(); +export function registerFireproofCloudStoreProtocol(protocol = "fireproof:", overrideBaseURL?: string) { + return onceRegisterFireproofCloudStoreProtocol.get(protocol).once(() => { + URI.protocolHasHostpart(protocol); + return bs.registerStoreProtocol({ + protocol, + overrideBaseURL, + gateway: async (sthis) => { + return new FireproofCloudGateway(sthis); + }, + test: async (sthis: SuperThis) => { + const gateway = new FireproofCloudGateway(sthis); + return new FireproofCloudTestStore(gateway, sthis); + }, + }); + }); +} diff --git a/src/cloud/index.ts b/src/cloud/client/index.ts similarity index 85% rename from src/cloud/index.ts rename to src/cloud/client/index.ts index aa9081bf..191587c6 100644 --- a/src/cloud/index.ts +++ b/src/cloud/client/index.ts @@ -26,11 +26,11 @@ const SYNC_DB_NAME = "fp_sync"; // process.env.FP_KEYBAG_URL = "file://./dist/kb-dir-fireproof?fs=mem"; // } -if (!runtimeFn().isBrowser) { - const url = BuildURI.from(process.env.FP_KEYBAG_URL || "file://./dist/kb-dir-FireproofCloud"); - url.setParam("extractKey", "_deprecated_internal_api"); - process.env.FP_KEYBAG_URL = url.toString(); -} +// if (!runtimeFn().isBrowser) { +// const url = BuildURI.from(process.env.FP_KEYBAG_URL || rt.kb.defaultKeyBagUrl()); +// url.setParam("extractKey", "_deprecated_internal_api"); +// process.env.FP_KEYBAG_URL = url.toString(); +// } registerFireproofCloudStoreProtocol(); @@ -45,19 +45,21 @@ export const rawConnect: ConnectFunction = ( throw new Error("dbName is required"); } const urlObj = BuildURI.from(url); + urlObj.protocol("fireproof:"); const existingName = urlObj.getParam("name"); urlObj.defParam("name", remoteDbName || existingName || dbName); urlObj.defParam("localName", dbName); urlObj.defParam("storekey", `@${dbName}:data@`); urlObj.defParam("getBaseUrl", "https://storage.fireproof.direct/"); - const fpUrl = urlObj - .toString() - .replace(/^http:\/\//, "fireproof://") - .replace(/^https:\/\//, "fireproof://"); - // console.log("Config URL: " + fpUrl); - return connectionCache.get(fpUrl).once(() => { + // const fpUrl = urlObj + // .toString() + // .replace(/^http:\/\//, "fireproof://") + // .replace(/^https:\/\//, "fireproof://"); + // eslint-disable-next-line no-console + console.log("Config URL: " + urlObj.toString()); + return connectionCache.get(urlObj.toString()).once(() => { makeKeyBagUrlExtractable(sthis); - const connection = connectionFactory(sthis, fpUrl); + const connection = connectionFactory(sthis, urlObj); connection.connect_X(blockstore); return connection; }); diff --git a/src/cloud/cloud-gateway.test.ts b/src/cloud/cloud-gateway.test.ts deleted file mode 100644 index 5cfb0de5..00000000 --- a/src/cloud/cloud-gateway.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { fireproof, Database, bs } from "@fireproof/core"; -import { registerFireproofCloudStoreProtocol } from "./gateway.js"; -import { describe, it, expect, beforeAll, afterAll } from "vitest"; -import { URI } from "@adviser/cement"; -import { smokeDB } from "../../tests/helper.js"; -import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; - -// has to leave -interface ExtendedGateway extends bs.Gateway { - headerSize: number; - subscribe?: (url: URI, callback: (meta: Uint8Array) => void) => Promise; // Changed VoidResult to UnsubscribeResult -} - -// has to leave -interface ExtendedStore { - gateway: ExtendedGateway; - _url: URI; - name: string; -} - -describe("FireproofCloudGateway", () => { - let db: Database; - let unregister: () => void; - const sthis = mockSuperThis(); - - beforeAll(() => { - unregister = registerFireproofCloudStoreProtocol("fireproof:"); - }); - - beforeEach(() => { - const config = { - store: { - stores: { - base: process.env.FP_STORAGE_URL || "fireproof://localhost:1999", - }, - }, - }; - const name = "fireproof-cloud-test-db-" + Math.random().toString(36).substring(7); - db = fireproof(name, config); - }); - - afterEach(() => { - // Clear the database before each test - if (db) { - db.destroy(); - } - }); - - afterAll(() => { - unregister(); - }); - - it("env setup is ok", () => { - // expect(process.env.FP_STORAGE_URL).toMatch(/fireproof:\/\/localhost:1999/); - }); - - it("should have loader and options", () => { - const loader = db.blockstore.loader; - expect(loader).toBeDefined(); - if (!loader) { - throw new Error("Loader is not defined"); - } - expect(loader.ebOpts).toBeDefined(); - expect(loader.ebOpts.store).toBeDefined(); - expect(loader.ebOpts.store.stores).toBeDefined(); - if (!loader.ebOpts.store.stores) { - throw new Error("Loader stores is not defined"); - } - if (!loader.ebOpts.store.stores.base) { - throw new Error("Loader stores.base is not defined"); - } - - const baseUrl = URI.from(loader.ebOpts.store.stores.base); - expect(baseUrl.protocol).toBe("fireproof:"); - // expect(baseUrl.hostname).toBe("localhost"); - // expect(baseUrl.port || "").toBe("1999"); - }); - - it("should initialize and perform basic operations", async () => { - const docs = await smokeDB(db); - - // // get a new db instance - // db = new Database(name, config); - - // Test update operation - const updateDoc = await db.get<{ content: string }>(docs[0]._id); - updateDoc.content = "Updated content"; - const updateResult = await db.put(updateDoc); - expect(updateResult.id).toBe(updateDoc._id); - - const updatedDoc = await db.get<{ content: string }>(updateDoc._id); - expect(updatedDoc.content).toBe("Updated content"); - - // Test delete operation - await db.del(updateDoc._id); - try { - await db.get(updateDoc._id); - throw new Error("Document should have been deleted"); - } catch (e) { - const error = e as Error; - expect(error.message).toContain("Not found"); - } - - // Clean up - await db.destroy(); - }); - - it("should subscribe to changes", async () => { - // Extract stores from the loader - const metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore; - - const metaGateway = metaStore?.gateway; - - const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main"); - await metaGateway?.start(metaStore?._url); - - let didCall = false; - - if (metaGateway.subscribe) { - let resolve: () => void; - const p = new Promise((r) => { - resolve = r; - }); - - const metaSubscribeResult = await metaGateway?.subscribe?.(metaUrl?.Ok(), async (data: Uint8Array) => { - const decodedData = sthis.txt.decode(data); - expect(decodedData).toContain("parents"); - didCall = true; - resolve(); - }); - expect(metaSubscribeResult?.Ok()).toBeTruthy(); - const ok = await db.put({ _id: "key1", hello: "world1" }); - expect(ok).toBeTruthy(); - expect(ok.id).toBe("key1"); - await p; - expect(didCall).toBeTruthy(); - } - }); -}); diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts new file mode 100644 index 00000000..28900b0f --- /dev/null +++ b/src/cloud/cloud.test.ts @@ -0,0 +1,354 @@ +// import { env } from "cloudflare:test" +import { BuildURI, Future, URI } from "@adviser/cement"; +import { ReqSignedUrl, ResSignedUrl } from "./msg-types"; +import { Env } from "./backend/env"; +import { $ } from "zx"; +import fs from "fs/promises"; +import * as toml from "smol-toml"; +import { bs, Database, fireproof } from "@fireproof/core"; +import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; +import { AwsClient } from "aws4fetch"; +import { smokeDB } from "../../tests/helper"; +import { registerFireproofCloudStoreProtocol } from "./client/gateway"; +import { calculatePreSignedUrl } from "./backend/server"; +import { newWebSocket } from "./new-websocket"; +// import { env, createExecutionContext, waitOnExecutionContext } from "cloudflare:test"; + +// const IncomingRequest = Request//; + +// const env: Env = { +// VERSION: "Test", +// STORAGE_URL: "http://localhost:8080", +// ACCESS_KEY_ID: "accessKeyId", +// SECRET_ACCESS_KEY: "secretAccessKey", +// TEST_DATE: "20241121T225359Z", +// } as Env; + +function testReqSignedUrl(tid = "test") { + return { + tid: tid, + type: "reqSignedUrl", + params: { + // protocol: "ws", + path: "/hallo", + name: "test-name", + method: "GET", + tendantId: "tenantId", + store: "wal", + key: "main", + }, + version: "test", + } satisfies ReqSignedUrl; +} + +async function testResSignedUrl(env: Env, tid = "test"): Promise { + const req = testReqSignedUrl(tid); + const rSignedUrl = await calculatePreSignedUrl(req, env); + if (rSignedUrl.isErr()) { + throw rSignedUrl.Err(); + } + return { + params: req.params, + signedUrl: rSignedUrl.Ok().toString(), + // `http://localhost:8080/tenantId/test-name/wal/main.json?tid=${tid}&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=accessKeyId%2F20241121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20241121T225359Z&X-Amz-Expires=86400&X-Amz-Signature=f52d5ecfbb6be93210dd57cb49ba1e426a8aee24a0738aedb636ae5722fcdded&X-Amz-SignedHeaders=host`, + tid: tid, + type: "resSignedUrl", + version: env.VERSION, + } satisfies ResSignedUrl; +} + +describe("CloudBackendTest", () => { + const sthis = mockSuperThis(); + let env: Env; + let pid: number; + const port = ~~(1024 + Math.random() * (0x10000 - 1024)); + const wrangler = BuildURI.from("http://localhost") + .port("" + port) + .URI(); + async function cfFetch(relative: string, init: RequestInit) { + return fetch(wrangler.build().appendRelative(relative).asURL(), init); + } + beforeAll(async () => { + const tomlFile = "src/cloud/backend/wrangler.toml"; + const tomeStr = await fs.readFile(tomlFile, "utf-8"); + const wranglerFile = toml.parse(tomeStr) as unknown as { + env: { test: { vars: Env } }; + }; + env = wranglerFile.env.test.vars; + // $.verbose = true + const runningWrangler = $` + wrangler dev -c ${tomlFile} --port ${port} --env test --no-show-interactive-dev-session & + waitPid=$! + echo "PID:$waitPid" + wait $waitPid`; + const waitReady = new Future(); + runningWrangler.stdout.on("data", (chunk) => { + // console.log(">>", chunk.toString()) + const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; + if (mightPid) { + pid = +mightPid; + } + if (chunk.includes("Ready on http")) { + waitReady.resolve(true); + } + if ($.verbose) { + // eslint-disable-next-line no-console + console.log(">>", chunk.toString()); + } + }); + runningWrangler.stderr.on("data", (chunk) => { + if ($.verbose) { + // eslint-disable-next-line no-console + console.error("!!", chunk.toString()); + } + }); + await waitReady.asPromise(); + // await f.asPromise() + // wrangler dev -c src/cloud/backend/wrangler.toml --port 4711 --env test + }); + + afterAll(async () => { + // console.log("kill", runningWrangler.pid, runningWrangler) + // process.kill(runningWrangler.pid) + // process.stdin.write(Array(4).fill("x\n\r").join("")) + if (pid) process.kill(pid); + }); + + describe("raw tests", () => { + it("return 404", async () => { + const res = await cfFetch("/posts", {}); + expect(res.status).toBe(404); + expect(await res.json()).toEqual({ + message: "Notfound:/posts", + tid: "internal", + type: "error", + version: env.VERSION, + }); + }); + it("return 422 invalid json", async () => { + const res = await cfFetch("/get-signed-url", { method: "PUT" }); + expect(res.status).toBe(422); + expect(await res.json()).toEqual({ + message: "Unexpected end of JSON input", + tid: "internal", + type: "error", + version: env.VERSION, + }); + }); + + it("return 422 illegal msg", async () => { + const res = await cfFetch("/get-signed-url", { + method: "PUT", + body: JSON.stringify({ + bucket: "test", + key: "test", + }), + }); + expect(res.status).toBe(422); + expect(await res.json()).toEqual({ + message: "unknown msg.type=undefined", + tid: "internal", + type: "error", + version: env.VERSION, + }); + }); + + it("return 200 msg", async () => { + const res = await cfFetch("/get-signed-url", { + method: "PUT", + body: JSON.stringify(testReqSignedUrl()), + }); + expect(res.status).toBe(200); + expect(await res.json()).toEqual(await testResSignedUrl(env)); + }); + it("use websockets SignedUrl", async () => { + await Promise.all( + Array(100) + .fill(null) + .map(async () => { + const url = wrangler.build().appendRelative("/ws").protocol("ws:"); + const so = await newWebSocket(url); + const done = new Future(); + const tid = `test-${Math.random()}`; + so.onopen = () => { + so.send(JSON.stringify(testReqSignedUrl(tid))); + }; + so.onmessage = async (msg) => { + try { + expect(JSON.parse(msg.data.toString())).toEqual(await testResSignedUrl(env, tid)); + done.resolve(true); + } catch (err) { + done.reject(err); + } + }; + so.onerror = (ev) => { + assert.fail(`WebSocket error: ${ev}`); + }; + return done.asPromise().then(() => so.close()); + }) + ); + }); + }); + + describe("FireproofCloudGateway", () => { + let db: Database; + let unregister: () => void; + interface ExtendedGateway extends bs.Gateway { + headerSize: number; + subscribe?: (url: URI, callback: (meta: Uint8Array) => void) => Promise; // Changed VoidResult to UnsubscribeResult + } + + // has to leave + interface ExtendedStore { + gateway: ExtendedGateway; + _url: URI; + name: string; + } + + beforeAll(() => { + unregister = registerFireproofCloudStoreProtocol("fireproof:"); + }); + + beforeEach(() => { + const config = { + store: { + stores: { + base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").asURL(), + // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", + }, + }, + }; + const name = "fireproof-cloud-test-db-" + sthis.nextId().str; + db = fireproof(name, config); + }); + + afterEach(async () => { + // Clear the database before each test + if (db) { + await db.close(); + await db.destroy(); + } + }); + + afterAll(() => { + unregister(); + }); + + // it("env setup is ok", () => { + // // expect(process.env.FP_STORAGE_URL).toMatch(/fireproof:\/\/localhost:1999/); + // }); + + it("should have loader and options", () => { + const loader = db.blockstore.loader; + expect(loader).toBeDefined(); + if (!loader) { + throw new Error("Loader is not defined"); + } + expect(loader.ebOpts).toBeDefined(); + expect(loader.ebOpts.store).toBeDefined(); + expect(loader.ebOpts.store.stores).toBeDefined(); + if (!loader.ebOpts.store.stores) { + throw new Error("Loader stores is not defined"); + } + if (!loader.ebOpts.store.stores.base) { + throw new Error("Loader stores.base is not defined"); + } + + const baseUrl = URI.from(loader.ebOpts.store.stores.base); + expect(baseUrl.protocol).toBe("fireproof:"); + // expect(baseUrl.hostname).toBe("localhost"); + // expect(baseUrl.port || "").toBe("1999"); + }); + + it("should initialize and perform basic operations", async () => { + const docs = await smokeDB(db); + + // // get a new db instance + // db = new Database(name, config); + + // Test update operation + const updateDoc = await db.get<{ content: string }>(docs[0]._id); + updateDoc.content = "Updated content"; + const updateResult = await db.put(updateDoc); + expect(updateResult.id).toBe(updateDoc._id); + + const updatedDoc = await db.get<{ content: string }>(updateDoc._id); + expect(updatedDoc.content).toBe("Updated content"); + + // Test delete operation + await db.del(updateDoc._id); + try { + await db.get(updateDoc._id); + throw new Error("Document should have been deleted"); + } catch (e) { + const error = e as Error; + expect(error.message).toContain("Not found"); + } + }); + + it("should subscribe to changes", async () => { + // Extract stores from the loader + const metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore; + + const metaGateway = metaStore?.gateway; + + const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main"); + await metaGateway?.start(metaStore?._url); + + let didCall = false; + + if (metaGateway.subscribe) { + const future = new Future(); + + const metaSubscribeResult = await metaGateway.subscribe(metaUrl?.Ok(), async (data: Uint8Array) => { + const decodedData = sthis.txt.decode(data); + expect(decodedData).toContain("parents"); + didCall = true; + future.resolve(); + }); + expect(metaSubscribeResult.isOk()).toBeTruthy(); + const ok = await db.put({ _id: "key1", hello: "world1" }); + expect(ok).toBeTruthy(); + expect(ok.id).toBe("key1"); + await future.asPromise(); + expect(didCall).toBeTruthy(); + metaSubscribeResult.Ok()(); + } + }); + }); + describe("AwsClient R2", () => { + it("make presigned url", async () => { + const sthis = mockSuperThis(); + const a4f = new AwsClient({ + accessKeyId: sthis.env.get("CF_ACCESS_KEY_ID") || "accessKeyId", + secretAccessKey: sthis.env.get("CF_SECRET_ACCESS_KEY") || "secretAccessKey", + region: "us-east-1", + service: "s3", + }); + const buildUrl = BuildURI.from(sthis.env.get("CF_STORAGE_URL") || "https://bucket.example.com/db/main") + .appendRelative("db/main") + .setParam("X-Amz-Expires", "22"); + const signedUrl = await a4f + .sign(new Request(buildUrl.toString(), { method: "PUT" }), { + aws: { + signQuery: true, + datetime: "2021-09-01T12:34:56Z", + }, + }) + .then((res) => res.url); + expect(URI.from(signedUrl).asObj()).toEqual( + buildUrl + .setParam("X-Amz-Date", "2021-09-01T12:34:56Z") + .setParam("X-Amz-Algorithm", "AWS4-HMAC-SHA256") + .setParam("X-Amz-Credential", `${a4f.accessKeyId}/2021-09-/${a4f.region}/${a4f.service}/aws4_request`) + .setParam("X-Amz-SignedHeaders", "host") + .setParam( + "X-Amz-Signature", + sthis.env.get("CF_PRESIGNED_SIGNATURE") || + "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + ) + .asObj() + ); + }); + }); +}); diff --git a/src/cloud/gateway.ts b/src/cloud/gateway.ts deleted file mode 100644 index 8a8a15b1..00000000 --- a/src/cloud/gateway.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { PartySocket, PartySocketOptions } from "partysocket"; -import { Result, URI, BuildURI, KeyedResolvOnce, runtimeFn, exception2Result } from "@adviser/cement"; -import { bs, ensureLogger, getStore, Logger, rt, SuperThis } from "@fireproof/core"; - -export class FireproofCloudGateway implements bs.Gateway { - readonly logger: Logger; - readonly sthis: SuperThis; - readonly id: string; - party?: PartySocket; - url?: URI; - - constructor(sthis: SuperThis) { - this.sthis = sthis; - this.id = sthis.nextId().str; - this.logger = ensureLogger(sthis, "FireproofCloudGateway", { - url: () => this.url?.toString(), - this: this.id, - }); //.EnableLevel(Level.DEBUG); - this.logger.Debug().Msg("constructor"); - } - - async buildUrl(baseUrl: URI, key: string): Promise> { - return Result.Ok(baseUrl.build().setParam("key", key).URI()); - } - - pso?: PartySocketOptions; - async start(uri: URI): Promise> { - this.logger.Debug().Msg("Starting FireproofCloudGateway with URI: " + uri.toString()); - - await this.sthis.start(); - - this.url = uri; - const ret = uri.build().defParam("version", "v0.1-fireproof-cloud"); - - const rName = uri.getParamResult("name"); - if (rName.isErr()) { - return this.logger.Error().Err(rName).Msg("name not found").ResultError(); - } - let dbName = rName.Ok(); - if (this.url.hasParam("index")) { - dbName = dbName + "-idx"; - } - ret.defParam("party", "fireproof"); - ret.defParam("protocol", "wss"); - // const party = uri.getParam("party") || "fireproof"; - // const proto = uri.getParam("protocol") || "wss"; - let possibleUndef: { - protocol: "wss" | "ws" | undefined; - protocols?: string[]; - prefix?: string; - } = { protocol: ret.getParam("protocol") as "wss" | "ws" }; - - const protocolsStr = uri.getParam("protocols"); - if (protocolsStr) { - const ps = protocolsStr - .split(",") - .map((x) => x.trim()) - .filter((x) => x); - if (ps.length > 0) { - possibleUndef = { ...possibleUndef, protocols: ps }; - } - } - const prefixStr = uri.getParam("prefix"); - if (prefixStr) { - possibleUndef = { ...possibleUndef, prefix: prefixStr }; - } - - const query: PartySocketOptions["query"] = {}; - - const partySockOpts: PartySocketOptions = { - id: this.id, - host: this.url.host, - room: dbName, - party: ret.getParam("party"), - ...possibleUndef, - query, - path: this.url.pathname.replace(/^\//, ""), - }; - - if (runtimeFn().isNodeIsh) { - const { WebSocket } = await import("ws"); - partySockOpts.WebSocket = WebSocket; - } - this.pso = partySockOpts; - - return Result.Ok(ret.URI()); - } - - async ready(): Promise { - this.logger.Debug().Msg("ready"); - } - - async connectFireproofCloud() { - const pkKeyThis = pkKey(this.pso); - return pkSockets.get(pkKeyThis).once(async () => { - if (!this.pso) { - throw new Error("Party socket options not found"); - } - this.party = new PartySocket(this.pso); - let exposedResolve: (value: boolean) => void; - const openFn = () => { - this.logger.Debug().Msg("party open"); - this.party?.addEventListener("message", async (event: MessageEvent) => { - this.logger.Debug().Msg(`got message: ${event.data}`); - const mbin = this.sthis.txt.encode(event.data); - this.notifySubscribers(mbin); - }); - exposedResolve(true); - }; - return await new Promise((resolve) => { - exposedResolve = resolve; - this.party?.addEventListener("open", openFn); - }); - }); - } - - async close(): Promise { - await this.ready(); - this.logger.Debug().Msg("close"); - this.party?.close(); - return Result.Ok(undefined); - } - - async put(uri: URI, body: Uint8Array): Promise> { - await this.ready(); - const { store } = getStore(uri, this.sthis, (...args) => args.join("/")); - if (store === "meta") { - const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); - if (bodyRes.isErr()) { - this.logger.Error().Err(bodyRes.Err()).Msg("Error in addCryptoKeyToGatewayMetaPayload"); - throw bodyRes.Err(); - } - body = bodyRes.Ok(); - } - const rkey = uri.getParamResult("key"); - if (rkey.isErr()) return Result.Err(rkey.Err()); - const key = rkey.Ok(); - if (store === "meta") { - const uploadUrl = pkMetaURL(uri, key); - return exception2Result(async () => { - const response = await fetch(uploadUrl.asURL(), { method: "PUT", body: body }); - if (response.status === 404) { - throw this.logger.Error().Url(uploadUrl).Msg(`Failure in uploading ${store}!`).AsError(); - } - }); - } else { - const uploadUrl = pkURL(uri, key, "car"); - return exception2Result(async () => { - const response = await fetch(uploadUrl.asURL(), { method: "PUT" }); - this.logger - .Debug() - .Url(uploadUrl) - .Uint64("status", response.status) - .Str("status-text", response.statusText) - .Msg("put"); - if (response.status === 404) { - throw this.logger.Error().Url(uploadUrl).Msg(`Failure in uploading ${store}!`).AsError(); - } - const url = (await response.json()).url; - this.logger.Debug().Url(url).Msg("put"); - const uploadResponse = await fetch(url, { method: "PUT", body: body }); - if (uploadResponse.status === 404) { - throw this.logger.Error().Url(uploadUrl).Msg(`Failure in uploading ${store}!`).AsError(); - } - }); - } - } - - private readonly subscriberCallbacks = new Set<(data: Uint8Array) => void>(); - - private notifySubscribers(data: Uint8Array): void { - for (const callback of this.subscriberCallbacks) { - try { - callback(data); - } catch (error) { - this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); - } - } - } - async subscribe(uri: URI, callback: (meta: Uint8Array) => void): Promise { - await this.ready(); - await this.connectFireproofCloud(); - - const store = uri.getParam("store"); - if (store !== "meta") { - return Result.Err(new Error("store must be meta")); - } - - this.subscriberCallbacks.add(callback); - - return Result.Ok(() => { - this.subscriberCallbacks.delete(callback); - }); - } - - async get(uri: URI): Promise { - await this.ready(); - return exception2Result(async () => { - const { store } = getStore(uri, this.sthis, (...args) => args.join("/")); - const key = uri.getParam("key"); - if (!key) throw new Error("key not found"); - let downloadUrl; - this.logger.Debug().Str("store", store).Str("key", key).Msg("get"); - switch (store) { - case "meta": - downloadUrl = pkMetaURL(uri, key); - break; - case "data": - downloadUrl = pkCarGetURL(uri, key); - break; - default: - throw new Error(`Unsupported store: ${store}`); - } - const response = await fetch(downloadUrl.toString(), { method: "GET" }); - if (response.status === 404) { - throw new Error(`Failure in downloading ${store}!`); - } - const body = new Uint8Array(await response.arrayBuffer()); - if (store === "meta") { - const resKeyInfo = await bs.setCryptoKeyFromGatewayMetaPayload(uri, this.sthis, body); - if (resKeyInfo.isErr()) { - this.logger - .Error() - .Url(uri) - .Err(resKeyInfo) - .Any("body", body) - .Msg("Error in setCryptoKeyFromGatewayMetaPayload"); - throw resKeyInfo.Err(); - } - } - return body; - }); - } - - async delete(_uri: URI): Promise { - await this.ready(); - // FIXME had to add this method back to make the compiler happy jchris - throw new Error("no delete for fireproof cloud"); - } - - async destroy(uri: URI): Promise> { - await this.ready(); - return exception2Result(async () => { - const deleteUrl = pkBaseURL(uri); - const response = await fetch(deleteUrl.asURL(), { method: "DELETE" }); - if (response.status === 404) { - throw new Error("Failure in deleting data!"); - } - return Result.Ok(undefined); - }); - } -} - -const pkSockets = new KeyedResolvOnce(); - -function pkKey(set?: PartySocketOptions): string { - const ret = JSON.stringify( - Object.entries(set || {}) - .sort(([a], [b]) => a.localeCompare(b)) - .filter(([k]) => k !== "id") - .map(([k, v]) => ({ [k]: v })) - ); - return ret; -} -// ws://localhost:1999/parties/fireproof/test-public-api?_pk=zp9BXhS6u -// partykit://localhost:1999/?name=test-public-api&protocol=ws&store=meta -function pkURL(uri: URI, key: string, type: "car" | "meta"): URI { - const host = uri.host; - const name = uri.getParam("name"); - const idx = uri.getParam("index") || ""; - const protocol = uri.getParam("protocol") === "ws" ? "http" : "https"; - // TODO extract url from uri - const path = `/parties/fireproof/${name}${idx}`; - return BuildURI.from(`${protocol}://${host}${path}`).setParam(type, key).URI(); -} - -function pkBaseURL(uri: URI): URI { - const host = uri.host; - const name = uri.getParam("name"); - const idx = uri.getParam("index") || ""; - const protocol = uri.getParam("protocol") === "ws" ? "http" : "https"; - // TODO extract url from uri - const path = `/parties/fireproof/${name}${idx}`; - return BuildURI.from(`${protocol}://${host}${path}`).URI(); -} - -function pkCarGetURL(uri: URI, key: string): URI { - const baseUrl = uri.getParam("getBaseUrl"); - if (!baseUrl) { - return pkURL(uri, key, "car"); - } - const name = uri.getParam("name"); - const idx = uri.getParam("index") || ""; - const baseUri = URI.from(baseUrl).asURL(); - baseUri.pathname = `/${name}${idx}/${key}`; - // console.log("pkCarGetURL", baseUri.toString()); - return BuildURI.from(baseUri).URI(); -} - -function pkMetaURL(uri: URI, key: string): URI { - return pkURL(uri, key, "meta"); -} - -export class FireproofCloudTestStore implements bs.TestGateway { - readonly logger: Logger; - readonly sthis: SuperThis; - readonly gateway: bs.Gateway; - constructor(gw: bs.Gateway, sthis: SuperThis) { - this.sthis = sthis; - this.logger = ensureLogger(sthis, "FireproofCloudTestStore"); - this.gateway = gw; - } - async get(uri: URI, key: string): Promise { - const url = uri.build().setParam("key", key).URI(); - const dbFile = this.sthis.pathOps.join(rt.getPath(url, this.sthis), rt.getFileName(url, this.sthis)); - this.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get"); - const buffer = await this.gateway.get(url); - this.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got"); - return buffer.Ok(); - } -} - -const onceRegisterFireproofCloudStoreProtocol = new KeyedResolvOnce<() => void>(); -export function registerFireproofCloudStoreProtocol(protocol = "fireproof:", overrideBaseURL?: string) { - return onceRegisterFireproofCloudStoreProtocol.get(protocol).once(() => { - URI.protocolHasHostpart(protocol); - return bs.registerStoreProtocol({ - protocol, - overrideBaseURL, - gateway: async (sthis) => { - return new FireproofCloudGateway(sthis); - }, - test: async (sthis: SuperThis) => { - const gateway = new FireproofCloudGateway(sthis); - return new FireproofCloudTestStore(gateway, sthis); - }, - }); - }); -} diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts new file mode 100644 index 00000000..f2c750c7 --- /dev/null +++ b/src/cloud/msg-types.ts @@ -0,0 +1,107 @@ +import { Logger, SuperThis } from "@fireproof/core"; + +export interface MsgBase { + readonly tid: string; + readonly type: string; + readonly version: string; +} + +export interface ErrorMsg extends MsgBase { + readonly type: "error"; + readonly message: string; +} +export function MsgIsError(msg: MsgBase): msg is ErrorMsg { + return msg.type === "error"; +} + +export type HttpMethods = "GET" | "PUT" | "DELETE"; +export type FPStoreTypes = "meta" | "data" | "wal"; + +export interface ConnectionKey { + // readonly protocol: "ws" | "wss"; // ws or wss + readonly tendantId: string; + readonly name: string; +} + +export interface SignedUrlParam extends ConnectionKey { + readonly path?: string; + readonly method: HttpMethods; + readonly store: FPStoreTypes; + readonly key: string; + readonly expires?: number; // seconds + readonly index?: string; +} + +export interface Connection { + readonly ws: WebSocket; + readonly params: ConnectionKey; +} + +export interface ReqSignedUrlParam { + readonly tid?: string; + readonly type?: "reqSignedUrl"; + readonly version?: string; + readonly params: { + // readonly protocol?: "ws" | "wss"; // ws or wss + readonly tendantId: string; + readonly name: string; + readonly path?: string; + readonly method: HttpMethods; + readonly store: FPStoreTypes; + readonly key: string; + readonly expires?: number; // seconds + readonly index?: string; + }; +} + +const VERSION = "FP-MSG-1.0"; + +export function buildReqSignedUrl(sthis: SuperThis, req: ReqSignedUrlParam): ReqSignedUrl { + return { + tid: sthis.nextId().str, + type: "reqSignedUrl", + version: VERSION, + ...req, + params: { + // protocol: "wss", + ...req.params, + }, + }; +} + +export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { + return { + tid: req.tid, + type: "resSignedUrl", + version: VERSION, + params: req.params, + signedUrl, + }; +} + +export function buildErrorMsg(logger: Logger, base: MsgBase, error: Error): ErrorMsg { + const msg = { + type: "error", + tid: base.tid, + message: error.message, + version: VERSION, + } satisfies ErrorMsg; + logger.Error().Any("msg", msg).Msg("error"); + return msg; +} + +export interface ReqSignedUrl extends MsgBase { + readonly type: "reqSignedUrl"; + readonly params: SignedUrlParam; +} + +export interface ReqSignedUrl extends MsgBase { + readonly type: "reqSignedUrl"; + readonly params: SignedUrlParam; +} + +export interface ResSignedUrl extends MsgBase { + readonly type: "resSignedUrl"; + readonly params: SignedUrlParam; + readonly signedUrl: string; +} diff --git a/src/cloud/new-websocket.ts b/src/cloud/new-websocket.ts new file mode 100644 index 00000000..1c8ef6fe --- /dev/null +++ b/src/cloud/new-websocket.ts @@ -0,0 +1,11 @@ +import { CoerceURI, runtimeFn, URI } from "@adviser/cement"; + +export async function newWebSocket(url: CoerceURI): Promise { + const wsUrl = URI.from(url).toString(); + if (runtimeFn().isNodeIsh) { + const { WebSocket: MyWS } = await import("ws"); + return new MyWS(wsUrl) as unknown as WebSocket; + } else { + return new WebSocket(wsUrl); + } +} diff --git a/src/connection-from-store.ts b/src/connection-from-store.ts index bdf6bba7..7a4f493f 100644 --- a/src/connection-from-store.ts +++ b/src/connection-from-store.ts @@ -1,5 +1,5 @@ -import { BuildURI, CoerceURI, runtimeFn, URI } from "@adviser/cement"; -import { bs, Database, ensureLogger, SuperThis } from "@fireproof/core"; +import { BuildURI, CoerceURI, URI } from "@adviser/cement"; +import { bs, Database, ensureLogger, rt, SuperThis } from "@fireproof/core"; // export interface StoreOptions { // readonly data: bs.DataStore; @@ -66,15 +66,15 @@ export function connectionFactory(sthis: SuperThis, iurl: CoerceURI): bs.Connect } export function makeKeyBagUrlExtractable(sthis: SuperThis) { - let base = sthis.env.get("FP_KEYBAG_URL"); - if (!base) { - if (runtimeFn().isBrowser) { - base = "indexdb://fp-keybag"; - } else { - base = "file://./dist/kb-dir-partykit"; - } - } - const kbUrl = BuildURI.from(base); + // let base = sthis.env.get("FP_KEYBAG_URL"); + // if (!base) { + // if (runtimeFn().isBrowser) { + // base = "indexdb://fp-keybag"; + // } else { + // base = "file://./dist/kb-dir-partykit"; + // } + // } + const kbUrl = BuildURI.from(rt.kb.defaultKeyBagUrl(sthis)); kbUrl.defParam("extractKey", "_deprecated_internal_api"); sthis.env.set("FP_KEYBAG_URL", kbUrl.toString()); sthis.logger.Debug().Url(kbUrl, "keyBagUrl").Msg("Make keybag url extractable"); diff --git a/src/netlify/server.ts b/src/netlify/server.ts index 0fd7d589..5c566131 100644 --- a/src/netlify/server.ts +++ b/src/netlify/server.ts @@ -23,9 +23,9 @@ export default async (req: Request) => { return new Response(JSON.stringify({ ok: true }), { status: 201 }); } else if (metaDb) { const meta = getStore("meta"); - const x = await req.json(); + const x = await req.json(); // fixme, marty changed to [0] as it is a slice of the structure we expected - const { data, cid, parents } = x[0] as CRDTEntry; + const { data, cid, parents } = x[0]; await meta.setJSON(`${metaDb}/${cid}`, { data, parents }); return new Response(JSON.stringify({ ok: true }), { status: 201 }); } diff --git a/tests/Dockerfile.connect-cloud b/tests/Dockerfile.connect-cloud new file mode 100644 index 00000000..9e3f8884 --- /dev/null +++ b/tests/Dockerfile.connect-cloud @@ -0,0 +1,19 @@ +FROM node:20-slim AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable +RUN apt update && apt install -y git +COPY src/cloud/backend /usr/src/app/cloud/backend +COPY .gitignore LICENSE.md /usr/src/app/cloud/backend/ +COPY package-cloud-backend.json /usr/src/app/cloud/backend +COPY version-copy-package.ts /usr/src/app/cloud/backend +WORKDIR /usr/src/app/cloud/backend +RUN pnpm install zx cmd-ts + +COPY package.json /usr/src/app/cloud/backend +RUN npx tsx version-copy-package.ts --skip-pack ./dist/package-cloud-backend.json && \ + cp ./dist/package.json . && \ + cat package.json && \ + pnpm i + +CMD pnpm run start diff --git a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts index 0fd7d589..8d71910e 100644 --- a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts +++ b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts @@ -23,9 +23,9 @@ export default async (req: Request) => { return new Response(JSON.stringify({ ok: true }), { status: 201 }); } else if (metaDb) { const meta = getStore("meta"); - const x = await req.json(); + const x = await req.json(); // fixme, marty changed to [0] as it is a slice of the structure we expected - const { data, cid, parents } = x[0] as CRDTEntry; + const { data, cid, parents } = x[0] await meta.setJSON(`${metaDb}/${cid}`, { data, parents }); return new Response(JSON.stringify({ ok: true }), { status: 201 }); } diff --git a/tests/start-cloud.sh b/tests/start-cloud.sh new file mode 100644 index 00000000..3f71e73e --- /dev/null +++ b/tests/start-cloud.sh @@ -0,0 +1,13 @@ +docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'cloud'| sed 's/\..*$//') +docker buildx build -t fireproof-cloud:latest --progress plain --no-cache -f ./tests/Dockerfile.connect-cloud . +# --no-cache-filter +docker run --name cloud \ + -e ACCESS_KEY_ID="minioadmin" \ + -e SECRET_ACCESS_KEY="minioadmin" \ + -e BUCKET_NAME="testbucket" \ + -e STORAGE_URL="http://localhost:9000/testbucket" \ + -e FP_STACK=fp \ + -e FP_DEBUG=Fireproof \ + -d -p 1968:1968 fireproof-cloud + + diff --git a/tests/waiton.ts b/tests/waiton.ts index 4c0d0885..97218668 100644 --- a/tests/waiton.ts +++ b/tests/waiton.ts @@ -1,6 +1,12 @@ import waitOn from "wait-on"; const opts = { - resources: ["http://localhost:8888/", "http://localhost:1999/", "http://localhost:8787/", "http://localhost:9000/"], + resources: [ + "http://localhost:8888/", + "http://localhost:1999/", + "http://localhost:8787/", + "http://localhost:9000/", + "http://localhost:1968", + ], delay: 0, // initial delay in ms, default 0 interval: 500, // poll interval in ms, default 250ms simultaneous: 4, // limit to 1 connection per resource at a time diff --git a/tsconfig.json b/tsconfig.json index 13bc6672..6741d6cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,7 +35,11 @@ // "rootDirs": ["./src", "./src-generated"], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - "types": ["vitest/globals"], + "types": [ + "vitest/globals", + "@cloudflare/workers-types" + // "@cloudflare/vitest-pool-workers" + ], // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ diff --git a/tsup.config.ts b/tsup.config.ts index 49aa7a73..fd8c16c6 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -242,7 +242,7 @@ const LIBRARY_BUNDLES: Options[] = [ ...LIBRARY_BUNDLE_OPTIONS, format: ["iife"], name: "@fireproof/cloud", - entry: ["src/cloud/index.ts"], + entry: ["src/cloud/client/index.ts"], platform: "browser", outDir: "dist/cloud", esbuildPlugins: [ @@ -263,7 +263,7 @@ const LIBRARY_BUNDLES: Options[] = [ ...LIBRARY_BUNDLE_OPTIONS, format: ["esm", "cjs"], name: "@fireproof/cloud", - entry: ["src/cloud/index.ts"], + entry: ["src/cloud/client/index.ts"], platform: "browser", outDir: "dist/cloud", esbuildPlugins: [ diff --git a/version-copy-package.ts b/version-copy-package.ts index b7cb9cb0..8f8986bf 100644 --- a/version-copy-package.ts +++ b/version-copy-package.ts @@ -1,70 +1,85 @@ -/* eslint-disable no-console */ -import fs from "fs/promises"; -import process from "process"; -import path from "path"; -import { $ } from "zx"; + const cmd = command({ + name: "version-copy-package", + description: "prepare a package.json for a release", + version: "1.0.0", + args: { + // method: option({ + // long: "method", + // type: oneOf(["GET", "PUT", "POST", "DELETE"]), + // defaultValue: () => "PUT", + // defaultValueIsSerializable: true, + // }), + verbose: flag({ + long: "verbose", + type: boolean, + // defaultValue: () => "false", + // defaultValueIsSerializable: true, + }), + skipPack: flag({ + long: "skip-pack", + type: boolean, + // defaultValue: () => "false", + // defaultValueIsSerializable: true, + }), + buildDest: positional({ + type: string, + description: "build destination", + }), + }, + handler: async (args) => { + $.verbose = args.verbose; -async function copyFilesToDist(destDir: string) { - for (const file of ["./.gitignore", "./LICENSE.md"]) { - await fs.copyFile(file, path.join(destDir, file)); - } -} - -async function patchVersion(packageJson: Record) { - let version = "refs/tags/v0.0.0-smoke"; - if (process.env.GITHUB_REF && process.env.GITHUB_REF.startsWith("refs/tags/v")) { - version = process.env.GITHUB_REF; - } - version = version.split("/").slice(-1)[0].replace(/^v/, ""); - console.log(`Patch version ${version} in package.json`); - packageJson.version = version; -} - -async function main() { - $.verbose = true; - const buildDest = process.argv[process.argv.length - 1]; - if (!(buildDest.startsWith("dist/") || buildDest.startsWith("./dist/"))) { - console.error("Usage: tsx version-copy-package.ts dist//template-package.json"); - process.exit(1); - } - const destDir = path.dirname(buildDest); - if (!(await fs.stat(destDir)).isDirectory) { - console.error(`Directory ${destDir} does not exist`); - process.exit(1); - } - await copyFilesToDist(destDir); - const mainPackageJson = JSON.parse(await fs.readFile("package.json", "utf8")); - const templateFile = path.basename(buildDest); - const destPackageJson = JSON.parse(await fs.readFile(templateFile, "utf-8")); - // copy version from package.json - for (const destDeps of Object.keys(destPackageJson.dependencies)) { - if (!mainPackageJson.dependencies[destDeps]) { - console.error(`Dependency ${destDeps} not found in main package.json`); - } else { - destPackageJson.dependencies[destDeps] = mainPackageJson.dependencies[destDeps]; - } - } - patchVersion(destPackageJson); - // add a dependency to fireproof core with the same tag we're building - destPackageJson.dependencies["@fireproof/core"] = mainPackageJson.dependencies["@fireproof/core"]; - if (!mainPackageJson.dependencies["@fireproof/core"]) { - throw new Error("there must be a version of @fireproof/core in main"); - } - for (const i of ["keywords", "contributors", "license"]) { - if (typeof mainPackageJson[i] === "string") { - destPackageJson[i] = mainPackageJson[i]; - } else if (Array.isArray(mainPackageJson[i])) { - destPackageJson[i] = Array.from(new Set([...mainPackageJson[i], ...(destPackageJson[i] || [])])); - } else { - destPackageJson[i] = { ...mainPackageJson[i], ...destPackageJson[i] }; - } - } - const destPackageJsonFile = path.join(destDir, "package.json"); - await fs.writeFile(destPackageJsonFile, JSON.stringify(destPackageJson, null, 2)); - console.log( - `Copied ${templateFile} to ${destDir} with version ${destPackageJson.version} using fireproof/core=${destPackageJson.dependencies["@fireproof/core"]}` - ); - await $`cd ${destDir} && pnpm pack`.pipe(process.stdout); + // const buildDest = process.argv[process.argv.length - 1]; + const buildDest = args.buildDest; + if (!(buildDest.startsWith("dist/") || buildDest.startsWith("./dist/"))) { + console.error("Usage: tsx version-copy-package.ts dist//template-package.json"); + process.exit(1); + } + const destDir = path.dirname(buildDest); + await fs.mkdir(destDir, { recursive: true }); + if (!(await fs.stat(destDir)).isDirectory) { + console.error(`Directory ${destDir} does not exist`); + process.exit(1); + } + await copyFilesToDist(destDir); + const mainPackageJson = JSON.parse(await fs.readFile("package.json", "utf8")); + const templateFile = path.basename(buildDest); + const destPackageJson = JSON.parse(await fs.readFile(templateFile, "utf-8")); + // copy version from package.json + for (const destDeps of Object.keys(destPackageJson.dependencies)) { + if (!mainPackageJson.dependencies[destDeps]) { + console.error(`Dependency ${destDeps} not found in main package.json`); + } else { + destPackageJson.dependencies[destDeps] = mainPackageJson.dependencies[destDeps]; + } + } + patchVersion(destPackageJson); + // add a dependency to fireproof core with the same tag we're building + destPackageJson.dependencies["@fireproof/core"] = mainPackageJson.dependencies["@fireproof/core"]; + if (!mainPackageJson.dependencies["@fireproof/core"]) { + throw new Error("there must be a version of @fireproof/core in main"); + } + for (const i of ["keywords", "contributors", "license"]) { + if (typeof mainPackageJson[i] === "string") { + destPackageJson[i] = mainPackageJson[i]; + } else if (Array.isArray(mainPackageJson[i])) { + destPackageJson[i] = Array.from(new Set([...mainPackageJson[i], ...(destPackageJson[i] || [])])); + } else { + destPackageJson[i] = { ...mainPackageJson[i], ...destPackageJson[i] }; + } + } + const destPackageJsonFile = path.join(destDir, "package.json"); + await fs.writeFile(destPackageJsonFile, JSON.stringify(destPackageJson, null, 2)); + console.log( + `Copied ${templateFile} to ${destDir} with version ${destPackageJson.version} using fireproof/core=${destPackageJson.dependencies["@fireproof/core"]}` + ); + if (args.skipPack) { + return; + } + await $`cd ${destDir} && pnpm pack`.pipe(process.stdout); + }, + }); + await run(cmd, process.argv.slice(2)); } main().catch(console.error); diff --git a/vitest.cloud.config.ts b/vitest.cloud.config.ts index 87a868a2..71efb795 100644 --- a/vitest.cloud.config.ts +++ b/vitest.cloud.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from "vitest/config"; - import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; +// import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'; export default defineConfig({ plugins: [tsconfigPaths()], @@ -9,6 +9,8 @@ export default defineConfig({ exclude: [ "node_modules/@fireproof/core/tests/react/**", "node_modules/@fireproof/core/tests/fireproof/config.test.ts", + "node_modules/@fireproof/core/tests/blockstore/keyed-crypto*", + "node_modules/@fireproof/core/tests/**/utils.test.ts", ], include: [ // "node_modules/@fireproof/core/tests/**/*test.?(c|m)[jt]s?(x)", @@ -19,5 +21,8 @@ export default defineConfig({ globals: true, setupFiles: "./setup.cloud.ts", testTimeout: 25000, + // poolOptions: { + // workers: { wrangler: { configPath: './src/cloud/backend/wrangler.toml' } }, + // }, }, }); diff --git a/wrangler.toml b/wrangler.toml deleted file mode 100644 index 3c60278e..00000000 --- a/wrangler.toml +++ /dev/null @@ -1,5 +0,0 @@ -# Top-level configuration -name = "connector" -#main = "src/cf-index.ts" -compatibility_date = "2024-06-03" -compatibility_flags = [ "nodejs_compat" ] From dc4b3de292d406e2b8fac7863f375bf608ccde1b Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 28 Nov 2024 23:13:40 +0100 Subject: [PATCH 02/83] chore: almost done --- package.json | 13 +- pnpm-lock.yaml | 48 +- src/cloud/backend/env.d.ts | 1 + src/cloud/backend/fp-meta-groups.ts | 83 ++-- src/cloud/backend/server.ts | 472 ++++++++++++++------ src/cloud/backend/wrangler.toml | 13 +- src/cloud/client/gateway.ts | 650 ++++++++++++++++++++-------- src/cloud/cloud.test.ts | 75 ++-- src/cloud/msg-types.ts | 315 +++++++++++++- src/cloud/pre-signed-url.ts | 53 +++ version-copy-package.ts | 23 + 11 files changed, 1348 insertions(+), 398 deletions(-) create mode 100644 src/cloud/pre-signed-url.ts diff --git a/package.json b/package.json index cef3b078..92871671 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "pretest:cloud": "bash ./tests/start-cloud.sh", + "xpretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "posttest:cloud": "docker rm -f cloud", + "xposttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -97,7 +97,7 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.38" + "@adviser/cement": "^0.2.40" }, "dependencies": { "@adviser/cement": "^0.2.40", @@ -105,6 +105,7 @@ "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", "@cloudflare/workers-types": "^4.20241112.0", + "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", @@ -120,6 +121,12 @@ "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", + "@ucanto/client": "^9.0.1", + "@ucanto/core": "^10.0.1", + "@ucanto/interface": "^10.0.1", + "@ucanto/principal": "^9.0.1", + "@ucanto/transport": "^9.1.1", + "@ucanto/validator": "^9.0.2", "assert": "^2.1.0", "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 82f87dcf..5da8336f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^4.20241112.0 version: 4.20241205.0 '@fireproof/core': - specifier: 0.19.116 - version: 0.19.116(react@18.3.1)(typescript@5.7.2) + specifier: 0.19.114 + version: 0.19.114(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 @@ -1064,8 +1064,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.116': - resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} + '@fireproof/core@0.19.114': + resolution: {integrity: sha512-b/UTsxqazHYkIglllhKIaZl+veik6zuBO8gJGAKBZhxCwAEz5NQOUPDz4Dhk0c5YIeu1ODi9tv2cQ2VFUUDvBg==} peerDependencies: react: ^18.3.1 @@ -1126,6 +1126,10 @@ packages: resolution: {integrity: sha512-NnU8HdHKwAoGyrW3S09NMa8aZw0tImLRyR64hoafpLpDpAbA9g1+fb24JsdlugbL4sXUQVwDVA+qK4Ud8V83lA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} + '@ipld/dag-json@10.2.3': + resolution: {integrity: sha512-itacv1j1hvYgLox2B42Msn70QLzcr0MEo5yGIENuw2SM/lQzq9bmBiMky+kDsIrsqqblKTXcHBZnnmK7D4a6ZQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + '@ipld/dag-pb@4.1.2': resolution: {integrity: sha512-BSztO4l3C+ya9HjCaQot26Y4AVsqIKtnn6+23ubc1usucnf6yoTBme18oCCdM6gKBMxuPqju5ye3lh9WEJsdeQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -2550,6 +2554,9 @@ packages: interface-store@6.0.2: resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} + ipfs-unixfs-exporter@13.6.1: + resolution: {integrity: sha512-pYPI4oBTWao2//sFzAL0pURyojn79q/u5BuK6L5/nVbVUQVw6DcVP5uB1ySdWlTM2H+0Zlhp9+OL9aJBRIICpg==} + ipfs-unixfs@11.2.0: resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} @@ -4947,13 +4954,18 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.114(react@18.3.1)(typescript@5.7.2)': dependencies: '@adviser/cement': 0.2.40(typescript@5.7.2) - '@fireproof/vendor': 1.0.0 + '@ipld/car': 5.3.3 + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.3 '@ipld/unixfs': 3.0.0 + '@web3-storage/pail': 0.6.0 + cborg: 4.2.6 charwise: 3.0.1 idb: 8.0.0 + ipfs-unixfs-exporter: 13.6.1 memfs: 4.14.1 multiformats: 13.3.1 p-limit: 6.1.0 @@ -5037,6 +5049,11 @@ snapshots: cborg: 4.2.6 multiformats: 13.3.1 + '@ipld/dag-json@10.2.3': + dependencies: + cborg: 4.2.6 + multiformats: 13.3.1 + '@ipld/dag-pb@4.1.2': dependencies: multiformats: 13.3.1 @@ -6924,6 +6941,25 @@ snapshots: interface-store@6.0.2: {} + ipfs-unixfs-exporter@13.6.1: + dependencies: + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.3 + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + ipfs-unixfs@11.2.0: dependencies: protons-runtime: 5.5.0 diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index 03cdd64c..fd73ba15 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -24,6 +24,7 @@ export interface Env { FP_STACK: string; FP_FORMAT: string; TEST_DATE?: string; + MAX_IDLE_TIME?: string; FP_META_GROUPS: DurableObjectNamespace; } diff --git a/src/cloud/backend/fp-meta-groups.ts b/src/cloud/backend/fp-meta-groups.ts index 786c2fea..846e5adb 100644 --- a/src/cloud/backend/fp-meta-groups.ts +++ b/src/cloud/backend/fp-meta-groups.ts @@ -1,46 +1,47 @@ - import { DurableObject } from "cloudflare:workers"; -import { Env } from './env'; +import { Env } from "./env"; export class FPMetaGroups extends DurableObject { - currentlyConnectedWebSockets: number; - - constructor(ctx: DurableObjectState, env: Env) { - // This is reset whenever the constructor runs because - // regular WebSockets do not survive Durable Object resets. - // - // WebSockets accepted via the Hibernation API can survive - // a certain type of eviction, but we will not cover that here. - super(ctx, env); - this.currentlyConnectedWebSockets = 0; - } - - async fetch(request: Request): Promise { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `accept()` tells the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - server.accept(); - this.currentlyConnectedWebSockets += 1; - - // Upon receiving a message from the client, the server replies with the same message, - // and the total number of connections with the "[Durable Object]: " prefix - server.addEventListener('message', (event: MessageEvent) => { - server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`); - }); - - // If the client closes the connection, the runtime will close the connection too. - server.addEventListener('close', (cls: CloseEvent) => { - this.currentlyConnectedWebSockets -= 1; - server.close(cls.code, "Durable Object is closing WebSocket"); - }); + currentlyConnectedWebSockets: number; + + constructor(ctx: DurableObjectState, env: Env) { + // This is reset whenever the constructor runs because + // regular WebSockets do not survive Durable Object resets. + // + // WebSockets accepted via the Hibernation API can survive + // a certain type of eviction, but we will not cover that here. + super(ctx, env); + this.currentlyConnectedWebSockets = 0; + } - return new Response(null, { - status: 101, - webSocket: client, - }); - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async fetch(request: Request): Promise { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `accept()` tells the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + server.accept(); + this.currentlyConnectedWebSockets += 1; + + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + // eslint-disable-next-line @typescript-eslint/no-unused-vars + server.addEventListener("message", (event: MessageEvent) => { + server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`); + }); + + // If the client closes the connection, the runtime will close the connection too. + server.addEventListener("close", (cls: CloseEvent) => { + this.currentlyConnectedWebSockets -= 1; + server.close(cls.code, "Durable Object is closing WebSocket"); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); } +} diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index d19c9e3d..bb656b6d 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,13 +1,43 @@ import type { Env } from "./env"; -import { AwsClient } from "aws4fetch"; -import { BuildURI, exception2Result, LoggerImpl, Result, URI } from "@adviser/cement"; -import { buildErrorMsg, buildResSignedUrl, MsgBase, MsgIsError, ReqSignedUrl } from "../msg-types"; -import { Hono } from "hono"; -import { NotFoundError } from "@fireproof/core"; -import { upgradeWebSocket } from "hono/cloudflare-workers"; -import { a } from "@adviser/cement/txt-en-decoder-CZYJUju2"; +import { exception2Result, Logger, LoggerImpl, URI } from "@adviser/cement"; +import { + buildErrorMsg, + buildResDelMeta, + buildResGetMeta, + buildResPutMeta, + buildResSignedUrl, + buildResSubscriptMeta, + buildUpdateMetaEvent, + ErrorMsg, + MsgBase, + MsgIsQSError, + MsgIsReqDelMeta, + MsgIsReqGetMeta, + MsgIsReqPutMeta, + MsgIsReqSignedUrl, + MsgIsReqSubscribeMeta, + MsgIsResPutMeta, + MsgIsResSubscribeMeta, + ReqDelMeta, + ReqGetMeta, + ReqOptRes, + ReqPutMeta, + ReqRes, + ReqSignedUrl, + ReqSubscribeMeta, + ResDelMeta, + ResGetMeta, + ResPutMeta, + ResSignedUrl, + ResSubscribeMeta, +} from "../msg-types"; +// import { Hono } from "hono"; +import { bs, NotFoundError } from "@fireproof/core"; +import { DurableObject } from "cloudflare:workers"; +import { calculatePreSignedUrl } from "../pre-signed-url"; const CORS = { + "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET,POST,OPTIONS,PUT,DELETE", "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours @@ -17,23 +47,11 @@ function json(data: T, status = 200) { return Response.json(data, { status, headers: CORS }); } -// function ok() { -// return json({ ok: true }); -// } - -// class FireProofWSockConnection extends DurableObject { -// } - - - - -const app = new Hono<{ Bindings: Env }>(); - -function getLogger(env: Env) { +function ensureLogger(env: Env, module = "Fireproof"): Logger { return ( new LoggerImpl() .With() - .Module("Fireproof") + .Module(module) .SetDebug(env.FP_DEBUG) // .SetFormatter((env.FP_FORMAT || "json") as LogFormatter) .SetExposeStack(!!env.FP_STACK || false) @@ -41,119 +59,327 @@ function getLogger(env: Env) { ); } -async function doMsg(decodeFn: () => Promise, env: Env): Promise { - const rReqMsg = await exception2Result(async () => (await decodeFn()) as MsgBase); - const logger = getLogger(env); - if (rReqMsg.isErr()) { - return buildErrorMsg(logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); +interface FPMetaGroup { + readonly group: ResSubscribeMeta; + readonly connId: string; + readonly msgSeq: number; + readonly lastUsed: Date; + readonly lastMeta: ReqPutMeta; +} + +// interface NextId { +// nextId: SuperThis["nextId"]; +// } +// class NextIdImpl implements NextId { +// nextId(bytes = 6): { str: string; bin: Uint8Array } { +// const buf = new Uint8Array(bytes); +// const bin = crypto.getRandomValues(buf); +// return { +// str: base58btc.encode(bin), +// bin, +// }; +// } +// } + +// const sthis = new NextIdImpl(); + +export class FPMetaGroups extends DurableObject { + // readonly sessions: Map = new Map(); + // readonly lastMetaByTendant = new Map[]>(); + + readonly logger: Logger; + + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + this.logger = ensureLogger(env, "FPMetaGroups"); + // this.ctx.getWebSockets().forEach((webSocket) => { + // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; + // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { + // this.sessions.set(webSocket, fpMetaGroup); + // } + // }); } - const reqMsg = rReqMsg.Ok(); - switch (reqMsg.type) { - case "reqSignedUrl": { - const rSignedUrl = await calculatePreSignedUrl(reqMsg as ReqSignedUrl, env); - if (rSignedUrl.isErr()) { - return buildErrorMsg(logger, reqMsg as ReqSignedUrl, rSignedUrl.Err()); + + async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { + if (typeof msg !== "string") { + this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary") + return; + } + + return CFMsgProcessor.dispatch(() => JSON.parse(msg.toString()), { + env: this.env, + }, async (req: MsgBase, ictx: CtxBase) => { + if (req.auth) { + // do ucan magic + } + let group = (ws.deserializeAttachment() || { msgSeq: 0 }) as FPMetaGroup; + group = { + ...group, + msgSeq: group.msgSeq + 1, + connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), + lastUsed: new Date() + } satisfies FPMetaGroup + ws.serializeAttachment(group); + const ctx = { ...ictx, group } satisfies CtxWithGroup + return { req, ctx }; + }).then((qs) => { + switch (true) { + case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): { + const group = { ...qs.ctx.group, lastMeta: qs.req } satisfies FPMetaGroup; + ws.serializeAttachment(group); + this.updateMeta(qs); + break; + } + case MsgIsResSubscribeMeta(qs.res): { + const group = { ...qs.ctx.group, group: qs.res } satisfies FPMetaGroup; + ws.serializeAttachment(group); + this.updateMeta(qs) + break; + } + } + ws.send(JSON.stringify(qs.res)); + }); + } + + async fetch(req: Request): Promise { + const path = URI.from(req.url).pathname + switch (path) { + case "/fp": { + const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); + return json(rq.res, MsgIsQSError(rq) ? 422 : 200); + } + case "/ws": { + const upgradeHeader = req.headers.get("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); + } + const { 0: fromClient, 1: toClient } = new WebSocketPair(); + this.ctx.acceptWebSocket(toClient); + this.logger.Debug().Msg("fetch"); + return new Response(null, { + status: 101, + webSocket: fromClient, + }); + } + default: { + const logger = ensureLogger(this.env); + return json(buildErrorMsg(logger, { tid: "internal", }, new NotFoundError(`Notfound:${c.req.path}`)), 404); } - const resSignedUrl = buildResSignedUrl(reqMsg as ReqSignedUrl, rSignedUrl.Ok().toString()); - return resSignedUrl; } } - return buildErrorMsg(logger, { tid: "internal" } as ReqSignedUrl, new Error(`unknown msg.type=${reqMsg.type}`)); + + webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { + try { + ws.close(code, reason); + } finally { + this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); + } + } + + updateMeta(qs: ReqRes): void { + const wsSocks = this.ctx.getWebSockets() + const groupWs = wsSocks.map(ws => ({ + ws, group: ws.deserializeAttachment() as FPMetaGroup + })); + const joinedMeta = groupWs.reduce((acc, { group }) => { + if (group && group.lastMeta) { + acc.push(...group.lastMeta.metas) + } + return acc + }, [] as bs.DbMeta[]) + const now = new Date() + groupWs.forEach(({ ws, group }) => { + ws.serializeAttachment({ + ...group, + msgSeq: group.msgSeq + 1, + lastUsed: now + } satisfies FPMetaGroup) + ws.send( + JSON.stringify( + buildUpdateMetaEvent(qs, { + metas: joinedMeta, + subscriberId: group.group.subscriberId, + connId: group.group.connId, + }) + ) + ) + }) + } +} + +// const app = new Hono<{ Bindings: Env }>(); + +interface MsgProcessor { + dispatch(decodeFn: () => Promise): Promise>; + + signedUrl(req: ReqSignedUrl): Promise; + subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise; + + delMeta(req: ReqDelMeta, ctx: CtxBase): Promise; + putMeta(req: ReqPutMeta, ctx: CtxBase): Promise; + getMeta(req: ReqGetMeta, ctx: CtxBase): Promise; +} + +interface CFMsgProcessorParams { + readonly env: Env; + readonly logger: Logger; +} + +interface CtxBaseParam { + readonly env: Env + readonly module?: string +} + +interface CtxBase { + readonly env: Env; + readonly logger: Logger; } -app.put("/get-signed-url", async (c) => { - c.env = c.env || {}; - const rRes = await doMsg(() => c.req.json(), c.env); - return json(rRes, MsgIsError(rRes) ? 422 : 200); -}); +type CtxWithGroup = CtxBase & { readonly group: FPMetaGroup } -app.get("/ws", async (c) => { - const upgradeHeader = c.req.header('Upgrade'); - if (!upgradeHeader || upgradeHeader !== 'websocket') { - return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); +interface ReqOptResCtx< + Q extends MsgBase, + S extends MsgBase, + C extends CtxBase> extends ReqOptRes { + readonly ctx?: C; +} + +interface ReqResCtx< + Q extends MsgBase, + S extends MsgBase, + C extends CtxBase> extends ReqRes { + readonly ctx: C +} + +class CFMsgProcessor implements MsgProcessor { + private readonly env: Env; + private readonly logger: Logger; + + static dispatch( + decodeFn: () => Promise, + ctx: CtxBaseParam, + reqFn?: (msg: Q, ctx: C) => Promise> + ): Promise> { + return new CFMsgProcessor({ + env: ctx.env, + logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor") + }).dispatch(decodeFn, reqFn); } - const id = c.env.FP_META_GROUPS.idFromName("foo"); - const stub = c.env.FP_META_GROUPS.get(id); - - return stub.fetch(c.req.raw) as unknown as Promise; - - - // upgradeWebSocket((c) => { - // return { - // onMessage(event, ws) { - // // console.log('Received message', event.data.toString()) - // doMsg(() => JSON.parse(event.data.toString()), c.env).then((msg) => { - // // console.log('Sending', msg) - // ws.send(JSON.stringify(msg)); - // }); - // }, - // onClose: () => { - // getLogger(c.env).Debug().Msg("Connection closed"); - // }, - // }; - // }) -}); - -app.notFound(async (c) => { - c.env = c.env || {}; - const logger = getLogger(c.env); - return json( - buildErrorMsg( - logger, - { - tid: "internal", - } as ReqSignedUrl, - new NotFoundError(`Notfound:${c.req.path}`) - ), - 404 - ); -}); -export default app; -export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env): Promise> { - let store: string = req.params.store; - if (req.params.index?.length) { - store = `${store}-${req.params.index}`; + constructor(cfp: CFMsgProcessorParams) { + this.env = cfp.env; + this.logger = cfp.logger; } - const expiresInSeconds = req.params.expires || 60 * 60; - - let suffix = ""; - switch (req.params.store) { - case "wal": - case "meta": - suffix = ".json"; - break; - default: - break; + + async dispatch( + decodeFn: () => Promise, + reqFn: (msg: Q, ctx: C) => Promise> = async (req) => ({ req }) + ): Promise> { + const ictx = { + env: this.env, + logger: this.logger + } as CtxBase + const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); + if (rReqMsg.isErr()) { + const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); + return { + req: errMsg as unknown as Q, + res: errMsg, + ctx: ictx as C + }; + } + const { req, ctx: optCtx } = (await reqFn(rReqMsg.Ok() as Q, ictx as C)); + const ctx = { ...ictx, ...optCtx } as C & { readonly group: FPMetaGroup } + switch (true) { + case MsgIsReqSignedUrl(req): + return { + req, + res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, + ctx + }; + case MsgIsReqSubscribeMeta(req): + return { + req, + res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, + ctx + }; + case MsgIsReqPutMeta(req): + return { + req, + res: (await this.putMeta(req, ctx)) as S | ErrorMsg, + ctx + }; + case MsgIsReqGetMeta(req): + return { + req, + res: (await this.getMeta(req, ctx)) as S | ErrorMsg, + ctx + }; + case MsgIsReqDelMeta(req): + return { + req, + res: (await this.delMeta(req, ctx)) as S | ErrorMsg, + ctx + }; + } + return { + req: req, + res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, + ctx + }; + } + + async delMeta(req: ReqDelMeta, ctx: CtxWithGroup): Promise { + return buildResDelMeta(req) } - const opUrl = BuildURI.from(env.STORAGE_URL) - // .protocol(vals.protocol === "ws" ? "http:" : "https:") - .setParam("X-Amz-Expires", expiresInSeconds.toString()) - .setParam("tid", req.tid) - .appendRelative(req.params.tendantId) - .appendRelative(req.params.name) - .appendRelative(store) - .appendRelative(`${req.params.key}${suffix}`) - .URI(); - const a4f = new AwsClient({ - accessKeyId: env.ACCESS_KEY_ID, - secretAccessKey: env.SECRET_ACCESS_KEY, - region: env.REGION || "us-east-1", - service: "s3", - }); - const signedUrl = await a4f - .sign( - new Request(opUrl.toString(), { - method: req.params.method, - }), + async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { + return buildResGetMeta(req) + } + + async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { + const rSignedUrl = await calculatePreSignedUrl( { - aws: { - signQuery: true, - // datetime: env.TEST_DATE, - }, - } - ) - .then((res) => res.url); - return Result.Ok(URI.from(signedUrl)); + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: req.params, + }, + this.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + // roughly time ordered + return buildResPutMeta(req, { + metaId: new Date().getTime().toString(), + metas: req.metas, + signedPutUrl: rSignedUrl.Ok().toString(), + connId: ctx.group.connId, + }); + } + + async signedUrl(req: ReqSignedUrl, _ctx: CtxBase): Promise { + const rSignedUrl = await calculatePreSignedUrl(req, this.env); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + const resSignedUrl = buildResSignedUrl(req, rSignedUrl.Ok().toString()); + return resSignedUrl; + } + + async subscribeMeta(req: ReqSubscribeMeta, ctx: CtxWithGroup): Promise { + // console.log("subscribeMeta", req) + return buildResSubscriptMeta(req, ctx.group); + } } + +export default { + async fetch(req, env, _ctx): Promise { + + const id = env.FP_META_GROUPS.idFromName("fireproof"); + const stub = env.FP_META_GROUPS.get(id); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return stub.fetch(req as any) as unknown as Promise; + }, +} satisfies ExportedHandler; diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 0ef0daa5..622c7d4f 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -4,9 +4,11 @@ compatibility_date = "2024-04-19" # compatibility_flags = ["nodejs_compat"] # upload_source_maps = true -[[durable_objects.bindings]] -name = "FP_META_GROUPS" -class_name = "FPMetaGroups" +[durable_objects] +bindings = [ + { name = "FP_META_GROUPS", class_name = "FPMetaGroups"}, +] + [[migrations]] tag = "v1" # Should be unique for each entry @@ -22,3 +24,8 @@ STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" # TEST_DATE = "20241121T225359Z" + +[env.test.durable_objects] +bindings = [ + { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, +] \ No newline at end of file diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index f9fd5511..c2231f05 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -1,97 +1,476 @@ // import PartySocket, { PartySocketOptions } from "partysocket"; import { Result, URI, KeyedResolvOnce, exception2Result, Future } from "@adviser/cement"; import { bs, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; -import { buildReqSignedUrl, ConnectionKey, FPStoreTypes, HttpMethods, MsgBase, ResSignedUrl } from "../msg-types.js"; +import { + buildErrorMsg, + buildReqDelMeta, + buildReqGetMeta, + buildReqPutMeta, + buildReqSignedUrl, + buildReqSubscriptMeta, + ConnectionKey, + FPStoreTypes, + HttpMethods, + MsgBase, + MsgIsError, + MsgIsUpdateMetaEvent, + ReqSignedUrl, + ResDelMeta, + ResGetMeta, + ResPutMeta, + ResSignedUrl, + ResSubscribeMeta, +} from "../msg-types.js"; import { newWebSocket } from "../new-websocket.js"; const VERSION = "v0.1-fp-cloud"; +interface RequestOpts { + readonly waitType: string; + readonly timeout: number; // ms +} interface Connection { readonly ws: WebSocket; - readonly params: ConnectionKey; - request(msg: MsgBase): Promise>; + readonly key: ConnectionKey; + request(msg: MsgBase, opts?: Partial): Promise>; + onMessage(msgFn: (msg: MsgBase) => void): () => void; +} + +interface WaitForTid { + readonly tid: string; + readonly future: Future; + // undefined match all + readonly type?: string; } + + export class ConnectionImpl implements Connection { readonly ws: WebSocket; - readonly params: ConnectionKey; - readonly waitForTid = new Map>(); - constructor(logger: Logger, ws: WebSocket, params: ConnectionKey) { + readonly key: ConnectionKey; + readonly waitForTid = new Map(); + readonly msgCallbacks = new Map void>(); + readonly sthis: SuperThis; + readonly logger: Logger; + constructor(sthis: SuperThis, ws: WebSocket, key: ConnectionKey) { this.ws = ws; - this.params = params; + this.key = key; + this.sthis = sthis; + this.logger = ensureLogger(sthis, "ConnectionImpl", { + this: true, + }); + this.logger.Debug().Any("key", key).Msg("constructor"); + // this.params = params; ws.onmessage = async (event) => { - const rMsg = await exception2Result(() => JSON.parse(event.data)); + const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); if (rMsg.isErr()) { - logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); + this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); return; } - const msg = rMsg.Ok() as MsgBase; - const future = this.waitForTid.get(msg.tid); - if (future) { + const msg = rMsg.Ok() + const waitFor = this.waitForTid.get(msg.tid); + if (waitFor) { + if (waitFor.type === msg.type || MsgIsError(msg)) { + this.msgCallbacks.forEach((cb) => cb(msg)); + } this.waitForTid.delete(msg.tid); - future.resolve(msg); + waitFor.future.resolve(msg); } }; } - async request(msg: MsgBase): Promise> { + + onMessage(msgFn: (msg: MsgBase) => void): () => void { + const fnId = this.sthis.nextId().str; + this.msgCallbacks.set(fnId, msgFn); + return () => { + this.msgCallbacks.delete(fnId); + }; + } + + async request(req: Q, opts: Partial = {}): Promise> { + opts = { + ...{ + timeout: 1000, + }, + ...opts, + } const future = new Future(); - this.waitForTid.set(msg.tid, future); - this.ws.send(JSON.stringify(msg)); + this.waitForTid.set(req.tid, { + tid: req.tid, + future, + type: opts.waitType, + }); + const start = Date.now(); + const logger = ensureLogger(this.sthis, "ConnectionImpl.request") + .With() + .Str("tid", req.tid) + .Uint64("timeout", opts.timeout) + .Ref("start", ()=> (new Date()).getTime()-start) + .Any("req", req) + .Logger(); + this.ws.send(JSON.stringify(req)); + const clean = setTimeout(() => { + this.waitForTid.delete(req.tid); + future.reject(new Error("Timeout")); + }, opts.timeout); // add timeout handling + logger.Debug().Msg("request-enter"); return future .asPromise() - .then((msg) => { - return Result.Ok(msg as T); + .finally(() => clearTimeout(clean)) + .then((res) => { + logger.Debug().Any("res", res).Msg("request-ok"); + return Result.Ok(res as S); }) .catch((err) => { - return Result.Err(err); - }); + logger.Error().Err(err).Msg("request-error"); + return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); + }) } } -export class FireproofCloudGateway implements bs.Gateway { +export interface StoreTypeGateway { + get(uri: URI, conn: Promise>): Promise>; + put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; + delete(uri: URI, conn: Promise>): Promise>; +} + +abstract class BaseGateway { readonly logger: Logger; readonly sthis: SuperThis; - readonly id: string; - // party?: PartySocket; - url?: URI; + constructor(sthis: SuperThis, module: string) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, module); + } + + abstract getConn(uri: URI, conn: Connection): Promise>; + async get(uri: URI, prConn: Promise>): Promise> { + const rConn = await prConn; + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in getConn").ResultError(); + } + const conn = rConn.Ok(); + this.logger.Debug().Any("conn", conn.key).Msg("get"); + return this.getConn(uri, conn); + } + abstract putConn(uri: URI, body: Uint8Array, conn: Connection): Promise>; + + async put(uri: URI, body: Uint8Array, prConn: Promise>): Promise> { + const rConn = await prConn; + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); + } + const conn = rConn.Ok(); + this.logger.Debug().Any("conn", conn.key).Msg("put"); + return this.putConn(uri, body, conn); + + } + abstract delConn(uri: URI, conn: Connection): Promise>; + async delete(uri: URI, prConn: Promise>): Promise> { + const rConn = await prConn; + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); + } + const conn = rConn.Ok(); + this.logger.Debug().Any("conn", conn.key).Msg("del"); + return this.delConn(uri, conn); + } + + prepareReqSignedUrl(uri: URI, method: HttpMethods, cKey: ConnectionKey): Result { + const rParams = uri.getParamsResult({ + store: 0, + key: 0, + }); + if (rParams.isErr()) { + return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); + } + const { store, key } = rParams.Ok(); + return Result.Ok( + buildReqSignedUrl(this.sthis, { + // auth: await getUcanAuthFromUri(uri), + params: { + ...cKey, + store: store as FPStoreTypes, + key, + method, + }, + }) + ); + } + + async getResSignedUrl(uri: URI, method: HttpMethods, conn: Connection): Promise> { + const rsu = this.prepareReqSignedUrl(uri, method, conn.key); + if (rsu.isErr()) { + return Result.Err(rsu.Err()); + } + return conn.request(rsu.Ok(), { waitType: "resSignedUrl"}); + } + + async putObject(uri: URI, uploadUrl: string, body: Uint8Array): Promise> { + this.logger.Debug().Any("url", { uploadUrl, uri }).Msg("put-fetch-url"); + const rUpload = await exception2Result(async () => fetch(uploadUrl, { method: "PUT", body })); + if (rUpload.isErr()) { + return this.logger.Error().Url(uploadUrl, "uploadUrl").Err(rUpload).Msg("Error in put fetch").ResultError(); + } + if (!rUpload.Ok().ok) { + return this.logger.Error().Url(uploadUrl, "uploadUrl").Http(rUpload.Ok()).Msg("Error in put fetch").ResultError(); + } + if (uri.getParam("testMode")) { + trackPuts.add(uri.toString()); + } + return Result.Ok(undefined); + } + + async getObject(uri: URI, downloadUrl: string): Promise> { + this.logger.Debug().Any("url", { downloadUrl, uri }).Msg("get-fetch-url"); + const rDownload = await exception2Result(async () => fetch(downloadUrl.toString(), { method: "GET" })); + if (rDownload.isErr()) { + return this.logger + .Error() + .Url(downloadUrl, "uploadUrl") + .Err(rDownload) + .Msg("Error in get downloadUrl") + .ResultError(); + } + const download = rDownload.Ok(); + if (!download.ok) { + if (download.status === 404) { + return Result.Err(new NotFoundError("Not found")); + } + return this.logger.Error().Url(downloadUrl, "uploadUrl").Err(rDownload).Msg("Error in get fetch").ResultError(); + } + return Result.Ok(new Uint8Array(await download.arrayBuffer())); + } - readonly trackPuts = new Set(); + async delObject(uri: URI, deleteUrl: string): Promise> { + this.logger.Debug().Any("url", { deleteUrl, uri }).Msg("get-fetch-url"); + const rDelete = await exception2Result(async () => fetch(deleteUrl.toString(), { method: "DELETE" })); + if (rDelete.isErr()) { + return this.logger.Error().Url(deleteUrl, "deleteUrl").Err(rDelete).Msg("Error in get deleteURL").ResultError(); + } + const download = rDelete.Ok(); + if (!download.ok) { + if (download.status === 404) { + return Result.Err(new NotFoundError("Not found")); + } + return this.logger.Error().Url(deleteUrl, "deleteUrl").Err(rDelete).Msg("Error in del fetch").ResultError(); + } + return Result.Ok(undefined); + } + +} + +class DataGateway extends BaseGateway implements StoreTypeGateway { + constructor(sthis: SuperThis) { + super(sthis, "DataGateway"); + } + async getConn(uri: URI, conn: Connection): Promise> { + const rResSignedUrl = await this.getResSignedUrl(uri, "GET", conn); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { signedUrl: downloadUrl } = rResSignedUrl.Ok(); + return this.getObject(uri, downloadUrl); + } + async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { + const rResSignedUrl = await this.getResSignedUrl(uri, "PUT", conn); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { signedUrl: uploadUrl } = rResSignedUrl.Ok(); + return this.putObject(uri, uploadUrl, body); + } + async delConn(uri: URI, conn: Connection): Promise> { + const rResSignedUrl = await this.getResSignedUrl(uri, "DELETE", conn); + if (rResSignedUrl.isErr()) { + return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + } + const { signedUrl: deleteUrl } = rResSignedUrl.Ok(); + return this.delObject(uri, deleteUrl); + } +} + +class MetaGateway extends BaseGateway implements StoreTypeGateway { + constructor(sthis: SuperThis) { + super(sthis, "MetaGateway"); + } + async getConn(uri: URI, conn: Connection): Promise> { + const rsu = this.prepareReqSignedUrl(uri, "GET", conn.key); + if (rsu.isErr()) { + return Result.Err(rsu.Err()); + } + const rRes = await conn.request( + buildReqGetMeta(this.sthis, conn.key, rsu.Ok().params), + {waitType: "resGetMeta"} + ); + if (rRes.isErr()) { + return Result.Err(rRes.Err()); + } + const res = rRes.Ok(); + if (MsgIsError(res)) { + return Result.Err(res) + } + if (res.signedGetUrl) { + return this.getObject(uri, res.signedGetUrl) + } + return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); + + } + async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { + const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); + if (bodyRes.isErr()) { + return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); + } + const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as bs.DbMeta[]; + this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); + const rsu = this.prepareReqSignedUrl(uri, "PUT", conn.key); + if (rsu.isErr()) { + return Result.Err(rsu.Err()); + } + const res = await conn.request( + buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas), + { waitType: "resPutMeta" } + ); + if (res.isErr()) { + return Result.Err(res.Err()); + } + this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); + return res; + + } + async delConn(uri: URI, conn: Connection): Promise> { + const rsu = this.prepareReqSignedUrl(uri, "DELETE", conn.key); + if (rsu.isErr()) { + return Result.Err(rsu.Err()); + } + const res = await conn.request( + buildReqDelMeta(this.sthis, conn.key, rsu.Ok().params), + { waitType: "resDelMeta"} + ); + if (res.isErr()) { + return Result.Err(res.Err()); + } + const { signedDelUrl } = res.Ok(); + if (signedDelUrl) { + return this.delObject(uri, signedDelUrl) + } + return Result.Ok(undefined); + + } +} + +class WALGateway extends BaseGateway implements StoreTypeGateway { + // WAL will not pollute to the cloud + readonly wals = new Map(); + constructor(sthis: SuperThis) { + super(sthis, "WALGateway"); + } + getWalKeyFromUri(uri: URI): Result { + const rKey = uri.getParamsResult({ + key: 0, + name: 0, + }) + if (rKey.isErr()) { + return Result.Err(rKey.Err()); + } + const { name, key } = rKey.Ok(); + return Result.Ok(`${name}:${key}`); + } + async getConn(uri: URI): Promise> { + const rKey = this.getWalKeyFromUri(uri); + if (rKey.isErr()) { + return Result.Err(rKey.Err()); + } + const wal = this.wals.get(rKey.Ok()); + if (!wal) { + return Result.Err(new NotFoundError("Not found")); + } + return Result.Ok(wal); + } + async putConn(uri: URI, body: Uint8Array): Promise> { + const rKey = this.getWalKeyFromUri(uri); + if (rKey.isErr()) { + return Result.Err(rKey.Err()); + } + this.wals.set(rKey.Ok(), body); + return Result.Ok(undefined); + } + async delConn(uri: URI): Promise> { + const rKey = this.getWalKeyFromUri(uri); + if (rKey.isErr()) { + return Result.Err(rKey.Err()); + } + this.wals.delete(rKey.Ok()); + return Result.Ok(undefined); + } +} + +const storeTypedGateways = new KeyedResolvOnce(); +function getStoreTypeGateway(sthis: SuperThis, uri: URI): StoreTypeGateway { + const store = uri.getParam("store"); + switch (store) { + case "data": + return storeTypedGateways.get(store).once(() => new DataGateway(sthis)); + case "meta": + return storeTypedGateways.get(store).once(() => new MetaGateway(sthis)); + case "wal": + return storeTypedGateways.get(store).once(() => new WALGateway(sthis)); + default: + throw ensureLogger(sthis, "getStoreTypeGateway").Error().Str("store", store).Msg("Invalid store type").ResultError(); + } +} + +const keyedConnections = new KeyedResolvOnce(); +const subscriptions = new Map void)[]>(); +const doServerSubscribe = new KeyedResolvOnce(); +const trackPuts = new Set(); +export class FireproofCloudGateway implements bs.Gateway { + readonly logger: Logger; + readonly sthis: SuperThis; constructor(sthis: SuperThis) { this.sthis = sthis; - this.id = sthis.nextId().str; this.logger = ensureLogger(sthis, "FireproofCloudGateway", { - url: () => this.url?.toString(), - this: this.id, - }); //.EnableLevel(Level.DEBUG); - // this.logger.Debug().Msg("constructor"); + this: true + }); } async buildUrl(baseUrl: URI, key: string): Promise> { return Result.Ok(baseUrl.build().setParam("key", key).URI()); } - // pso?: PartySocketOptions; async start(uri: URI): Promise> { - this.url = uri; - // this.logger.Debug().Msg("Starting FireproofCloudGateway"); - await this.sthis.start(); - const ret = uri.build().defParam("version", VERSION); - const rName = uri.getParamResult("name"); if (rName.isErr()) { return this.logger.Error().Err(rName).Msg("name not found").ResultError(); } ret.defParam("protocol", "wss"); - this.url = ret.URI(); - return Result.Ok(this.url); + return Result.Ok(ret.URI()); + } + + async get(uri: URI): Promise { + return getStoreTypeGateway(this.sthis, uri).get(uri, this.getCloudConnection(uri)); + } + + async put(uri: URI, body: Uint8Array): Promise> { + const ret = await getStoreTypeGateway(this.sthis, uri).put(uri, body, this.getCloudConnection(uri)); + if (ret.isOk()) { + if (uri.getParam("testMode")) { + trackPuts.add(uri.toString()); + } + } + return ret; + } + + async delete(uri: URI): Promise { + trackPuts.delete(uri.toString()); + return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); } async close(_uri: URI): Promise { - // console.log("close:gateway"); + console.log("close:gateway"); // await this.ready(); // this.logger.Debug().Msg("close"); // this.party?.close(); @@ -104,7 +483,6 @@ export class FireproofCloudGateway implements bs.Gateway { name: 0, protocol: 0, store: 0, - key: 0, storekey: 0, }); if (rParams.isErr()) { @@ -118,182 +496,98 @@ export class FireproofCloudGateway implements bs.Gateway { return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); } const connectionKey = { - tendantId: uri.build().getParam("tendenId", rfingerprint.Ok().fingerPrint) as string, + tenantId: uri.build().getParam("tendenId", rfingerprint.Ok().fingerPrint) as string, name: params.name, // protocol: params.protocol as ConnectionKey["protocol"], } satisfies ConnectionKey; + + const wsUrl = uri + .build() + .protocol(params.protocol === "ws" ? "ws" : "wss") + .appendRelative("ws") + .cleanParams() + .toString(); + return Result.Ok( - await wsSockets.get(pkKey(connectionKey)).once(async (cKey) => { - const wsUrl = uri - .build() - .protocol(params.protocol === "ws" ? "ws" : "wss") - .appendRelative("ws") - .URI(); + await keyedConnections.get(wsUrl).once(async (cKey) => { const ws = await newWebSocket(wsUrl); const waitOpen = new Future(); ws.onopen = () => { this.logger.Debug().Url(wsUrl).Msg("ws open"); waitOpen.resolve(); }; + ws.onerror = (err) => { + this.logger.Error().Err(err).Url(wsUrl).Msg("ws error"); + keyedConnections.unget(cKey); + }; ws.onclose = () => { - wsSockets.unget(cKey); + keyedConnections.unget(cKey); this.logger.Debug().Url(wsUrl).Msg("ws close"); }; await waitOpen.asPromise(); - return new ConnectionImpl(this.logger, ws, connectionKey); - }) - ); - } - - async getResSignedUrl(uri: URI, method: HttpMethods): Promise> { - const rParams = uri.getParamsResult({ - store: 0, - key: 0, - }); - if (rParams.isErr()) { - return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); - } - const rConn = await this.getCloudConnection(uri); - if (rConn.isErr()) { - return this.logger.Error().Err(rConn).Msg("Error in getCloudConnection").ResultError(); - } - const conn = rConn.Ok(); - - const { store, key } = rParams.Ok(); - - return conn.request( - buildReqSignedUrl(this.sthis, { - params: { - ...conn.params, - store: store as FPStoreTypes, - key, - method, - }, + return new ConnectionImpl(this.sthis, ws, connectionKey); }) ); } - async put(uri: URI, body: Uint8Array): Promise> { - const rResSignedUrl = await this.getResSignedUrl(uri, "PUT"); - if (rResSignedUrl.isErr()) { - return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); - } - const { - signedUrl: uploadUrl, - params: { store }, - } = rResSignedUrl.Ok(); - if (store === "meta") { - const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); - if (bodyRes.isErr()) { - return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); - } - body = bodyRes.Ok(); - } - this.logger.Debug().Any("url", { uri, uploadUrl }).Msg("put-fetch-url"); - const rUpload = await exception2Result(async () => fetch(uploadUrl, { method: "PUT", body })); - if (rUpload.isErr()) { - return this.logger.Error().Url(uploadUrl, "uploadUrl").Err(rUpload).Msg("Error in put fetch").ResultError(); - } - if (!rUpload.Ok().ok) { - return this.logger.Error().Url(uploadUrl, "uploadUrl").Http(rUpload.Ok()).Msg("Error in put fetch").ResultError(); - } - if (uri.getParam("testMode")) { - this.trackPuts.add(uri.toString()); - } - return Result.Ok(undefined); - } - - private readonly subscriberCallbacks = new Set<(data: Uint8Array) => void>(); - - private notifySubscribers(data: Uint8Array): void { - console.log("notifySubscribers", data); - for (const callback of this.subscriberCallbacks) { + private notifySubscribers(data: Uint8Array, callbacks: ((msg: Uint8Array) => void)[] = []): void { + for (const cb of callbacks) { try { - callback(data); + cb(data); } catch (error) { this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); } } } async subscribe(uri: URI, callback: (meta: Uint8Array) => void): Promise { - const store = uri.getParam("store"); - if (store !== "meta") { - return Result.Err(new Error("store must be meta")); - } - this.subscriberCallbacks.add(callback); - - // only ask for meta url if we are connected - // if (this.party) { - // const rSignedUrl = await SignedUrl.from(this.sthis, this.logger, uri, "GET"); - // if (rSignedUrl.isErr()) { - // return this.logger.Error().Err(rSignedUrl).Msg("Error in getOpUrl").ResultError(); - // } - // await this.sendReqSignedMetaUrl(rSignedUrl.Ok()); - // } - return Result.Ok(() => { - this.subscriberCallbacks.delete(callback); + const rParams = uri.getParamsResult({ + store: 0, + storekey: 0, }); - } - - async get(uri: URI): Promise { - const rResSignedUrl = await this.getResSignedUrl(uri, "GET"); - if (rResSignedUrl.isErr()) { - return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); - } - const { signedUrl: downloadUrl } = rResSignedUrl.Ok(); - this.logger.Debug().Url(downloadUrl).Msg("get-fetch-url"); - const rDownload = await exception2Result(async () => fetch(downloadUrl.toString(), { method: "GET" })); - if (rDownload.isErr()) { - return this.logger - .Error() - .Url(downloadUrl, "uploadUrl") - .Err(rDownload) - .Msg("Error in get downloadUrl") - .ResultError(); + if (rParams.isErr()) { + return this.logger.Error().Err(rParams).Msg("Error in subscribe").ResultError(); } - const download = rDownload.Ok(); - if (!download.ok) { - if (download.status === 404) { - return Result.Err(new NotFoundError("Not found")); - } - return this.logger.Error().Url(downloadUrl, "uploadUrl").Err(rDownload).Msg("Error in get fetch").ResultError(); + const { store } = rParams.Ok(); + if (store !== "meta") { + return Result.Err(new Error("store must be meta")); } - return Result.Ok(new Uint8Array(await download.arrayBuffer())); - } - - async delete(uri: URI): Promise { - const rResSignedUrl = await this.getResSignedUrl(uri, "DELETE"); - if (rResSignedUrl.isErr()) { - return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); + const rConn = await this.getCloudConnection(uri); + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in subscribe:getCloudConnection").ResultError(); } - const { signedUrl: deleteUrl } = rResSignedUrl.Ok(); - this.logger.Debug().Url(deleteUrl).Msg("delete-fetch-url"); - const rDelete = await exception2Result(async () => fetch(deleteUrl.toString(), { method: "DELETE" })); - if (rDelete.isErr()) { - return this.logger.Error().Url(deleteUrl, "uploadUrl").Err(rDelete).Msg("Error in get deleteURL").ResultError(); + const conn = rConn.Ok(); + const rResSubscribeMeta = await doServerSubscribe.get(pkKey(conn.key)).once(async () => { + const subId = this.sthis.nextId().str; + const fn = (subId: string) => (msg: MsgBase) => { + if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { + // console.log("onMessage", subId, conn.key, msg.metas); + this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), subscriptions.get(subId)); + } + }; + conn.onMessage(fn(subId)); + return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { waitType: "resSubscribeMeta"}); + }); + if (rResSubscribeMeta.isErr()) { + return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); } - const download = rDelete.Ok(); - if (!download.ok) { - if (download.status === 404) { - return Result.Err(new NotFoundError("Not found")); - } - return this.logger.Error().Url(deleteUrl, "uploadUrl").Err(rDelete).Msg("Error in del fetch").ResultError(); + const subId = rResSubscribeMeta.Ok().subscriberId; + let callbacks = subscriptions.get(subId); + if (!callbacks) { + callbacks = []; + subscriptions.set(subId, callbacks); } - this.trackPuts.delete(uri.toString()); - return Result.Ok(undefined); + callbacks.push(callback); + return Result.Ok(() => { + subscriptions.delete(subId); + }); } async destroy(_uri: URI): Promise> { - // await this.ready(); - for (const key of this.trackPuts) { - await this.delete(URI.from(key)); - } + await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))) return Result.Ok(undefined); } } -const wsSockets = new KeyedResolvOnce(); - function pkKey(set?: ConnectionKey): string { const ret = JSON.stringify( Object.entries(set || {}) diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 28900b0f..909a61c4 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -10,19 +10,8 @@ import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers. import { AwsClient } from "aws4fetch"; import { smokeDB } from "../../tests/helper"; import { registerFireproofCloudStoreProtocol } from "./client/gateway"; -import { calculatePreSignedUrl } from "./backend/server"; +import { calculatePreSignedUrl } from "./pre-signed-url"; import { newWebSocket } from "./new-websocket"; -// import { env, createExecutionContext, waitOnExecutionContext } from "cloudflare:test"; - -// const IncomingRequest = Request//; - -// const env: Env = { -// VERSION: "Test", -// STORAGE_URL: "http://localhost:8080", -// ACCESS_KEY_ID: "accessKeyId", -// SECRET_ACCESS_KEY: "secretAccessKey", -// TEST_DATE: "20241121T225359Z", -// } as Env; function testReqSignedUrl(tid = "test") { return { @@ -33,7 +22,7 @@ function testReqSignedUrl(tid = "test") { path: "/hallo", name: "test-name", method: "GET", - tendantId: "tenantId", + tenantId: "tenantId", store: "wal", key: "main", }, @@ -41,9 +30,9 @@ function testReqSignedUrl(tid = "test") { } satisfies ReqSignedUrl; } -async function testResSignedUrl(env: Env, tid = "test"): Promise { +async function testResSignedUrl(env: Env, tid?: string, amzDate?: string): Promise { const req = testReqSignedUrl(tid); - const rSignedUrl = await calculatePreSignedUrl(req, env); + const rSignedUrl = await calculatePreSignedUrl(req, env, amzDate); if (rSignedUrl.isErr()) { throw rSignedUrl.Err(); } @@ -51,7 +40,7 @@ async function testResSignedUrl(env: Env, tid = "test"): Promise { params: req.params, signedUrl: rSignedUrl.Ok().toString(), // `http://localhost:8080/tenantId/test-name/wal/main.json?tid=${tid}&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=accessKeyId%2F20241121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20241121T225359Z&X-Amz-Expires=86400&X-Amz-Signature=f52d5ecfbb6be93210dd57cb49ba1e426a8aee24a0738aedb636ae5722fcdded&X-Amz-SignedHeaders=host`, - tid: tid, + tid: tid || "test", type: "resSignedUrl", version: env.VERSION, } satisfies ResSignedUrl; @@ -61,7 +50,7 @@ describe("CloudBackendTest", () => { const sthis = mockSuperThis(); let env: Env; let pid: number; - const port = ~~(1024 + Math.random() * (0x10000 - 1024)); + const port = +(process.env.FP_WRANGLER_PORT || 0) || ~~(1024 + Math.random() * (0x10000 - 1024)); const wrangler = BuildURI.from("http://localhost") .port("" + port) .URI(); @@ -75,7 +64,10 @@ describe("CloudBackendTest", () => { env: { test: { vars: Env } }; }; env = wranglerFile.env.test.vars; - // $.verbose = true + if (process.env.FP_WRANGLER_PORT) { + return; + } + $.verbose = !!process.env.FP_DEBUG; const runningWrangler = $` wrangler dev -c ${tomlFile} --port ${port} --env test --no-show-interactive-dev-session & waitPid=$! @@ -91,16 +83,10 @@ describe("CloudBackendTest", () => { if (chunk.includes("Ready on http")) { waitReady.resolve(true); } - if ($.verbose) { - // eslint-disable-next-line no-console - console.log(">>", chunk.toString()); - } }); runningWrangler.stderr.on("data", (chunk) => { - if ($.verbose) { - // eslint-disable-next-line no-console - console.error("!!", chunk.toString()); - } + // eslint-disable-next-line no-console + console.error("!!", chunk.toString()); }); await waitReady.asPromise(); // await f.asPromise() @@ -126,7 +112,7 @@ describe("CloudBackendTest", () => { }); }); it("return 422 invalid json", async () => { - const res = await cfFetch("/get-signed-url", { method: "PUT" }); + const res = await cfFetch("/fp", { method: "PUT" }); expect(res.status).toBe(422); expect(await res.json()).toEqual({ message: "Unexpected end of JSON input", @@ -137,7 +123,7 @@ describe("CloudBackendTest", () => { }); it("return 422 illegal msg", async () => { - const res = await cfFetch("/get-signed-url", { + const res = await cfFetch("/fp", { method: "PUT", body: JSON.stringify({ bucket: "test", @@ -154,7 +140,7 @@ describe("CloudBackendTest", () => { }); it("return 200 msg", async () => { - const res = await cfFetch("/get-signed-url", { + const res = await cfFetch("/fp", { method: "PUT", body: JSON.stringify(testReqSignedUrl()), }); @@ -169,14 +155,21 @@ describe("CloudBackendTest", () => { const url = wrangler.build().appendRelative("/ws").protocol("ws:"); const so = await newWebSocket(url); const done = new Future(); - const tid = `test-${Math.random()}`; + let total = 10; + let tid = `${total}-test-${Math.random()}`; so.onopen = () => { so.send(JSON.stringify(testReqSignedUrl(tid))); }; so.onmessage = async (msg) => { try { - expect(JSON.parse(msg.data.toString())).toEqual(await testResSignedUrl(env, tid)); - done.resolve(true); + const res = JSON.parse(msg.data.toString()) as ResSignedUrl; + expect(res).toEqual(await testResSignedUrl(env, tid, URI.from(res.signedUrl).getParam("X-Amz-Date"))); + if (--total === 0) { + done.resolve(true); + } else { + tid = `${total}-test-${Math.random()}`; + so.send(JSON.stringify(testReqSignedUrl(tid))); + } } catch (err) { done.reject(err); } @@ -184,7 +177,7 @@ describe("CloudBackendTest", () => { so.onerror = (ev) => { assert.fail(`WebSocket error: ${ev}`); }; - return done.asPromise().then(() => so.close()); + return done.asPromise().then(() => so.close(1000, "done")); }) ); }); @@ -213,7 +206,11 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").asURL(), + base: wrangler + .build() + .protocol("fireproof:") + .setParam("protocol", "ws") + .setParam("testMode", "true") // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -225,8 +222,12 @@ describe("CloudBackendTest", () => { afterEach(async () => { // Clear the database before each test if (db) { + setInterval(() => console.log("Waiting for db to close"), 1000); + console.log("Closing db"); await db.close(); + console.log("Closed db"); await db.destroy(); + console.log("Destroyed db"); } }); @@ -297,10 +298,12 @@ describe("CloudBackendTest", () => { let didCall = false; + expect(metaGateway.subscribe).toBeTypeOf("function"); if (metaGateway.subscribe) { const future = new Future(); - const metaSubscribeResult = await metaGateway.subscribe(metaUrl?.Ok(), async (data: Uint8Array) => { + const metaSubscribeResult = await metaGateway.subscribe(metaUrl?.Ok(), (data: Uint8Array) => { + // console.log("data", data); const decodedData = sthis.txt.decode(data); expect(decodedData).toContain("parents"); didCall = true; @@ -345,7 +348,7 @@ describe("CloudBackendTest", () => { .setParam( "X-Amz-Signature", sthis.env.get("CF_PRESIGNED_SIGNATURE") || - "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" ) .asObj() ); diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index f2c750c7..72f90828 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,17 +1,43 @@ import { Logger, SuperThis } from "@fireproof/core"; +import { bs } from "@fireproof/core"; + +export interface ConnId { + readonly connId: string; +} + +// type AddConnId = Omit & ConnId & { readonly type: N }; + +interface NextId { + readonly nextId: SuperThis["nextId"]; +} + +export interface AuthType { + readonly type: "ucan"; +} + +export interface UCanAuth { + readonly type: "ucan"; + readonly params: { + readonly tbd: string + }; +} export interface MsgBase { readonly tid: string; readonly type: string; readonly version: string; + readonly auth?: AuthType; } export interface ErrorMsg extends MsgBase { readonly type: "error"; readonly message: string; } -export function MsgIsError(msg: MsgBase): msg is ErrorMsg { - return msg.type === "error"; +export function MsgIsError(rq: MsgBase): rq is ErrorMsg { + return rq.type === "error"; +} +export function MsgIsQSError(rq: ReqRes): rq is ReqRes { + return rq.res.type === "error" || rq.req.type === "error"; } export type HttpMethods = "GET" | "PUT" | "DELETE"; @@ -19,7 +45,7 @@ export type FPStoreTypes = "meta" | "data" | "wal"; export interface ConnectionKey { // readonly protocol: "ws" | "wss"; // ws or wss - readonly tendantId: string; + readonly tenantId: string; readonly name: string; } @@ -37,13 +63,23 @@ export interface Connection { readonly params: ConnectionKey; } +export interface ReqRes { + readonly req: Q; + readonly res: S; +} + +export interface ReqOptRes { + readonly req: Q; + readonly res?: S; +} + export interface ReqSignedUrlParam { readonly tid?: string; - readonly type?: "reqSignedUrl"; readonly version?: string; + readonly auth?: AuthType; readonly params: { // readonly protocol?: "ws" | "wss"; // ws or wss - readonly tendantId: string; + readonly tenantId: string; readonly name: string; readonly path?: string; readonly method: HttpMethods; @@ -56,7 +92,9 @@ export interface ReqSignedUrlParam { const VERSION = "FP-MSG-1.0"; -export function buildReqSignedUrl(sthis: SuperThis, req: ReqSignedUrlParam): ReqSignedUrl { +/* Signed URL */ + +export function buildReqSignedUrl(sthis: NextId, req: ReqSignedUrlParam): ReqSignedUrl { return { tid: sthis.nextId().str, type: "reqSignedUrl", @@ -69,6 +107,10 @@ export function buildReqSignedUrl(sthis: SuperThis, req: ReqSignedUrlParam): Req }; } +export function MsgIsReqSignedUrl(msg: MsgBase): msg is ReqSignedUrl { + return msg.type === "reqSignedUrl"; +} + export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { return { tid: req.tid, @@ -79,10 +121,10 @@ export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSign }; } -export function buildErrorMsg(logger: Logger, base: MsgBase, error: Error): ErrorMsg { +export function buildErrorMsg(logger: Logger, base: Partial, error: Error): ErrorMsg { const msg = { type: "error", - tid: base.tid, + tid: base.tid || "internal", message: error.message, version: VERSION, } satisfies ErrorMsg; @@ -105,3 +147,260 @@ export interface ResSignedUrl extends MsgBase { readonly params: SignedUrlParam; readonly signedUrl: string; } + +/* Subscribe Meta */ + +export interface ReqSubscribeMeta extends MsgBase { + readonly type: "reqSubscribeMeta"; + readonly subscriberId: string; + readonly key: ConnectionKey; +} + +// export type ReqSubscribeMetaWithConnId = AddConnId; + +// export function MsgIsReqSubscribeMetaWithConnId(req: MsgBase): req is ReqSubscribeMetaWithConnId { +// return req.type === "reqSubscribeMetaWithConnId"; +// } + +export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { + return req.type === "reqSubscribeMeta"; +} + +export function buildReqSubscriptMeta(sthis: NextId, ck: ConnectionKey, subscriberId: string): ReqSubscribeMeta { + return { + tid: sthis.nextId().str, + subscriberId, + type: "reqSubscribeMeta", + version: VERSION, + key: ck, + }; +} + +export interface ResSubscribeMeta extends MsgBase { + readonly type: "resSubscribeMeta"; + readonly subscriberId: string; + readonly connId: string; + readonly key: ConnectionKey; +} + +export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: ConnId): ResSubscribeMeta { + return { + tid: req.tid, + type: "resSubscribeMeta", + connId: ctx.connId, + subscriberId: req.subscriberId, + key: req.key, + version: VERSION, + }; +} + +export function MsgIsResSubscribeMeta(msg: MsgBase): msg is ResSubscribeMeta { + return msg.type === "resSubscribeMeta"; +} + + +/* Put Meta */ +export interface ReqPutMeta extends MsgBase { + readonly type: "reqPutMeta"; + readonly key: ConnectionKey; + readonly params: SignedUrlParam; + readonly metas: bs.DbMeta[]; +} + +// export type ReqPutMetaWithConnId = AddConnId; + +// export function MsgIsReqPutMetaWithConnId(msg: MsgBase): msg is ReqPutMetaWithConnId { +// return msg.type === "reqPutMetaWithConnId"; +// } + +export interface PutMetaParam { + readonly metaId: string; + readonly metas: bs.DbMeta[]; + readonly signedPutUrl: string; + readonly connId: string; +} + +export interface ResPutMeta extends MsgBase, PutMetaParam { + readonly type: "resPutMeta"; + readonly key: ConnectionKey; +} + +export function buildReqPutMeta( + sthis: NextId, + key: ConnectionKey, + signedUrlParams: SignedUrlParam, + metas: bs.DbMeta[], +): ReqPutMeta { + return { + tid: sthis.nextId().str, + type: "reqPutMeta", + version: VERSION, + params: signedUrlParams, + key, + metas, + }; +} + +export function MsgIsReqPutMeta(msg: MsgBase): msg is ReqPutMeta { + return msg.type === "reqPutMeta"; +} + +export function buildResPutMeta(req: ReqPutMeta, metaParam: PutMetaParam): ResPutMeta { + return { + ...metaParam, + tid: req.tid, + type: "resPutMeta", + key: req.key, + version: VERSION, + }; +} + +export function MsgIsResPutMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resPutMeta" && qs.req.type === "reqPutMeta"; +} + +export interface ConnSubId { + readonly connId: string; + readonly subscriberId: string; +} + +export interface UpdateMetaEvent extends MsgBase, ConnSubId { + readonly type: "updateMeta"; + readonly key: ConnectionKey; + readonly metaId: string; + readonly metas: bs.DbMeta[]; +} + +export function buildUpdateMetaEvent(rq: ReqRes, consub: ConnSubId): UpdateMetaEvent { + return { + ...consub, + tid: rq.res.tid, + type: "updateMeta", + key: rq.res.key, + metaId: rq.res.metaId, + metas: rq.req.metas, + version: rq.res.version, + }; +} + +export function MsgIsUpdateMetaEvent(msg: MsgBase): msg is UpdateMetaEvent { + return msg.type === "updateMeta"; +} + +/* Get Meta */ +export interface ReqGetMeta extends MsgBase { + readonly type: "reqGetMeta"; + readonly params: SignedUrlParam; + readonly key: ConnectionKey; +} + +// export type ReqGetMetaWithConnId = AddConnId; + +export function MsgIsReqGetMeta(msg: MsgBase): msg is ReqGetMeta { + return msg.type === "reqGetMeta"; +} + +// export function MsgIsReqGetMetaWithConnId(msg: MsgBase): msg is ReqGetMetaWithConnId { +// return msg.type === "reqGetMetaWithConnId"; +// } + +export interface GetMetaParam { + readonly params: SignedUrlParam; + readonly key: ConnectionKey; + readonly status: "found" | "not-found" | "redirect"; + readonly metas: bs.DbMeta[]; + readonly connId: string; + // if set client should query this url to retrieve the meta + readonly signedGetUrl?: string; +} + +export interface ResGetMeta extends MsgBase, GetMetaParam { + readonly type: "resGetMeta"; +} + +export function buildReqGetMeta( + sthis: NextId, + key: ConnectionKey, + signedUrlParams: SignedUrlParam +): ReqGetMeta { + return { + tid: sthis.nextId().str, + key, + type: "reqGetMeta", + version: VERSION, + params: signedUrlParams, + }; +} + +export function buildResGetMeta(req: ReqGetMeta, metaParam: GetMetaParam): ResGetMeta { + return { + ...metaParam, + tid: req.tid, + type: "resGetMeta", + key: req.key, + version: VERSION, + }; +} + +export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resGetMeta" && qs.req.type === "reqGetMeta"; +} + + +/* Del Meta */ +export interface ReqDelMeta extends MsgBase { + readonly type: "reqDelMeta"; + readonly params: SignedUrlParam; + readonly key: ConnectionKey; +} + +// export type ReqDelMetaWithConnId = AddConnId; + +// export function MsgIsReqDelMetaWithConnId(msg: MsgBase): msg is ReqDelMetaWithConnId { +// return msg.type === "reqDelMetaWithConnId"; +// } + +export interface DelMetaParam { + readonly params: SignedUrlParam; + readonly key: ConnectionKey; + readonly status: "found" | "not-found" | "redirect"; + readonly connId: string; + // if set client should query this url to retrieve the meta + readonly signedDelUrl?: string; +} + +export interface ResDelMeta extends MsgBase, DelMetaParam { + readonly type: "resDelMeta"; +} + +export function buildReqDelMeta( + sthis: NextId, + key: ConnectionKey, + signedUrlParams: SignedUrlParam +): ReqDelMeta { + return { + tid: sthis.nextId().str, + key, + type: "reqDelMeta", + version: VERSION, + params: signedUrlParams, + }; +} + +export function MsgIsReqDelMeta(msg: MsgBase): msg is ReqDelMeta { + return msg.type === "reqDelMeta"; +} + +export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDelMeta { + return { + ...metaParam, + tid: req.tid, + type: "resDelMeta", + key: req.key, + version: VERSION, + }; +} + +export function MsgIsResDelMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; +} \ No newline at end of file diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts new file mode 100644 index 00000000..2a4ed25f --- /dev/null +++ b/src/cloud/pre-signed-url.ts @@ -0,0 +1,53 @@ +import { Result, URI, BuildURI } from "@adviser/cement"; +import { AwsClient } from "aws4fetch"; +import { Env } from "./backend/env"; +import { ReqSignedUrl } from "./msg-types"; + +export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env, amzDate?: string): Promise> { + let store: string = req.params.store; + if (req.params.index?.length) { + store = `${store}-${req.params.index}`; + } + const expiresInSeconds = req.params.expires || 60 * 60; + + let suffix = ""; + switch (req.params.store) { + case "wal": + case "meta": + suffix = ".json"; + break; + default: + break; + } + + const opUrl = BuildURI.from(env.STORAGE_URL) + // .protocol(vals.protocol === "ws" ? "http:" : "https:") + .setParam("X-Amz-Expires", expiresInSeconds.toString()) + .setParam("tid", req.tid) + .appendRelative(req.params.tenantId) + .appendRelative(req.params.name) + .appendRelative(store) + .appendRelative(`${req.params.key}${suffix}`) + .URI(); + const a4f = new AwsClient({ + accessKeyId: env.ACCESS_KEY_ID, + secretAccessKey: env.SECRET_ACCESS_KEY, + region: env.REGION || "us-east-1", + service: "s3", + }); + const signedUrl = await a4f + .sign( + new Request(opUrl.toString(), { + method: req.params.method, + }), + { + aws: { + signQuery: true, + datetime: amzDate, + // datetime: env.TEST_DATE, + }, + } + ) + .then((res) => res.url); + return Result.Ok(URI.from(signedUrl)); +} diff --git a/version-copy-package.ts b/version-copy-package.ts index 8f8986bf..1db77a7a 100644 --- a/version-copy-package.ts +++ b/version-copy-package.ts @@ -1,3 +1,26 @@ +/* eslint-disable no-console */ +import { $ } from "zx"; +import { command, flag, positional, run, boolean, string } from "cmd-ts"; +import * as fs from "fs/promises"; +import * as path from "path"; + +async function patchVersion(packageJson: Record) { + let version = "refs/tags/v0.0.0-smoke"; + if (process.env.GITHUB_REF && process.env.GITHUB_REF.startsWith("refs/tags/v")) { + version = process.env.GITHUB_REF; + } + version = version.split("/").slice(-1)[0].replace(/^v/, ""); + console.log(`Patch version ${version} in package.json`); + packageJson.version = version; +} + +async function copyFilesToDist(destDir: string) { + for (const file of ["./.gitignore", "./LICENSE.md"]) { + await fs.copyFile(file, path.join(destDir, file)); + } +} + +async function main() { const cmd = command({ name: "version-copy-package", description: "prepare a package.json for a release", From 70c4f0782c028d3ae45de045e9689bf6ea336153 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 08:00:26 +0000 Subject: [PATCH 03/83] chore(deps): bump better-sqlite3 from 11.5.0 to 11.6.0 Bumps [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) from 11.5.0 to 11.6.0. - [Release notes](https://github.com/WiseLibs/better-sqlite3/releases) - [Commits](https://github.com/WiseLibs/better-sqlite3/compare/v11.5.0...v11.6.0) --- updated-dependencies: - dependency-name: better-sqlite3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 92871671..d8b60142 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "assert": "^2.1.0", "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", + "better-sqlite3": "^11.6.0", "cborg": "^4.2.6", "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", From 91bd86f739f7479fa6b3f96487629d8d11a08c97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:12:23 +0000 Subject: [PATCH 04/83] chore(deps): bump @fireproof/core from 0.19.113 to 0.19.114 Bumps [@fireproof/core](https://github.com/fireproof-storage/fireproof) from 0.19.113 to 0.19.114. - [Commits](https://github.com/fireproof-storage/fireproof/compare/v0.19.113...v0.19.114) --- updated-dependencies: - dependency-name: "@fireproof/core" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pnpm-lock.yaml | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5da8336f..87e00895 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -164,7 +164,7 @@ importers: version: 8.5.13 '@typescript-eslint/typescript-estree': specifier: ^8.16.0 - version: 8.16.0(typescript@5.7.2) + version: 8.17.0(typescript@5.7.2) esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -1639,6 +1639,10 @@ packages: resolution: {integrity: sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.17.0': + resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.16.0': resolution: {integrity: sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1648,6 +1652,15 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.17.0': + resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@8.16.0': resolution: {integrity: sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1662,6 +1675,10 @@ packages: resolution: {integrity: sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.17.0': + resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ucanto/client@9.0.1': resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} @@ -5687,6 +5704,8 @@ snapshots: '@typescript-eslint/types@8.16.0': {} + '@typescript-eslint/types@8.17.0': {} + '@typescript-eslint/typescript-estree@8.16.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.16.0 @@ -5702,6 +5721,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.16.0(eslint@9.16.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) @@ -5719,6 +5753,11 @@ snapshots: '@typescript-eslint/types': 8.16.0 eslint-visitor-keys: 4.2.0 + '@typescript-eslint/visitor-keys@8.17.0': + dependencies: + '@typescript-eslint/types': 8.17.0 + eslint-visitor-keys: 4.2.0 + '@ucanto/client@9.0.1': dependencies: '@ucanto/core': 10.0.1 From dbcc6166c8a1ab2dfc6be9af262b3fcfd734bdca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:13:42 +0000 Subject: [PATCH 05/83] chore(deps): bump @web3-storage/w3up-client from 16.5.1 to 16.5.2 Bumps [@web3-storage/w3up-client](https://github.com/storacha/w3up/tree/HEAD/packages/w3up-client) from 16.5.1 to 16.5.2. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/w3up-client/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/w3up-client-v16.5.2/packages/w3up-client) --- updated-dependencies: - dependency-name: "@web3-storage/w3up-client" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package.json b/package.json index d8b60142..5930e7ba 100644 --- a/package.json +++ b/package.json @@ -121,12 +121,6 @@ "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", - "@ucanto/client": "^9.0.1", - "@ucanto/core": "^10.0.1", - "@ucanto/interface": "^10.0.1", - "@ucanto/principal": "^9.0.1", - "@ucanto/transport": "^9.1.1", - "@ucanto/validator": "^9.0.2", "assert": "^2.1.0", "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", From 4bd85674096d790dd62d1ffe27b73c849625222f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:16:56 +0000 Subject: [PATCH 06/83] chore(deps-dev): bump vite from 5.4.11 to 6.0.2 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.11 to 6.0.2. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.0.2/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pnpm-lock.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 87e00895..d00c27df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3270,6 +3270,10 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + prebuild-install@7.1.2: resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} engines: {node: '>=10'} @@ -7793,6 +7797,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.4.49: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prebuild-install@7.1.2: dependencies: detect-libc: 2.0.3 From c4f8bedeab24db8e3771bfc48708c8552759efca Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 15 Nov 2024 09:20:11 +0100 Subject: [PATCH 07/83] chore: intro of local cloud tests chore: cloud now generated pre-signed-urls chore: fix signature chore: remove env version chore: remove console.log chore: now we have cloud-backend tests chore: the ng redirecting backend chore: everything except subscript --- package.json | 7 +- pnpm-lock.yaml | 183 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 178 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 5930e7ba..5b417302 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "xpretest:cloud": "bash ./tests/start-cloud.sh", + "pretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "xposttest:cloud": "docker rm -f cloud", + "posttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -106,6 +106,8 @@ "@fireproof/vendor": "1.0.0", "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", + "@cloudflare/vitest-pool-workers": "^0.5.30", + "@cloudflare/workers-types": "^4.20241112.0", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", @@ -125,6 +127,7 @@ "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", "better-sqlite3": "^11.6.0", + "aws4fetch": "^1.0.20", "cborg": "^4.2.6", "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d00c27df..78ba0ef5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@aws-sdk/client-s3': specifier: ^3.703.0 version: 3.703.0 + '@cloudflare/vitest-pool-workers': + specifier: ^0.5.30 + version: 0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) '@cloudflare/workers-types': specifier: ^4.20241112.0 version: 4.20241205.0 @@ -384,6 +387,13 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} + '@cloudflare/vitest-pool-workers@0.5.33': + resolution: {integrity: sha512-gsMArZ7fN9WB8blVIK8kVPXV8zI7JuoQN6n4grBYMmJgqfLrWE5N8NnEz0O5qagyLQJvD9TxD16WZOzVT/fbzw==} + peerDependencies: + '@vitest/runner': 2.0.x - 2.1.x + '@vitest/snapshot': 2.0.x - 2.1.x + vitest: 2.0.x - 2.1.x + '@cloudflare/workerd-darwin-64@1.20240718.0': resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} engines: {node: '>=16'} @@ -396,6 +406,12 @@ packages: cpu: [x64] os: [darwin] + '@cloudflare/workerd-darwin-64@1.20241106.2': + resolution: {integrity: sha512-p3PzgiMBp9xKo4dMINM1RkrC+miUtz65IuuMCEdCa5QZTM0eyEGcBj1A9/lmS3wW72oMfRTo6CxCkqPteFJeBA==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + '@cloudflare/workerd-darwin-arm64@1.20240718.0': resolution: {integrity: sha512-nlr4gaOO5gcJerILJQph3+2rnas/nx/lYsuaot1ntHu4LAPBoQo1q/Pucj2cSIav4UiMzTbDmoDwPlls4Kteog==} engines: {node: '>=16'} @@ -408,6 +424,12 @@ packages: cpu: [arm64] os: [darwin] + '@cloudflare/workerd-darwin-arm64@1.20241106.2': + resolution: {integrity: sha512-AZQTAKG6bP9z0SKSXQGlXR2K2MQnDMtKC78NGjN0NOcjALTsFlLFhczaLvmuJjsT16k9yJUq2Gl+NG4ao/qgvg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + '@cloudflare/workerd-linux-64@1.20240718.0': resolution: {integrity: sha512-LJ/k3y47pBcjax0ee4K+6ZRrSsqWlfU4lbU8Dn6u5tSC9yzwI4YFNXDrKWInB0vd7RT3w4Yqq1S6ZEbfRrqVUg==} engines: {node: '>=16'} @@ -420,6 +442,12 @@ packages: cpu: [x64] os: [linux] + '@cloudflare/workerd-linux-64@1.20241106.2': + resolution: {integrity: sha512-TWIcVdUzU7w7YP2OEIgTDtNl9jyzjxOptjRDw7jhSUsQy/02IjBLP+ZnNpgB5CUJ1tCbcOp1L2IGhZmayd7OEQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + '@cloudflare/workerd-linux-arm64@1.20240718.0': resolution: {integrity: sha512-zBEZvy88EcAMGRGfuVtS00Yl7lJdUM9sH7i651OoL+q0Plv9kphlCC0REQPwzxrEYT1qibSYtWcD9IxQGgx2/g==} engines: {node: '>=16'} @@ -432,6 +460,12 @@ packages: cpu: [arm64] os: [linux] + '@cloudflare/workerd-linux-arm64@1.20241106.2': + resolution: {integrity: sha512-f5Mn9IzfLs9yGjB2UCcKh+I7Ahiw6xqiQ9f/FGsHjsgLELjJ8JCKBwXmc9WdfNmVPae5jNCg2N5qVfDoWBKbCA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + '@cloudflare/workerd-windows-64@1.20240718.0': resolution: {integrity: sha512-YpCRvvT47XanFum7C3SedOZKK6BfVhqmwdAAVAQFyc4gsCdegZo0JkUkdloC/jwuWlbCACOG2HTADHOqyeolzQ==} engines: {node: '>=16'} @@ -444,10 +478,20 @@ packages: cpu: [x64] os: [win32] + '@cloudflare/workerd-windows-64@1.20241106.2': + resolution: {integrity: sha512-kdLExN3rktax23iHUKP7AHQP0HT0yGHik58fMP4kExjsMnwxw92TLI3n4HlmEqsbtMtwr9rhTJVaMBRUXq0aXw==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + '@cloudflare/workers-shared@0.9.0': resolution: {integrity: sha512-eP6Ir45uPbKnpADVzUCtkRUYxYxjB1Ew6n/whTJvHu8H4m93USHAceCMm736VBZdlxuhXXUjEP3fCUxKPn+cfw==} engines: {node: '>=16.7.0'} + '@cloudflare/workers-shared@0.9.1': + resolution: {integrity: sha512-56w4pL5D6ODw7+SieMgdwrwNyyT7tY8H4UPD4/95TSBVjqDcMPq0Dr+D4rJ+nHK+290o4ZnSiOOiKqRMqy6tPg==} + engines: {node: '>=16.7.0'} + '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} @@ -1928,6 +1972,9 @@ packages: bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + birpc@0.2.14: + resolution: {integrity: sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -2014,6 +2061,9 @@ packages: chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + cli-color@2.0.4: resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==} engines: {node: '>=0.10'} @@ -2123,6 +2173,9 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + devalue@4.3.3: + resolution: {integrity: sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -2964,6 +3017,11 @@ packages: engines: {node: '>=16.13'} hasBin: true + miniflare@3.20241106.2: + resolution: {integrity: sha512-40JAPtNFMFrSW41CSxPgDykX4CgDokDfTZgDYYL8dsODb7pdAlj/dvlDPnaonkyXjRO7svyDwAavQT6IdagMwA==} + engines: {node: '>=16.13'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3270,10 +3328,6 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} - engines: {node: ^10 || ^12 || >=14} - prebuild-install@7.1.2: resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} engines: {node: '>=10'} @@ -4019,6 +4073,11 @@ packages: engines: {node: '>=16'} hasBin: true + workerd@1.20241106.2: + resolution: {integrity: sha512-Xw2hVIXA9MvDSHx3IX55ouGRPsQUzG0oadRVeQRs5xwgmiKshR0ompyYDO1JUvozJazfjcCSdgV8jyLcPqNIDA==} + engines: {node: '>=16'} + hasBin: true + wrangler@3.91.0: resolution: {integrity: sha512-Hdzn6wbY9cz5kL85ZUvWLwLIH7nPaEVRblfms40jhRf4qQO/Zf74aFlku8rQFbe8/2aVZFaxJVfBd6JQMeMSBQ==} engines: {node: '>=16.17.0'} @@ -4029,6 +4088,16 @@ packages: '@cloudflare/workers-types': optional: true + wrangler@3.92.0: + resolution: {integrity: sha512-MC+s+stSYQKXEn7ucENhzrw+RyMc5bSIRQ2EVcjCtqjAtO82uKQBatW2YXK5hkQOZg9Kfcdqgkcnpf/Bn94FiA==} + engines: {node: '>=16.17.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20241106.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -4602,41 +4671,80 @@ snapshots: dependencies: mime: 3.0.0 + '@cloudflare/vitest-pool-workers@0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1))': + dependencies: + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + birpc: 0.2.14 + cjs-module-lexer: 1.4.1 + devalue: 4.3.3 + esbuild: 0.17.19 + miniflare: 3.20241106.2 + semver: 7.6.3 + vitest: 2.1.8(@types/node@22.10.1) + wrangler: 3.92.0(@cloudflare/workers-types@4.20241205.0) + zod: 3.23.8 + transitivePeerDependencies: + - '@cloudflare/workers-types' + - bufferutil + - supports-color + - utf-8-validate + '@cloudflare/workerd-darwin-64@1.20240718.0': optional: true '@cloudflare/workerd-darwin-64@1.20241106.1': optional: true + '@cloudflare/workerd-darwin-64@1.20241106.2': + optional: true + '@cloudflare/workerd-darwin-arm64@1.20240718.0': optional: true '@cloudflare/workerd-darwin-arm64@1.20241106.1': optional: true + '@cloudflare/workerd-darwin-arm64@1.20241106.2': + optional: true + '@cloudflare/workerd-linux-64@1.20240718.0': optional: true '@cloudflare/workerd-linux-64@1.20241106.1': optional: true + '@cloudflare/workerd-linux-64@1.20241106.2': + optional: true + '@cloudflare/workerd-linux-arm64@1.20240718.0': optional: true '@cloudflare/workerd-linux-arm64@1.20241106.1': optional: true + '@cloudflare/workerd-linux-arm64@1.20241106.2': + optional: true + '@cloudflare/workerd-windows-64@1.20240718.0': optional: true '@cloudflare/workerd-windows-64@1.20241106.1': optional: true + '@cloudflare/workerd-windows-64@1.20241106.2': + optional: true + '@cloudflare/workers-shared@0.9.0': dependencies: mime: 3.0.0 zod: 3.23.8 + '@cloudflare/workers-shared@0.9.1': + dependencies: + mime: 3.0.0 + zod: 3.23.8 + '@cloudflare/workers-types@4.20240718.0': {} '@cloudflare/workers-types@4.20241205.0': {} @@ -6179,6 +6287,8 @@ snapshots: dependencies: file-uri-to-path: 1.0.0 + birpc@0.2.14: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -6280,6 +6390,8 @@ snapshots: chownr@1.1.4: {} + cjs-module-lexer@1.4.1: {} + cli-color@2.0.4: dependencies: d: 1.0.2 @@ -6420,6 +6532,8 @@ snapshots: detect-libc@2.0.3: {} + devalue@4.3.3: {} + didyoumean@1.2.2: {} dot-prop@7.2.0: @@ -7495,6 +7609,25 @@ snapshots: - supports-color - utf-8-validate + miniflare@3.20241106.2: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.4 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20241106.2 + ws: 8.18.0 + youch: 3.3.4 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -7797,12 +7930,6 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.4.49: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.1 - source-map-js: 1.2.1 - prebuild-install@7.1.2: dependencies: detect-libc: 2.0.3 @@ -8594,6 +8721,14 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241106.1 '@cloudflare/workerd-windows-64': 1.20241106.1 + workerd@1.20241106.2: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20241106.2 + '@cloudflare/workerd-darwin-arm64': 1.20241106.2 + '@cloudflare/workerd-linux-64': 1.20241106.2 + '@cloudflare/workerd-linux-arm64': 1.20241106.2 + '@cloudflare/workerd-windows-64': 1.20241106.2 + wrangler@3.91.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -8623,6 +8758,34 @@ snapshots: - supports-color - utf-8-validate + wrangler@3.92.0(@cloudflare/workers-types@4.20241205.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.9.1 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 4.0.1 + date-fns: 4.1.0 + esbuild: 0.17.19 + itty-time: 1.0.6 + miniflare: 3.20241106.2 + nanoid: 3.3.7 + path-to-regexp: 6.3.0 + resolve: 1.22.8 + selfsigned: 2.4.1 + source-map: 0.6.1 + unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0 + workerd: 1.20241106.2 + xxhash-wasm: 1.0.2 + optionalDependencies: + '@cloudflare/workers-types': 4.20241205.0 + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 From 0a64bfe1fd2f1e0353e243190b0c054432569b6d Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 28 Nov 2024 23:13:40 +0100 Subject: [PATCH 08/83] chore: almost done --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5b417302..5e259bc1 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "pretest:cloud": "bash ./tests/start-cloud.sh", + "xpretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "posttest:cloud": "docker rm -f cloud", + "xposttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -108,6 +108,7 @@ "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241112.0", + "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", From b230ea4086c6a16bbdb384612f4d8f9b9e545859 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 2 Dec 2024 10:17:58 +0100 Subject: [PATCH 09/83] chore: wip --- package.json | 1 + pnpm-lock.yaml | 194 ++++++++++++++++++++++++++++++++++++ src/cloud/backend/server.ts | 56 ++++++++--- src/cloud/client/gateway.ts | 57 ++++++++--- src/cloud/cloud.test.ts | 163 ++++++++++++++++++++++++++++-- src/cloud/msg-types.ts | 30 +++--- 6 files changed, 453 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 5e259bc1..7a646b26 100644 --- a/package.json +++ b/package.json @@ -109,6 +109,7 @@ "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", + "@fireproof/encrypted-blockstore": "^0.18.0", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78ba0ef5..45b3b230 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@fireproof/core': specifier: 0.19.114 version: 0.19.114(react@18.3.1)(typescript@5.7.2) + '@fireproof/encrypted-blockstore': + specifier: ^0.18.0 + version: 0.18.0(encoding@0.1.13)(eslint@9.16.0) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 @@ -1113,6 +1116,9 @@ packages: peerDependencies: react: ^18.3.1 + '@fireproof/encrypted-blockstore@0.18.0': + resolution: {integrity: sha512-W9uUl3LH2o6+TqE4uv9879w9GyRw+YA7aMc4RLfwBr+uZU/12qLPFBCd90YCyIUsYboX4AhghBRLCc2K2yOWiw==} + '@fireproof/vendor@1.0.0': resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} @@ -1264,6 +1270,17 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@peculiar/asn1-schema@2.3.13': + resolution: {integrity: sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g==} + + '@peculiar/json-schema@1.1.12': + resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} + engines: {node: '>=8.0.0'} + + '@peculiar/webcrypto@1.5.0': + resolution: {integrity: sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==} + engines: {node: '>=10.12.0'} + '@perma/map@1.0.3': resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} @@ -1913,6 +1930,10 @@ packages: as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + asn1js@3.0.5: + resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} + engines: {node: '>=12.0.0'} + assert-is-function-x@3.1.2: resolution: {integrity: sha512-FiMv0RYR/eMQk2EOMYJKvm+QFQa2AQzjccI9rN4cpvNd6M+UuobnV6m0sqIO5U+Q2LillGwaya16MRGa2Sr6+w==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -2003,6 +2024,13 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + builtins@5.1.0: + resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==} + bundle-require@5.0.0: resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2268,6 +2296,24 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-n@16.6.2: + resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + eslint-scope@8.2.0: resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2499,6 +2545,10 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -2583,6 +2633,9 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + idb@8.0.0: resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} @@ -2664,6 +2717,10 @@ packages: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -3200,6 +3257,10 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@6.1.0: resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} engines: {node: '>=18'} @@ -3376,6 +3437,13 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.1.3: + resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} + engines: {node: '>=6.0.0'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -3789,6 +3857,9 @@ packages: tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsup@8.3.5: resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==} engines: {node: '>=18'} @@ -3820,6 +3891,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} @@ -3895,6 +3970,10 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + uuidv7@0.6.3: + resolution: {integrity: sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==} + hasBin: true + valibot@1.0.0-beta.7: resolution: {integrity: sha512-8CsDu3tqyg7quEHMzCOYdQ/d9NlmVQKtd4AlFje6oJpvqo70EIZjSakKIeWltJyNAiUtdtLe0LAk4625gavoeQ==} peerDependencies: @@ -4023,6 +4102,9 @@ packages: engines: {node: '>=12.0.0'} hasBin: true + webcrypto-core@1.8.1: + resolution: {integrity: sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -5105,6 +5187,27 @@ snapshots: transitivePeerDependencies: - typescript + '@fireproof/encrypted-blockstore@0.18.0(encoding@0.1.13)(eslint@9.16.0)': + dependencies: + '@ipld/car': 5.3.3 + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.3 + '@ipld/unixfs': 2.2.0 + '@peculiar/webcrypto': 1.5.0 + '@web3-storage/pail': 0.6.0 + charwise: 3.0.1 + cross-fetch: 4.0.0(encoding@0.1.13) + eslint-plugin-n: 16.6.2(eslint@9.16.0) + idb: 7.1.1 + ipfs-unixfs-exporter: 13.6.1 + multiformats: 12.1.3 + p-limit: 4.0.0 + prolly-trees: 1.0.4 + uuidv7: 0.6.3 + transitivePeerDependencies: + - encoding + - eslint + '@fireproof/vendor@1.0.0': dependencies: '@ipld/dag-pb': 4.1.2 @@ -5289,6 +5392,24 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@peculiar/asn1-schema@2.3.13': + dependencies: + asn1js: 3.0.5 + pvtsutils: 1.3.6 + tslib: 2.7.0 + + '@peculiar/json-schema@1.1.12': + dependencies: + tslib: 2.7.0 + + '@peculiar/webcrypto@1.5.0': + dependencies: + '@peculiar/asn1-schema': 2.3.13 + '@peculiar/json-schema': 1.1.12 + pvtsutils: 1.3.6 + tslib: 2.7.0 + webcrypto-core: 1.8.1 + '@perma/map@1.0.3': dependencies: '@multiformats/murmur3': 2.1.8 @@ -6216,6 +6337,12 @@ snapshots: dependencies: printable-characters: 1.0.42 + asn1js@3.0.5: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.3 + tslib: 2.7.0 + assert-is-function-x@3.1.2: dependencies: is-function-x: 4.1.2 @@ -6324,6 +6451,12 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + builtin-modules@3.3.0: {} + + builtins@5.1.0: + dependencies: + semver: 7.6.3 + bundle-require@5.0.0(esbuild@0.24.0): dependencies: esbuild: 0.24.0 @@ -6710,6 +6843,33 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-compat-utils@0.5.1(eslint@9.16.0): + dependencies: + eslint: 9.16.0 + semver: 7.6.3 + + eslint-plugin-es-x@7.8.0(eslint@9.16.0): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + '@eslint-community/regexpp': 4.12.1 + eslint: 9.16.0 + eslint-compat-utils: 0.5.1(eslint@9.16.0) + + eslint-plugin-n@16.6.2(eslint@9.16.0): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + builtins: 5.1.0 + eslint: 9.16.0 + eslint-plugin-es-x: 7.8.0(eslint@9.16.0) + get-tsconfig: 4.8.1 + globals: 13.24.0 + ignore: 5.3.2 + is-builtin-module: 3.2.1 + is-core-module: 2.15.1 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 7.6.3 + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 @@ -6983,6 +7143,10 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + globals@14.0.0: {} globrex@0.1.2: {} @@ -7054,6 +7218,8 @@ snapshots: idb-keyval@6.2.1: {} + idb@7.1.1: {} + idb@8.0.0: {} ieee754@1.2.1: {} @@ -7184,6 +7350,10 @@ snapshots: is-buffer@2.0.5: {} + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + is-callable@1.2.7: {} is-core-module@2.15.1: @@ -7812,6 +7982,10 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-limit@4.0.0: + dependencies: + yocto-queue: 1.1.1 + p-limit@6.1.0: dependencies: yocto-queue: 1.1.1 @@ -7996,6 +8170,12 @@ snapshots: punycode@2.3.1: {} + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.1.3: {} + queue-microtask@1.2.3: {} rabin-rs@2.1.0: {} @@ -8430,6 +8610,8 @@ snapshots: tslib@2.7.0: {} + tslib@2.8.1: {} + tsup@8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.5.1): dependencies: bundle-require: 5.0.0(esbuild@0.24.0) @@ -8472,6 +8654,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@0.20.2: {} + type-fest@2.19.0: {} type-fest@4.26.1: {} @@ -8557,6 +8741,8 @@ snapshots: uuid@9.0.1: {} + uuidv7@0.6.3: {} + valibot@1.0.0-beta.7(typescript@5.7.2): optionalDependencies: typescript: 5.7.2 @@ -8659,6 +8845,14 @@ snapshots: transitivePeerDependencies: - debug + webcrypto-core@1.8.1: + dependencies: + '@peculiar/asn1-schema': 2.3.13 + '@peculiar/json-schema': 1.1.12 + asn1js: 3.0.5 + pvtsutils: 1.3.6 + tslib: 2.7.0 + webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index bb656b6d..8c7048ca 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -32,7 +32,7 @@ import { ResSubscribeMeta, } from "../msg-types"; // import { Hono } from "hono"; -import { bs, NotFoundError } from "@fireproof/core"; +import { CRDTEntry, NotFoundError } from "@fireproof/core"; import { DurableObject } from "cloudflare:workers"; import { calculatePreSignedUrl } from "../pre-signed-url"; @@ -108,6 +108,7 @@ export class FPMetaGroups extends DurableObject { return CFMsgProcessor.dispatch(() => JSON.parse(msg.toString()), { env: this.env, + dobj: this.ctx }, async (req: MsgBase, ictx: CtxBase) => { if (req.auth) { // do ucan magic @@ -130,7 +131,7 @@ export class FPMetaGroups extends DurableObject { this.updateMeta(qs); break; } - case MsgIsResSubscribeMeta(qs.res): { + case MsgIsResSubscribeMeta(qs): { const group = { ...qs.ctx.group, group: qs.res } satisfies FPMetaGroup; ws.serializeAttachment(group); this.updateMeta(qs) @@ -145,7 +146,7 @@ export class FPMetaGroups extends DurableObject { const path = URI.from(req.url).pathname switch (path) { case "/fp": { - const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); + const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env, dobj: this.ctx }); return json(rq.res, MsgIsQSError(rq) ? 422 : 200); } case "/ws": { @@ -163,7 +164,7 @@ export class FPMetaGroups extends DurableObject { } default: { const logger = ensureLogger(this.env); - return json(buildErrorMsg(logger, { tid: "internal", }, new NotFoundError(`Notfound:${c.req.path}`)), 404); + return json(buildErrorMsg(logger, { tid: "internal", }, new NotFoundError(`Notfound:${path}`)), 404); } } } @@ -176,8 +177,8 @@ export class FPMetaGroups extends DurableObject { } } - updateMeta(qs: ReqRes): void { - const wsSocks = this.ctx.getWebSockets() + updateMeta(qs: ReqResCtx): void { + const wsSocks = qs.ctx.dobj.getWebSockets() const groupWs = wsSocks.map(ws => ({ ws, group: ws.deserializeAttachment() as FPMetaGroup })); @@ -186,8 +187,12 @@ export class FPMetaGroups extends DurableObject { acc.push(...group.lastMeta.metas) } return acc - }, [] as bs.DbMeta[]) + }, [] as CRDTEntry[]) const now = new Date() + const joinedQS = { + req: { ...qs.req, metas: joinedMeta }, + res: qs.res, + } groupWs.forEach(({ ws, group }) => { ws.serializeAttachment({ ...group, @@ -195,9 +200,9 @@ export class FPMetaGroups extends DurableObject { lastUsed: now } satisfies FPMetaGroup) ws.send( + // this is not the best way to do this JSON.stringify( - buildUpdateMetaEvent(qs, { - metas: joinedMeta, + buildUpdateMetaEvent(joinedQS, { subscriberId: group.group.subscriberId, connId: group.group.connId, }) @@ -212,7 +217,7 @@ export class FPMetaGroups extends DurableObject { interface MsgProcessor { dispatch(decodeFn: () => Promise): Promise>; - signedUrl(req: ReqSignedUrl): Promise; + signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise; subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise; delMeta(req: ReqDelMeta, ctx: CtxBase): Promise; @@ -228,9 +233,11 @@ interface CFMsgProcessorParams { interface CtxBaseParam { readonly env: Env readonly module?: string + readonly dobj: DurableObjectState } interface CtxBase { + readonly dobj: DurableObjectState; readonly env: Env; readonly logger: Logger; } @@ -330,11 +337,34 @@ class CFMsgProcessor implements MsgProcessor { } async delMeta(req: ReqDelMeta, ctx: CtxWithGroup): Promise { - return buildResDelMeta(req) + // delete meta does nothing in this implementation + // if you delete meta basically you are deleting the whole ledger + return buildResDelMeta(req, { + params: req.params, + status: "unsupported", + connId: ctx.group.connId, + }) } async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { - return buildResGetMeta(req) + const rSignedUrl = await calculatePreSignedUrl( + { + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: { ...req.params, method: "GET" }, + }, + this.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + return buildResGetMeta(req, { + signedGetUrl: rSignedUrl.Ok().toString(), + status: "found", + metas: [], + connId: "" + }) } async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { @@ -343,7 +373,7 @@ class CFMsgProcessor implements MsgProcessor { tid: req.tid, type: "reqSignedUrl", version: req.version, - params: req.params, + params: { ...req.params, method: "PUT" }, }, this.env ); diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index c2231f05..bdd912b9 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -1,6 +1,6 @@ // import PartySocket, { PartySocketOptions } from "partysocket"; import { Result, URI, KeyedResolvOnce, exception2Result, Future } from "@adviser/cement"; -import { bs, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; +import { bs, CRDTEntry, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; import { buildErrorMsg, buildReqDelMeta, @@ -321,7 +321,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { if (bodyRes.isErr()) { return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); } - const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as bs.DbMeta[]; + const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); const rsu = this.prepareReqSignedUrl(uri, "PUT", conn.key); if (rsu.isErr()) { @@ -421,7 +421,13 @@ function getStoreTypeGateway(sthis: SuperThis, uri: URI): StoreTypeGateway { } const keyedConnections = new KeyedResolvOnce(); -const subscriptions = new Map void)[]>(); +interface Subscription { + readonly sid: string; + readonly uri: string; // optimization + readonly callback: (msg: Uint8Array) => void; + readonly unsub: () => void; +} +const subscriptions = new Map(); const doServerSubscribe = new KeyedResolvOnce(); const trackPuts = new Set(); export class FireproofCloudGateway implements bs.Gateway { @@ -469,11 +475,16 @@ export class FireproofCloudGateway implements bs.Gateway { return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); } - async close(_uri: URI): Promise { - console.log("close:gateway"); - // await this.ready(); - // this.logger.Debug().Msg("close"); - // this.party?.close(); + async close(uri: URI): Promise { + const uriStr = uri.toString(); + // CAUTION here is my happen a mutation of subscriptions caused by unsub + for (const sub of Array.from(subscriptions.values())) { + for (const s of sub) { + if (s.uri.toString() === uriStr) { + s.unsub(); + } + } + } return Result.Ok(undefined); } @@ -506,10 +517,14 @@ export class FireproofCloudGateway implements bs.Gateway { .protocol(params.protocol === "ws" ? "ws" : "wss") .appendRelative("ws") .cleanParams() - .toString(); + // forces to open a new websocket connection + const connId = uri.getParam("connId"); + if (connId) { + wsUrl.setParam("connId", connId); + } return Result.Ok( - await keyedConnections.get(wsUrl).once(async (cKey) => { + await keyedConnections.get(wsUrl.toString()).once(async (cKey) => { const ws = await newWebSocket(wsUrl); const waitOpen = new Future(); ws.onopen = () => { @@ -561,7 +576,11 @@ export class FireproofCloudGateway implements bs.Gateway { const fn = (subId: string) => (msg: MsgBase) => { if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { // console.log("onMessage", subId, conn.key, msg.metas); - this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), subscriptions.get(subId)); + const s = subscriptions.get(subId); + if (!s) { + return; + } + this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), s.map((s) => s.callback)); } }; conn.onMessage(fn(subId)); @@ -576,10 +595,18 @@ export class FireproofCloudGateway implements bs.Gateway { callbacks = []; subscriptions.set(subId, callbacks); } - callbacks.push(callback); - return Result.Ok(() => { - subscriptions.delete(subId); - }); + const sid = this.sthis.nextId().str; + const unsub = () => { + const idx = callbacks.findIndex((c) => c.sid === sid); + if (idx !== -1) { + callbacks.splice(idx, 1); + } + if (callbacks.length === 0) { + subscriptions.delete(subId); + } + } + callbacks.push({ uri: uri.toString(), callback, sid, unsub }); + return Result.Ok(unsub); } async destroy(_uri: URI): Promise> { diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 909a61c4..bb6fe0bf 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -5,11 +5,11 @@ import { Env } from "./backend/env"; import { $ } from "zx"; import fs from "fs/promises"; import * as toml from "smol-toml"; -import { bs, Database, fireproof } from "@fireproof/core"; +import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; import { AwsClient } from "aws4fetch"; import { smokeDB } from "../../tests/helper"; -import { registerFireproofCloudStoreProtocol } from "./client/gateway"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway"; import { calculatePreSignedUrl } from "./pre-signed-url"; import { newWebSocket } from "./new-websocket"; @@ -222,12 +222,8 @@ describe("CloudBackendTest", () => { afterEach(async () => { // Clear the database before each test if (db) { - setInterval(() => console.log("Waiting for db to close"), 1000); - console.log("Closing db"); await db.close(); - console.log("Closed db"); await db.destroy(); - console.log("Destroyed db"); } }); @@ -354,4 +350,159 @@ describe("CloudBackendTest", () => { ); }); }); + + + + describe(`store=meta`, () => { + const store = "meta" + let gw: bs.Gateway + const sthis = mockSuperThis(); + let uri: URI + beforeAll(async () => { + gw = new FireproofCloudGateway(sthis) + const id = sthis.nextId().str + uri = BuildURI.from("fireproof://localhost:1968") + .setParam("store", store) + .setParam("name", id) + .setParam("storekey", id) + .URI() + + const last: Uint8Array[] = [] + const cnt = 4 + Array(cnt).fill(null).map(async () => { + const rOk = await gw.subscribe?.(uri, (meta: Uint8Array) => { + last.push(meta) + if (last.length === cnt) { + expect(last[0]).toEqual(last[1]) + expect(last[1]).toEqual(last[2]) + expect(last[2]).toEqual(last[3]) + last.length = 0 + } + }) as bs.VoidResult + expect(rOk.isOk()).toBeTruthy() + }) + }); + + afterAll(async () => { + const rOk = await gw.close(uri) + expect(rOk.isOk()).toBeTruthy() + }) + + const subscribeCallbacks: ({ + connId: string + uri: URI + cb: ReturnType void>> + unsub: bs.UnsubscribeResult + })[] = [] + beforeEach(async () => { + await Promise.all(Array(4).fill(null).map(async () => { + const cb = vitest.fn() + const connId = sthis.nextId().str + const uriConnId = uri.build().setParam("connId", connId).URI() + const unsub = await gw.subscribe?.(uriConnId, + (meta: Uint8Array) => cb(meta, connId)) as bs.UnsubscribeResult + subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }) + })) + }) + afterEach(() => { + subscribeCallbacks.forEach(({ unsub }) => unsub.Ok()()) + subscribeCallbacks.length = 0 + }) + + function crdtEntry(connId = "default"): Uint8Array { + return sthis.txt.encode(JSON.stringify([ + { + "cid": `${connId}:bafyreidjlylxmmb3yuz7levzzbso3g7ql54zovxl3mkhbbqxmmfnfbkoym`, + "data": "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWdvdHM3dmFzeHhhdmdoY3FjeHo3ZXJibTdtY21ramQybTV0bXpzcGdhbG91d2lpcjYzZnkifV19Z3BhcmVudHOA", + "parents": [] + }, + { + "cid": `${connId}:bafyreie7izpgpmxd6heoiweoyblgyzoxt74xrp5wcpqo66bmjv2plgmceq`, + "data": "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWQyZ2l1c2t2YWJoZTZ5ZHdsdXo0aGx4Z3lyNTZ5dmZmbjVpdndqdmhlYXl3cWJ4bHFmeGEifV19Z3BhcmVudHOA", + "parents": [] + }, + ] satisfies CRDTEntry[])) + } + + it(`buildUrl`, async () => { + const rOk = await gw.buildUrl(uri, "KEY") + const url = rOk.Ok() + expect(url.getParam("store")).toBe(store) + expect(url.getParam("key")).toBe("KEY") + }) + it(`start`, async () => { + const rOk = await gw.start(uri) + const url = rOk.Ok() + expect(url.getParam("store")).toBe(store) + expect(url.getParam("version")).toBeTruthy() + }) + + it(`unsubscribe`, async () => { + subscribeCallbacks.forEach(sub => sub.unsub.Ok()()) + const rOk = await gw.put(uri, crdtEntry()) + expect(rOk.isOk()).toBeTruthy() + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + }) + + it(`get-put-delete`, async () => { + async function getNotFound() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.get(u.build().setParam("key", key).URI()) + expect(rOk.isErr()).toBeTruthy() + expect(isNotFoundError(rOk.Err())).toBeTruthy() + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + } + // get not found + await getNotFound() + // put + async function put() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.put(u.build().setParam("key", key).URI(), + crdtEntry(u.getParam("connId", "default"))) + expect(rOk.isOk()).toBeTruthy() + } + } + subscribeCallbacks.forEach(({ cb, connId }) => { + expect(cb).toHaveBeenCalledTimes(1) + expect(cb).toHaveBeenCalledWith(crdtEntry(connId), connId) + }) + } + await put() + subscribeCallbacks.forEach(({ cb }) => cb.mockClear()) + + async function get() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.get(u.build().setParam("key", key).URI()) + const data = JSON.parse(sthis.txt.decode(rOk.Ok())) as CRDTEntry[] + expect(data).toEqual(subscribeCallbacks.map(({ connId }) => crdtEntry(connId))) + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + } + await get() + async function del() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.delete(u.build().setParam("key", key).URI()) + expect(rOk.isOk()).toBeTruthy() + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + } + await del() + // get not found + await getNotFound() + }) + it(`close`, async () => { + const rOk = await gw.close(uri) + expect(rOk.isOk()).toBeTruthy() + }) + }); + + }); diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 72f90828..5254c92d 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,5 +1,4 @@ -import { Logger, SuperThis } from "@fireproof/core"; -import { bs } from "@fireproof/core"; +import { CRDTEntry, Logger, SuperThis } from "@fireproof/core"; export interface ConnId { readonly connId: string; @@ -194,8 +193,8 @@ export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: ConnId): ResSu }; } -export function MsgIsResSubscribeMeta(msg: MsgBase): msg is ResSubscribeMeta { - return msg.type === "resSubscribeMeta"; +export function MsgIsResSubscribeMeta>(qs: T): qs is T & ReqRes { + return qs.res.type === "resSubscribeMeta"; } @@ -204,7 +203,7 @@ export interface ReqPutMeta extends MsgBase { readonly type: "reqPutMeta"; readonly key: ConnectionKey; readonly params: SignedUrlParam; - readonly metas: bs.DbMeta[]; + readonly metas: CRDTEntry[]; } // export type ReqPutMetaWithConnId = AddConnId; @@ -215,7 +214,7 @@ export interface ReqPutMeta extends MsgBase { export interface PutMetaParam { readonly metaId: string; - readonly metas: bs.DbMeta[]; + readonly metas: CRDTEntry[]; readonly signedPutUrl: string; readonly connId: string; } @@ -229,7 +228,7 @@ export function buildReqPutMeta( sthis: NextId, key: ConnectionKey, signedUrlParams: SignedUrlParam, - metas: bs.DbMeta[], + metas: CRDTEntry[], ): ReqPutMeta { return { tid: sthis.nextId().str, @@ -268,7 +267,7 @@ export interface UpdateMetaEvent extends MsgBase, ConnSubId { readonly type: "updateMeta"; readonly key: ConnectionKey; readonly metaId: string; - readonly metas: bs.DbMeta[]; + readonly metas: CRDTEntry[]; } export function buildUpdateMetaEvent(rq: ReqRes, consub: ConnSubId): UpdateMetaEvent { @@ -305,10 +304,10 @@ export function MsgIsReqGetMeta(msg: MsgBase): msg is ReqGetMeta { // } export interface GetMetaParam { - readonly params: SignedUrlParam; - readonly key: ConnectionKey; + // readonly params: SignedUrlParam; + // readonly key: ConnectionKey; readonly status: "found" | "not-found" | "redirect"; - readonly metas: bs.DbMeta[]; + readonly metas: CRDTEntry[]; readonly connId: string; // if set client should query this url to retrieve the meta readonly signedGetUrl?: string; @@ -316,6 +315,8 @@ export interface GetMetaParam { export interface ResGetMeta extends MsgBase, GetMetaParam { readonly type: "resGetMeta"; + readonly params: SignedUrlParam; + readonly key: ConnectionKey; } export function buildReqGetMeta( @@ -337,6 +338,7 @@ export function buildResGetMeta(req: ReqGetMeta, metaParam: GetMetaParam): ResGe ...metaParam, tid: req.tid, type: "resGetMeta", + params: req.params, key: req.key, version: VERSION, }; @@ -362,8 +364,8 @@ export interface ReqDelMeta extends MsgBase { export interface DelMetaParam { readonly params: SignedUrlParam; - readonly key: ConnectionKey; - readonly status: "found" | "not-found" | "redirect"; + // readonly key: ConnectionKey; + readonly status: "found" | "not-found" | "redirect" | "unsupported"; readonly connId: string; // if set client should query this url to retrieve the meta readonly signedDelUrl?: string; @@ -396,7 +398,7 @@ export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDe ...metaParam, tid: req.tid, type: "resDelMeta", - key: req.key, + // key: req.key, version: VERSION, }; } From efeaa86b60845dd63b79cd30cd6d5812c048d811 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 2 Dec 2024 16:55:23 +0100 Subject: [PATCH 10/83] chore: runs the tsc --- package.json | 2 +- pnpm-lock.yaml | 2 +- src/aws/gateway.ts | 9 +- src/cloud/backend/server.ts | 169 ++++++++------ src/cloud/client/gateway.ts | 72 +++--- src/cloud/cloud.test.ts | 214 +++++++++--------- src/cloud/msg-types.ts | 24 +- src/coerce-binary.ts | 24 ++ src/netlify/gateway.ts | 3 +- src/netlify/server.ts | 5 +- src/partykit/gateway.ts | 3 +- src/ucan/client.ts | 12 +- src/ucan/common.ts | 3 +- .../app/netlify/edge-functions/fireproof.ts | 5 +- tsconfig.json | 11 +- 15 files changed, 307 insertions(+), 251 deletions(-) create mode 100644 src/coerce-binary.ts diff --git a/package.json b/package.json index 7a646b26..20043d10 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", - "@cloudflare/workers-types": "^4.20241112.0", + "@cloudflare/workers-types": "^4.20241127.0", "@fireproof/core": "0.19.114", "@fireproof/encrypted-blockstore": "^0.18.0", "@hono/node-ws": "^1.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45b3b230..9957673b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^0.5.30 version: 0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) '@cloudflare/workers-types': - specifier: ^4.20241112.0 + specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': specifier: 0.19.114 diff --git a/src/aws/gateway.ts b/src/aws/gateway.ts index 9cecadc8..fdd7736f 100644 --- a/src/aws/gateway.ts +++ b/src/aws/gateway.ts @@ -1,5 +1,6 @@ import { BuildURI, CoerceURI, exception2Result, KeyedResolvOnce, Result, URI } from "@adviser/cement"; import { bs, getStore, Logger, NotFoundError, SuperThis, ensureSuperLog } from "@fireproof/core"; +import { to_uint8 } from "../coerce-binary"; async function resultFetch(logger: Logger, curl: CoerceURI, init?: RequestInit): Promise> { const url = URI.from(curl); @@ -137,7 +138,7 @@ export class AWSGateway implements bs.Gateway { return this.logger.Error().Any({ resp: done }).Msg("failed to upload meta").ResultError(); } - const doneJson = await done.json<{ uploadURL?: string }>(); + const doneJson = (await done.json()) as { uploadURL?: string }; if (!doneJson.uploadURL) { return this.logger.Error().Url(fetchUrl).Msg("Upload URL not found in the response").ResultError(); } @@ -191,7 +192,7 @@ export class AWSGateway implements bs.Gateway { return Result.Err(new NotFoundError(`data not found: ${url}`)); } - const data = new Uint8Array(await response.arrayBuffer()); + const data = to_uint8(await response.arrayBuffer()); return Result.Ok(data); } @@ -224,7 +225,7 @@ export class AWSGateway implements bs.Gateway { return this.logger.Error().Url(fetchUrl).Any({ response }).Msg("Download Meta response error").ResultError(); } - const data = new Uint8Array(await response.arrayBuffer()); + const data = to_uint8(await response.arrayBuffer()); // bs.setCryptoKeyFromGatewayMetaPayload(url, this.sthis, data); const res = await bs.setCryptoKeyFromGatewayMetaPayload(url, this.sthis, data); if (res.isErr()) { @@ -249,7 +250,7 @@ export class AWSGateway implements bs.Gateway { // console.log("Download Wal response error:", response.status); return Result.Err(new NotFoundError(`wal not found: ${url}`)); } - const data = new Uint8Array(await response.arrayBuffer()); + const data = to_uint8(await response.arrayBuffer()); return Result.Ok(data); } diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 8c7048ca..20a3e168 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,3 +1,4 @@ +// / import type { Env } from "./env"; import { exception2Result, Logger, LoggerImpl, URI } from "@adviser/cement"; import { @@ -30,9 +31,11 @@ import { ResPutMeta, ResSignedUrl, ResSubscribeMeta, + UpdateMetaEvent, } from "../msg-types"; // import { Hono } from "hono"; import { CRDTEntry, NotFoundError } from "@fireproof/core"; +// import { DurableObject } from "cloudflare:workers"; import { DurableObject } from "cloudflare:workers"; import { calculatePreSignedUrl } from "../pre-signed-url"; @@ -102,39 +105,61 @@ export class FPMetaGroups extends DurableObject { async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { if (typeof msg !== "string") { - this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary") + this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); return; } - return CFMsgProcessor.dispatch(() => JSON.parse(msg.toString()), { - env: this.env, - dobj: this.ctx - }, async (req: MsgBase, ictx: CtxBase) => { - if (req.auth) { - // do ucan magic + return CFMsgProcessor.dispatch( + () => JSON.parse(msg.toString()), + { + env: this.env, + dobj: this.ctx, + }, + async (req: MsgBase, ictx: CtxBase) => { + if (req.auth) { + // do ucan magic + } + let group = (ws.deserializeAttachment() || { msgSeq: 0 }) as FPMetaGroup; + group = { + ...group, + msgSeq: group.msgSeq + 1, + connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), + lastUsed: new Date(), + } satisfies FPMetaGroup; + ws.serializeAttachment(group); + const ctx = { ...ictx, group } satisfies CtxWithGroup; + return { req, ctx }; } - let group = (ws.deserializeAttachment() || { msgSeq: 0 }) as FPMetaGroup; - group = { - ...group, - msgSeq: group.msgSeq + 1, - connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), - lastUsed: new Date() - } satisfies FPMetaGroup - ws.serializeAttachment(group); - const ctx = { ...ictx, group } satisfies CtxWithGroup - return { req, ctx }; - }).then((qs) => { + ).then((qs) => { switch (true) { case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): { const group = { ...qs.ctx.group, lastMeta: qs.req } satisfies FPMetaGroup; ws.serializeAttachment(group); - this.updateMeta(qs); + this.updateMeta( + buildUpdateMetaEvent(qs, { + connId: qs.res.connId, + subscriberId: "later-overriden", + }), + qs.ctx + ); break; } case MsgIsResSubscribeMeta(qs): { const group = { ...qs.ctx.group, group: qs.res } satisfies FPMetaGroup; ws.serializeAttachment(group); - this.updateMeta(qs) + this.updateMeta( + { + connId: qs.res.connId, + subscriberId: "later-overriden", + tid: qs.res.tid, + type: "updateMeta", + key: qs.res.key, + metaId: "later-overriden", + metas: [], + version: qs.res.version, + }, + qs.ctx + ); break; } } @@ -143,7 +168,7 @@ export class FPMetaGroups extends DurableObject { } async fetch(req: Request): Promise { - const path = URI.from(req.url).pathname + const path = URI.from(req.url).pathname; switch (path) { case "/fp": { const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env, dobj: this.ctx }); @@ -164,7 +189,7 @@ export class FPMetaGroups extends DurableObject { } default: { const logger = ensureLogger(this.env); - return json(buildErrorMsg(logger, { tid: "internal", }, new NotFoundError(`Notfound:${path}`)), 404); + return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); } } } @@ -177,45 +202,48 @@ export class FPMetaGroups extends DurableObject { } } - updateMeta(qs: ReqResCtx): void { - const wsSocks = qs.ctx.dobj.getWebSockets() - const groupWs = wsSocks.map(ws => ({ - ws, group: ws.deserializeAttachment() as FPMetaGroup + // updateMeta(qs: ReqResCtx): void { + updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { + const wsSocks = ctx.dobj.getWebSockets(); + const groupWs = wsSocks.map((ws) => ({ + ws, + group: ws.deserializeAttachment() as FPMetaGroup, })); const joinedMeta = groupWs.reduce((acc, { group }) => { if (group && group.lastMeta) { - acc.push(...group.lastMeta.metas) + acc.push(...group.lastMeta.metas); } - return acc - }, [] as CRDTEntry[]) - const now = new Date() - const joinedQS = { - req: { ...qs.req, metas: joinedMeta }, - res: qs.res, - } + return acc; + }, [] as CRDTEntry[]); + const now = new Date(); + const joinedUp = { + ...up, + metas: joinedMeta, + }; groupWs.forEach(({ ws, group }) => { ws.serializeAttachment({ ...group, msgSeq: group.msgSeq + 1, - lastUsed: now - } satisfies FPMetaGroup) + lastUsed: now, + } satisfies FPMetaGroup); ws.send( // this is not the best way to do this - JSON.stringify( - buildUpdateMetaEvent(joinedQS, { - subscriberId: group.group.subscriberId, - connId: group.group.connId, - }) - ) - ) - }) + JSON.stringify({ + ...joinedUp, + subscriberId: group.group.subscriberId, + connId: group.group.connId, + }) + ); + }); } } // const app = new Hono<{ Bindings: Env }>(); interface MsgProcessor { - dispatch(decodeFn: () => Promise): Promise>; + dispatch( + decodeFn: () => Promise + ): Promise>; signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise; subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise; @@ -231,9 +259,9 @@ interface CFMsgProcessorParams { } interface CtxBaseParam { - readonly env: Env - readonly module?: string - readonly dobj: DurableObjectState + readonly env: Env; + readonly module?: string; + readonly dobj: DurableObjectState; } interface CtxBase { @@ -242,20 +270,14 @@ interface CtxBase { readonly logger: Logger; } -type CtxWithGroup = CtxBase & { readonly group: FPMetaGroup } +type CtxWithGroup = CtxBase & { readonly group: FPMetaGroup }; -interface ReqOptResCtx< - Q extends MsgBase, - S extends MsgBase, - C extends CtxBase> extends ReqOptRes { +interface ReqOptResCtx extends ReqOptRes { readonly ctx?: C; } -interface ReqResCtx< - Q extends MsgBase, - S extends MsgBase, - C extends CtxBase> extends ReqRes { - readonly ctx: C +interface ReqResCtx extends ReqRes { + readonly ctx: C; } class CFMsgProcessor implements MsgProcessor { @@ -269,7 +291,7 @@ class CFMsgProcessor implements MsgProcessor { ): Promise> { return new CFMsgProcessor({ env: ctx.env, - logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor") + logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor"), }).dispatch(decodeFn, reqFn); } @@ -284,55 +306,55 @@ class CFMsgProcessor implements MsgProcessor { ): Promise> { const ictx = { env: this.env, - logger: this.logger - } as CtxBase + logger: this.logger, + } as CtxBase; const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); if (rReqMsg.isErr()) { const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); return { req: errMsg as unknown as Q, res: errMsg, - ctx: ictx as C + ctx: ictx as C, }; } - const { req, ctx: optCtx } = (await reqFn(rReqMsg.Ok() as Q, ictx as C)); - const ctx = { ...ictx, ...optCtx } as C & { readonly group: FPMetaGroup } + const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, ictx as C); + const ctx = { ...ictx, ...optCtx } as C & { readonly group: FPMetaGroup }; switch (true) { case MsgIsReqSignedUrl(req): return { req, res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, - ctx + ctx, }; case MsgIsReqSubscribeMeta(req): return { req, res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, - ctx + ctx, }; case MsgIsReqPutMeta(req): return { req, res: (await this.putMeta(req, ctx)) as S | ErrorMsg, - ctx + ctx, }; case MsgIsReqGetMeta(req): return { req, res: (await this.getMeta(req, ctx)) as S | ErrorMsg, - ctx + ctx, }; case MsgIsReqDelMeta(req): return { req, res: (await this.delMeta(req, ctx)) as S | ErrorMsg, - ctx + ctx, }; } return { req: req, res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, - ctx + ctx, }; } @@ -343,7 +365,7 @@ class CFMsgProcessor implements MsgProcessor { params: req.params, status: "unsupported", connId: ctx.group.connId, - }) + }); } async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { @@ -363,8 +385,8 @@ class CFMsgProcessor implements MsgProcessor { signedGetUrl: rSignedUrl.Ok().toString(), status: "found", metas: [], - connId: "" - }) + connId: "", + }); } async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { @@ -406,7 +428,6 @@ class CFMsgProcessor implements MsgProcessor { export default { async fetch(req, env, _ctx): Promise { - const id = env.FP_META_GROUPS.idFromName("fireproof"); const stub = env.FP_META_GROUPS.get(id); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index bdd912b9..3ffba1ac 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -22,6 +22,7 @@ import { ResSubscribeMeta, } from "../msg-types.js"; import { newWebSocket } from "../new-websocket.js"; +import { to_uint8 } from "../../coerce-binary.js"; const VERSION = "v0.1-fp-cloud"; @@ -43,8 +44,6 @@ interface WaitForTid { readonly type?: string; } - - export class ConnectionImpl implements Connection { readonly ws: WebSocket; readonly key: ConnectionKey; @@ -67,7 +66,7 @@ export class ConnectionImpl implements Connection { this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); return; } - const msg = rMsg.Ok() + const msg = rMsg.Ok(); const waitFor = this.waitForTid.get(msg.tid); if (waitFor) { if (waitFor.type === msg.type || MsgIsError(msg)) { @@ -93,7 +92,7 @@ export class ConnectionImpl implements Connection { timeout: 1000, }, ...opts, - } + }; const future = new Future(); this.waitForTid.set(req.tid, { tid: req.tid, @@ -105,7 +104,7 @@ export class ConnectionImpl implements Connection { .With() .Str("tid", req.tid) .Uint64("timeout", opts.timeout) - .Ref("start", ()=> (new Date()).getTime()-start) + .Ref("start", () => new Date().getTime() - start) .Any("req", req) .Logger(); this.ws.send(JSON.stringify(req)); @@ -125,7 +124,7 @@ export class ConnectionImpl implements Connection { .catch((err) => { logger.Error().Err(err).Msg("request-error"); return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); - }) + }); } } @@ -163,7 +162,6 @@ abstract class BaseGateway { const conn = rConn.Ok(); this.logger.Debug().Any("conn", conn.key).Msg("put"); return this.putConn(uri, body, conn); - } abstract delConn(uri: URI, conn: Connection): Promise>; async delete(uri: URI, prConn: Promise>): Promise> { @@ -203,7 +201,7 @@ abstract class BaseGateway { if (rsu.isErr()) { return Result.Err(rsu.Err()); } - return conn.request(rsu.Ok(), { waitType: "resSignedUrl"}); + return conn.request(rsu.Ok(), { waitType: "resSignedUrl" }); } async putObject(uri: URI, uploadUrl: string, body: Uint8Array): Promise> { @@ -239,7 +237,7 @@ abstract class BaseGateway { } return this.logger.Error().Url(downloadUrl, "uploadUrl").Err(rDownload).Msg("Error in get fetch").ResultError(); } - return Result.Ok(new Uint8Array(await download.arrayBuffer())); + return Result.Ok(to_uint8(await download.arrayBuffer())); } async delObject(uri: URI, deleteUrl: string): Promise> { @@ -257,7 +255,6 @@ abstract class BaseGateway { } return Result.Ok(undefined); } - } class DataGateway extends BaseGateway implements StoreTypeGateway { @@ -299,22 +296,20 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { if (rsu.isErr()) { return Result.Err(rsu.Err()); } - const rRes = await conn.request( - buildReqGetMeta(this.sthis, conn.key, rsu.Ok().params), - {waitType: "resGetMeta"} - ); + const rRes = await conn.request(buildReqGetMeta(this.sthis, conn.key, rsu.Ok().params), { + waitType: "resGetMeta", + }); if (rRes.isErr()) { return Result.Err(rRes.Err()); } const res = rRes.Ok(); if (MsgIsError(res)) { - return Result.Err(res) + return Result.Err(res); } if (res.signedGetUrl) { - return this.getObject(uri, res.signedGetUrl) + return this.getObject(uri, res.signedGetUrl); } return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); - } async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); @@ -327,35 +322,31 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { if (rsu.isErr()) { return Result.Err(rsu.Err()); } - const res = await conn.request( - buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas), - { waitType: "resPutMeta" } - ); + const res = await conn.request(buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas), { + waitType: "resPutMeta", + }); if (res.isErr()) { return Result.Err(res.Err()); } this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); return res; - } async delConn(uri: URI, conn: Connection): Promise> { const rsu = this.prepareReqSignedUrl(uri, "DELETE", conn.key); if (rsu.isErr()) { return Result.Err(rsu.Err()); } - const res = await conn.request( - buildReqDelMeta(this.sthis, conn.key, rsu.Ok().params), - { waitType: "resDelMeta"} - ); + const res = await conn.request(buildReqDelMeta(this.sthis, conn.key, rsu.Ok().params), { + waitType: "resDelMeta", + }); if (res.isErr()) { return Result.Err(res.Err()); } const { signedDelUrl } = res.Ok(); if (signedDelUrl) { - return this.delObject(uri, signedDelUrl) + return this.delObject(uri, signedDelUrl); } return Result.Ok(undefined); - } } @@ -369,7 +360,7 @@ class WALGateway extends BaseGateway implements StoreTypeGateway { const rKey = uri.getParamsResult({ key: 0, name: 0, - }) + }); if (rKey.isErr()) { return Result.Err(rKey.Err()); } @@ -416,7 +407,11 @@ function getStoreTypeGateway(sthis: SuperThis, uri: URI): StoreTypeGateway { case "wal": return storeTypedGateways.get(store).once(() => new WALGateway(sthis)); default: - throw ensureLogger(sthis, "getStoreTypeGateway").Error().Str("store", store).Msg("Invalid store type").ResultError(); + throw ensureLogger(sthis, "getStoreTypeGateway") + .Error() + .Str("store", store) + .Msg("Invalid store type") + .ResultError(); } } @@ -437,7 +432,7 @@ export class FireproofCloudGateway implements bs.Gateway { constructor(sthis: SuperThis) { this.sthis = sthis; this.logger = ensureLogger(sthis, "FireproofCloudGateway", { - this: true + this: true, }); } @@ -516,7 +511,7 @@ export class FireproofCloudGateway implements bs.Gateway { .build() .protocol(params.protocol === "ws" ? "ws" : "wss") .appendRelative("ws") - .cleanParams() + .cleanParams(); // forces to open a new websocket connection const connId = uri.getParam("connId"); @@ -580,11 +575,16 @@ export class FireproofCloudGateway implements bs.Gateway { if (!s) { return; } - this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), s.map((s) => s.callback)); + this.notifySubscribers( + this.sthis.txt.encode(JSON.stringify(msg.metas)), + s.map((s) => s.callback) + ); } }; conn.onMessage(fn(subId)); - return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { waitType: "resSubscribeMeta"}); + return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { + waitType: "resSubscribeMeta", + }); }); if (rResSubscribeMeta.isErr()) { return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); @@ -604,13 +604,13 @@ export class FireproofCloudGateway implements bs.Gateway { if (callbacks.length === 0) { subscriptions.delete(subId); } - } + }; callbacks.push({ uri: uri.toString(), callback, sid, unsub }); return Result.Ok(unsub); } async destroy(_uri: URI): Promise> { - await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))) + await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))); return Result.Ok(undefined); } } diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index bb6fe0bf..80b372c0 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -206,11 +206,7 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler - .build() - .protocol("fireproof:") - .setParam("protocol", "ws") - .setParam("testMode", "true") + base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -344,165 +340,169 @@ describe("CloudBackendTest", () => { .setParam( "X-Amz-Signature", sthis.env.get("CF_PRESIGNED_SIGNATURE") || - "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" ) .asObj() ); }); }); - - describe(`store=meta`, () => { - const store = "meta" - let gw: bs.Gateway + const store = "meta"; + let gw: bs.Gateway; const sthis = mockSuperThis(); - let uri: URI + let uri: URI; beforeAll(async () => { - gw = new FireproofCloudGateway(sthis) - const id = sthis.nextId().str + gw = new FireproofCloudGateway(sthis); + const id = sthis.nextId().str; uri = BuildURI.from("fireproof://localhost:1968") .setParam("store", store) .setParam("name", id) .setParam("storekey", id) - .URI() - - const last: Uint8Array[] = [] - const cnt = 4 - Array(cnt).fill(null).map(async () => { - const rOk = await gw.subscribe?.(uri, (meta: Uint8Array) => { - last.push(meta) - if (last.length === cnt) { - expect(last[0]).toEqual(last[1]) - expect(last[1]).toEqual(last[2]) - expect(last[2]).toEqual(last[3]) - last.length = 0 - } - }) as bs.VoidResult - expect(rOk.isOk()).toBeTruthy() - }) + .URI(); + + const last: Uint8Array[] = []; + const cnt = 4; + Array(cnt) + .fill(null) + .map(async () => { + const rOk = (await gw.subscribe?.(uri, (meta: Uint8Array) => { + last.push(meta); + if (last.length === cnt) { + expect(last[0]).toEqual(last[1]); + expect(last[1]).toEqual(last[2]); + expect(last[2]).toEqual(last[3]); + last.length = 0; + } + })) as bs.VoidResult; + expect(rOk.isOk()).toBeTruthy(); + }); }); afterAll(async () => { - const rOk = await gw.close(uri) - expect(rOk.isOk()).toBeTruthy() - }) - - const subscribeCallbacks: ({ - connId: string - uri: URI - cb: ReturnType void>> - unsub: bs.UnsubscribeResult - })[] = [] + const rOk = await gw.close(uri); + expect(rOk.isOk()).toBeTruthy(); + }); + + const subscribeCallbacks: { + connId: string; + uri: URI; + cb: ReturnType void>>; + unsub: bs.UnsubscribeResult; + }[] = []; beforeEach(async () => { - await Promise.all(Array(4).fill(null).map(async () => { - const cb = vitest.fn() - const connId = sthis.nextId().str - const uriConnId = uri.build().setParam("connId", connId).URI() - const unsub = await gw.subscribe?.(uriConnId, - (meta: Uint8Array) => cb(meta, connId)) as bs.UnsubscribeResult - subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }) - })) - }) + await Promise.all( + Array(4) + .fill(null) + .map(async () => { + const cb = vitest.fn(); + const connId = sthis.nextId().str; + const uriConnId = uri.build().setParam("connId", connId).URI(); + const unsub = (await gw.subscribe?.(uriConnId, (meta: Uint8Array) => + cb(meta, connId) + )) as bs.UnsubscribeResult; + subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }); + }) + ); + }); afterEach(() => { - subscribeCallbacks.forEach(({ unsub }) => unsub.Ok()()) - subscribeCallbacks.length = 0 - }) + subscribeCallbacks.forEach(({ unsub }) => unsub.Ok()()); + subscribeCallbacks.length = 0; + }); function crdtEntry(connId = "default"): Uint8Array { - return sthis.txt.encode(JSON.stringify([ - { - "cid": `${connId}:bafyreidjlylxmmb3yuz7levzzbso3g7ql54zovxl3mkhbbqxmmfnfbkoym`, - "data": "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWdvdHM3dmFzeHhhdmdoY3FjeHo3ZXJibTdtY21ramQybTV0bXpzcGdhbG91d2lpcjYzZnkifV19Z3BhcmVudHOA", - "parents": [] - }, - { - "cid": `${connId}:bafyreie7izpgpmxd6heoiweoyblgyzoxt74xrp5wcpqo66bmjv2plgmceq`, - "data": "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWQyZ2l1c2t2YWJoZTZ5ZHdsdXo0aGx4Z3lyNTZ5dmZmbjVpdndqdmhlYXl3cWJ4bHFmeGEifV19Z3BhcmVudHOA", - "parents": [] - }, - ] satisfies CRDTEntry[])) + return sthis.txt.encode( + JSON.stringify([ + { + cid: `${connId}:bafyreidjlylxmmb3yuz7levzzbso3g7ql54zovxl3mkhbbqxmmfnfbkoym`, + data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWdvdHM3dmFzeHhhdmdoY3FjeHo3ZXJibTdtY21ramQybTV0bXpzcGdhbG91d2lpcjYzZnkifV19Z3BhcmVudHOA", + parents: [], + }, + { + cid: `${connId}:bafyreie7izpgpmxd6heoiweoyblgyzoxt74xrp5wcpqo66bmjv2plgmceq`, + data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWQyZ2l1c2t2YWJoZTZ5ZHdsdXo0aGx4Z3lyNTZ5dmZmbjVpdndqdmhlYXl3cWJ4bHFmeGEifV19Z3BhcmVudHOA", + parents: [], + }, + ] satisfies CRDTEntry[]) + ); } it(`buildUrl`, async () => { - const rOk = await gw.buildUrl(uri, "KEY") - const url = rOk.Ok() - expect(url.getParam("store")).toBe(store) - expect(url.getParam("key")).toBe("KEY") - }) + const rOk = await gw.buildUrl(uri, "KEY"); + const url = rOk.Ok(); + expect(url.getParam("store")).toBe(store); + expect(url.getParam("key")).toBe("KEY"); + }); it(`start`, async () => { - const rOk = await gw.start(uri) - const url = rOk.Ok() - expect(url.getParam("store")).toBe(store) - expect(url.getParam("version")).toBeTruthy() - }) + const rOk = await gw.start(uri); + const url = rOk.Ok(); + expect(url.getParam("store")).toBe(store); + expect(url.getParam("version")).toBeTruthy(); + }); it(`unsubscribe`, async () => { - subscribeCallbacks.forEach(sub => sub.unsub.Ok()()) - const rOk = await gw.put(uri, crdtEntry()) - expect(rOk.isOk()).toBeTruthy() - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) - }) + subscribeCallbacks.forEach((sub) => sub.unsub.Ok()()); + const rOk = await gw.put(uri, crdtEntry()); + expect(rOk.isOk()).toBeTruthy(); + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); + }); it(`get-put-delete`, async () => { async function getNotFound() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.get(u.build().setParam("key", key).URI()) - expect(rOk.isErr()).toBeTruthy() - expect(isNotFoundError(rOk.Err())).toBeTruthy() + const rOk = await gw.get(u.build().setParam("key", key).URI()); + expect(rOk.isErr()).toBeTruthy(); + expect(isNotFoundError(rOk.Err())).toBeTruthy(); } } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } // get not found - await getNotFound() + await getNotFound(); // put async function put() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.put(u.build().setParam("key", key).URI(), - crdtEntry(u.getParam("connId", "default"))) - expect(rOk.isOk()).toBeTruthy() + const rOk = await gw.put(u.build().setParam("key", key).URI(), crdtEntry(u.getParam("connId", "default"))); + expect(rOk.isOk()).toBeTruthy(); } } subscribeCallbacks.forEach(({ cb, connId }) => { - expect(cb).toHaveBeenCalledTimes(1) - expect(cb).toHaveBeenCalledWith(crdtEntry(connId), connId) - }) + expect(cb).toHaveBeenCalledTimes(1); + expect(cb).toHaveBeenCalledWith(crdtEntry(connId), connId); + }); } - await put() - subscribeCallbacks.forEach(({ cb }) => cb.mockClear()) + await put(); + subscribeCallbacks.forEach(({ cb }) => cb.mockClear()); async function get() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.get(u.build().setParam("key", key).URI()) - const data = JSON.parse(sthis.txt.decode(rOk.Ok())) as CRDTEntry[] - expect(data).toEqual(subscribeCallbacks.map(({ connId }) => crdtEntry(connId))) + const rOk = await gw.get(u.build().setParam("key", key).URI()); + const data = JSON.parse(sthis.txt.decode(rOk.Ok())) as CRDTEntry[]; + expect(data).toEqual(subscribeCallbacks.map(({ connId }) => crdtEntry(connId))); } } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } - await get() + await get(); async function del() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.delete(u.build().setParam("key", key).URI()) - expect(rOk.isOk()).toBeTruthy() + const rOk = await gw.delete(u.build().setParam("key", key).URI()); + expect(rOk.isOk()).toBeTruthy(); } } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()) + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } - await del() + await del(); // get not found - await getNotFound() - }) + await getNotFound(); + }); it(`close`, async () => { - const rOk = await gw.close(uri) - expect(rOk.isOk()).toBeTruthy() - }) + const rOk = await gw.close(uri); + expect(rOk.isOk()).toBeTruthy(); + }); }); - - }); diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 5254c92d..e74880c2 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -17,7 +17,7 @@ export interface AuthType { export interface UCanAuth { readonly type: "ucan"; readonly params: { - readonly tbd: string + readonly tbd: string; }; } @@ -193,11 +193,12 @@ export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: ConnId): ResSu }; } -export function MsgIsResSubscribeMeta>(qs: T): qs is T & ReqRes { +export function MsgIsResSubscribeMeta>( + qs: T +): qs is T & ReqRes { return qs.res.type === "resSubscribeMeta"; } - /* Put Meta */ export interface ReqPutMeta extends MsgBase { readonly type: "reqPutMeta"; @@ -228,7 +229,7 @@ export function buildReqPutMeta( sthis: NextId, key: ConnectionKey, signedUrlParams: SignedUrlParam, - metas: CRDTEntry[], + metas: CRDTEntry[] ): ReqPutMeta { return { tid: sthis.nextId().str, @@ -319,11 +320,7 @@ export interface ResGetMeta extends MsgBase, GetMetaParam { readonly key: ConnectionKey; } -export function buildReqGetMeta( - sthis: NextId, - key: ConnectionKey, - signedUrlParams: SignedUrlParam -): ReqGetMeta { +export function buildReqGetMeta(sthis: NextId, key: ConnectionKey, signedUrlParams: SignedUrlParam): ReqGetMeta { return { tid: sthis.nextId().str, key, @@ -348,7 +345,6 @@ export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes): qs is ReqRes { return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; -} \ No newline at end of file +} diff --git a/src/coerce-binary.ts b/src/coerce-binary.ts new file mode 100644 index 00000000..170168f2 --- /dev/null +++ b/src/coerce-binary.ts @@ -0,0 +1,24 @@ +export function to_uint8(input: ArrayBuffer | ArrayBufferView | Uint8Array): Uint8Array { + if (input instanceof ArrayBuffer) { + return new Uint8Array(input); + } + + if (input instanceof Uint8Array) { + return input; + } + // not nice but we make the cloudflare types happy + return new Uint8Array(input as unknown as ArrayBuffer); +} + +export function to_blob(input: ArrayBuffer | ArrayBufferView | Uint8Array | Blob): Blob { + if (input instanceof Blob) { + return input; + } + return new Blob([to_uint8(input)]); +} +export function to_arraybuf(input: ArrayBuffer | ArrayBufferView | Uint8Array): ArrayBuffer { + if (input instanceof ArrayBuffer) { + return input; + } + return to_uint8(input).buffer as ArrayBuffer; +} diff --git a/src/netlify/gateway.ts b/src/netlify/gateway.ts index 762fa855..7ca9f0fa 100644 --- a/src/netlify/gateway.ts +++ b/src/netlify/gateway.ts @@ -1,5 +1,6 @@ import { KeyedResolvOnce, Result, URI, BuildURI, exception2Result } from "@adviser/cement"; import { bs, getStore, Logger, NotFoundError, SuperThis, ensureSuperLog } from "@fireproof/core"; +import { to_uint8 } from "../coerce-binary"; export class NetlifyGateway implements bs.Gateway { readonly sthis: SuperThis; @@ -149,7 +150,7 @@ export class NetlifyGateway implements bs.Gateway { return Result.Err(new NotFoundError(`${store} not found: ${url}`)); } - const data = new Uint8Array(await response.arrayBuffer()); + const data = to_uint8(await response.arrayBuffer()); if (store === "meta") { const res = await bs.setCryptoKeyFromGatewayMetaPayload(url, this.sthis, data); if (res.isErr()) { diff --git a/src/netlify/server.ts b/src/netlify/server.ts index 5c566131..d672e1e7 100644 --- a/src/netlify/server.ts +++ b/src/netlify/server.ts @@ -1,4 +1,5 @@ import { getStore } from "@netlify/blobs"; +import { to_blob } from "../coerce-binary"; // eslint-disable-next-line no-console console.log("fireproof edge function loaded netlify"); @@ -18,12 +19,12 @@ export default async (req: Request) => { if (req.method === "PUT") { if (carId) { const carFiles = getStore("cars"); - const carArrayBuffer = new Uint8Array(await req.arrayBuffer()); + const carArrayBuffer = to_blob(await req.arrayBuffer()); await carFiles.set(carId, carArrayBuffer); return new Response(JSON.stringify({ ok: true }), { status: 201 }); } else if (metaDb) { const meta = getStore("meta"); - const x = await req.json(); + const x = (await req.json()) as CRDTEntry[]; // fixme, marty changed to [0] as it is a slice of the structure we expected const { data, cid, parents } = x[0]; await meta.setJSON(`${metaDb}/${cid}`, { data, parents }); diff --git a/src/partykit/gateway.ts b/src/partykit/gateway.ts index 2af56b95..38b797fd 100644 --- a/src/partykit/gateway.ts +++ b/src/partykit/gateway.ts @@ -1,6 +1,7 @@ import { PartySocket, PartySocketOptions } from "partysocket"; import { Result, URI, BuildURI, KeyedResolvOnce, runtimeFn, exception2Result } from "@adviser/cement"; import { bs, ensureLogger, getStore, Logger, rt, SuperThis } from "@fireproof/core"; +import { to_uint8 } from "../coerce-binary"; export class PartyKitGateway implements bs.Gateway { readonly logger: Logger; @@ -182,7 +183,7 @@ export class PartyKitGateway implements bs.Gateway { if (response.status === 404) { throw new Error(`Failure in downloading ${store}!`); } - const body = new Uint8Array(await response.arrayBuffer()); + const body = to_uint8(await response.arrayBuffer()); if (store === "meta") { const resKeyInfo = await bs.setCryptoKeyFromGatewayMetaPayload(uri, this.sthis, body); if (resKeyInfo.isErr()) { diff --git a/src/ucan/client.ts b/src/ucan/client.ts index da3888d2..78ea25dd 100644 --- a/src/ucan/client.ts +++ b/src/ucan/client.ts @@ -10,6 +10,7 @@ import { sha256 } from "multiformats/hashes/sha2"; import * as ClockCaps from "./clock/capabilities.js"; import * as StoreCaps from "./store/capabilities.js"; import { Server, type Clock, type Service } from "./types.js"; +import { to_uint8 } from "../coerce-binary.js"; //////////////////////////////////////// // CLOCK @@ -140,6 +141,13 @@ export async function registerClock({ //////////////////////////////////////// // CONNECTION //////////////////////////////////////// +export function coerceHeaders(headers: Record | Headers): Record { + if ("entries" in headers) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return Object.fromEntries((headers as any).entries()); + } + return headers as Record; +} export function service(server: Server): ConnectionView { const url = server.uri.toString(); @@ -156,8 +164,8 @@ export function service(server: Server): ConnectionView { const buffer = response.ok ? await response.arrayBuffer() : new Uint8Array(); return { - headers: response.headers.entries ? Object.fromEntries(response.headers.entries()) : {}, - body: new Uint8Array(buffer), + headers: coerceHeaders(response.headers), + body: to_uint8(buffer), }; }, }; diff --git a/src/ucan/common.ts b/src/ucan/common.ts index 17887c2d..4821090a 100644 --- a/src/ucan/common.ts +++ b/src/ucan/common.ts @@ -3,6 +3,7 @@ import { Delegation } from "@ucanto/interface"; import type { AgentDataExport, DelegationMeta } from "@web3-storage/access/types"; import { Block } from "multiformats/block"; import { CID } from "multiformats"; +import { to_arraybuf } from "../coerce-binary"; export async function extractDelegation(dataExport: AgentDataExport): Promise { const delegationKey = Array.from(dataExport.delegations.keys())[0]; @@ -32,7 +33,7 @@ export function exportDelegation(del: Delegation): [ meta: {}, delegation: [...del.export()].map((b) => ({ cid: b.cid.toString(), - bytes: b.bytes, + bytes: to_arraybuf(b.bytes), })), }, ]; diff --git a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts index 8d71910e..7cca885b 100644 --- a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts +++ b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts @@ -1,4 +1,5 @@ import { getStore } from "@netlify/blobs"; +import { to_blob } from "../../../../../src/coerce-binary"; // eslint-disable-next-line no-console console.log("fireproof edge function loaded netlify"); @@ -18,12 +19,12 @@ export default async (req: Request) => { if (req.method === "PUT") { if (carId) { const carFiles = getStore("cars"); - const carArrayBuffer = new Uint8Array(await req.arrayBuffer()); + const carArrayBuffer = to_blob(await req.arrayBuffer()); await carFiles.set(carId, carArrayBuffer); return new Response(JSON.stringify({ ok: true }), { status: 201 }); } else if (metaDb) { const meta = getStore("meta"); - const x = await req.json(); + const x = await req.json() as CRDTEntry[]; // fixme, marty changed to [0] as it is a slice of the structure we expected const { data, cid, parents } = x[0] await meta.setJSON(`${metaDb}/${cid}`, { data, parents }); diff --git a/tsconfig.json b/tsconfig.json index 6741d6cb..439ee72a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,11 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "target": "esnext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "esnext", + "dom" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ @@ -114,10 +117,12 @@ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, "include": ["src/**/*", "tests/**/*"], - "typeRoots": ["ts-types", "node_modules/@types"], + "typeRoots": ["ts-types", "node_modules/@types"] + /* "ts-node": { "compilerOptions": { "module": "CommonJS" } } + */ } From a0e649e7a02b52c5367723e9f14bc4ad74796d7c Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 6 Dec 2024 09:40:45 +0100 Subject: [PATCH 11/83] chore: make tsc happy --- src/aws/gateway.ts | 2 +- src/cloud/backend/fp-meta-groups.ts | 2 +- src/cloud/backend/server.ts | 6 +++--- src/cloud/client/index.ts | 2 +- src/cloud/cloud.test.ts | 12 ++++++------ src/cloud/pre-signed-url.ts | 4 ++-- src/netlify/gateway.ts | 2 +- src/netlify/server.ts | 2 +- src/partykit/gateway.ts | 2 +- src/ucan/common.ts | 2 +- .../app/netlify/edge-functions/fireproof.ts | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/aws/gateway.ts b/src/aws/gateway.ts index fdd7736f..2e189c9d 100644 --- a/src/aws/gateway.ts +++ b/src/aws/gateway.ts @@ -1,6 +1,6 @@ import { BuildURI, CoerceURI, exception2Result, KeyedResolvOnce, Result, URI } from "@adviser/cement"; import { bs, getStore, Logger, NotFoundError, SuperThis, ensureSuperLog } from "@fireproof/core"; -import { to_uint8 } from "../coerce-binary"; +import { to_uint8 } from "../coerce-binary.js"; async function resultFetch(logger: Logger, curl: CoerceURI, init?: RequestInit): Promise> { const url = URI.from(curl); diff --git a/src/cloud/backend/fp-meta-groups.ts b/src/cloud/backend/fp-meta-groups.ts index 846e5adb..d18d3aae 100644 --- a/src/cloud/backend/fp-meta-groups.ts +++ b/src/cloud/backend/fp-meta-groups.ts @@ -1,5 +1,5 @@ import { DurableObject } from "cloudflare:workers"; -import { Env } from "./env"; +import { Env } from "./env.js"; export class FPMetaGroups extends DurableObject { currentlyConnectedWebSockets: number; diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 20a3e168..1c0eee3a 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,5 +1,5 @@ // / -import type { Env } from "./env"; +import type { Env } from "./env.js"; import { exception2Result, Logger, LoggerImpl, URI } from "@adviser/cement"; import { buildErrorMsg, @@ -32,12 +32,12 @@ import { ResSignedUrl, ResSubscribeMeta, UpdateMetaEvent, -} from "../msg-types"; +} from "../msg-types.js"; // import { Hono } from "hono"; import { CRDTEntry, NotFoundError } from "@fireproof/core"; // import { DurableObject } from "cloudflare:workers"; import { DurableObject } from "cloudflare:workers"; -import { calculatePreSignedUrl } from "../pre-signed-url"; +import { calculatePreSignedUrl } from "../pre-signed-url.js"; const CORS = { "Content-Type": "application/json", diff --git a/src/cloud/client/index.ts b/src/cloud/client/index.ts index 191587c6..48804cd3 100644 --- a/src/cloud/client/index.ts +++ b/src/cloud/client/index.ts @@ -1,6 +1,6 @@ import { BuildURI, CoerceURI, KeyedResolvOnce, runtimeFn, URI } from "@adviser/cement"; import { bs, Database, fireproof } from "@fireproof/core"; -import { ConnectFunction, connectionFactory, makeKeyBagUrlExtractable } from "../connection-from-store.js"; +import { ConnectFunction, connectionFactory, makeKeyBagUrlExtractable } from "../../connection-from-store.js"; import { registerFireproofCloudStoreProtocol } from "./gateway.js"; interface ConnectData { diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 80b372c0..84f5928c 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -1,17 +1,17 @@ // import { env } from "cloudflare:test" import { BuildURI, Future, URI } from "@adviser/cement"; -import { ReqSignedUrl, ResSignedUrl } from "./msg-types"; -import { Env } from "./backend/env"; +import { ReqSignedUrl, ResSignedUrl } from "./msg-types.js"; +import { Env } from "./backend/env.js"; import { $ } from "zx"; import fs from "fs/promises"; import * as toml from "smol-toml"; import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; import { AwsClient } from "aws4fetch"; -import { smokeDB } from "../../tests/helper"; -import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway"; -import { calculatePreSignedUrl } from "./pre-signed-url"; -import { newWebSocket } from "./new-websocket"; +import { smokeDB } from "../../tests/helper.js"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.js"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; +import { newWebSocket } from "./new-websocket.js"; function testReqSignedUrl(tid = "test") { return { diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts index 2a4ed25f..70104a2c 100644 --- a/src/cloud/pre-signed-url.ts +++ b/src/cloud/pre-signed-url.ts @@ -1,7 +1,7 @@ import { Result, URI, BuildURI } from "@adviser/cement"; import { AwsClient } from "aws4fetch"; -import { Env } from "./backend/env"; -import { ReqSignedUrl } from "./msg-types"; +import { Env } from "./backend/env.js"; +import { ReqSignedUrl } from "./msg-types.js"; export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env, amzDate?: string): Promise> { let store: string = req.params.store; diff --git a/src/netlify/gateway.ts b/src/netlify/gateway.ts index 7ca9f0fa..4283076f 100644 --- a/src/netlify/gateway.ts +++ b/src/netlify/gateway.ts @@ -1,6 +1,6 @@ import { KeyedResolvOnce, Result, URI, BuildURI, exception2Result } from "@adviser/cement"; import { bs, getStore, Logger, NotFoundError, SuperThis, ensureSuperLog } from "@fireproof/core"; -import { to_uint8 } from "../coerce-binary"; +import { to_uint8 } from "../coerce-binary.js"; export class NetlifyGateway implements bs.Gateway { readonly sthis: SuperThis; diff --git a/src/netlify/server.ts b/src/netlify/server.ts index d672e1e7..754c1ede 100644 --- a/src/netlify/server.ts +++ b/src/netlify/server.ts @@ -1,5 +1,5 @@ import { getStore } from "@netlify/blobs"; -import { to_blob } from "../coerce-binary"; +import { to_blob } from "../coerce-binary.js"; // eslint-disable-next-line no-console console.log("fireproof edge function loaded netlify"); diff --git a/src/partykit/gateway.ts b/src/partykit/gateway.ts index 38b797fd..14d3df5e 100644 --- a/src/partykit/gateway.ts +++ b/src/partykit/gateway.ts @@ -1,7 +1,7 @@ import { PartySocket, PartySocketOptions } from "partysocket"; import { Result, URI, BuildURI, KeyedResolvOnce, runtimeFn, exception2Result } from "@adviser/cement"; import { bs, ensureLogger, getStore, Logger, rt, SuperThis } from "@fireproof/core"; -import { to_uint8 } from "../coerce-binary"; +import { to_uint8 } from "../coerce-binary.js"; export class PartyKitGateway implements bs.Gateway { readonly logger: Logger; diff --git a/src/ucan/common.ts b/src/ucan/common.ts index 4821090a..abdf2114 100644 --- a/src/ucan/common.ts +++ b/src/ucan/common.ts @@ -3,7 +3,7 @@ import { Delegation } from "@ucanto/interface"; import type { AgentDataExport, DelegationMeta } from "@web3-storage/access/types"; import { Block } from "multiformats/block"; import { CID } from "multiformats"; -import { to_arraybuf } from "../coerce-binary"; +import { to_arraybuf } from "../coerce-binary.js"; export async function extractDelegation(dataExport: AgentDataExport): Promise { const delegationKey = Array.from(dataExport.delegations.keys())[0]; diff --git a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts index 7cca885b..ad3d8bee 100644 --- a/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts +++ b/tests/connect-netlify/app/netlify/edge-functions/fireproof.ts @@ -1,5 +1,5 @@ import { getStore } from "@netlify/blobs"; -import { to_blob } from "../../../../../src/coerce-binary"; +import { to_blob } from "../../../../../src/coerce-binary.js"; // eslint-disable-next-line no-console console.log("fireproof edge function loaded netlify"); From f919140f5b8cac7efc486faeb97289a876106cb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:24:25 +0000 Subject: [PATCH 12/83] chore(deps-dev): bump vitest from 2.1.6 to 2.1.8 Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 2.1.6 to 2.1.8. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.8/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 657 ++++++++++++++++++------------------------------- 2 files changed, 242 insertions(+), 417 deletions(-) diff --git a/package.json b/package.json index 20043d10..e18b6ea7 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "vite": "^6.0.2", "vite-tsconfig-paths": "^5.1.3", "wait-on": "^8.0.1", - "vitest": "^2.1.6", + "vitest": "^2.1.8", "wrangler": "^3.91.0", "zx": "^8.2.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9957673b..a51e8024 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,13 +10,13 @@ importers: dependencies: '@adviser/cement': specifier: ^0.2.40 - version: 0.2.40(typescript@5.7.2) + version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.703.0 - version: 3.703.0 + version: 3.705.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 - version: 0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) + version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 @@ -82,10 +82,10 @@ importers: version: 1.0.20 better-sqlite3: specifier: ^11.6.0 - version: 11.6.0 + version: 11.7.0 cborg: specifier: ^4.2.6 - version: 4.2.6 + version: 4.2.7 cmd-ts: specifier: ^0.13.0 version: 0.13.0 @@ -142,7 +142,7 @@ importers: version: 8.0.1 wrangler: specifier: ^3.87.0 - version: 3.91.0(@cloudflare/workers-types@4.20241205.0) + version: 3.93.0(@cloudflare/workers-types@4.20241205.0) ws: specifier: ^8.18.0 version: 8.18.0 @@ -185,7 +185,7 @@ importers: version: 9.16.0 prettier: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.2 semver: specifier: ^7.6.3 version: 7.6.3 @@ -203,15 +203,15 @@ importers: version: 5.7.2 typescript-eslint: specifier: ^8.16.0 - version: 8.16.0(eslint@9.16.0)(typescript@5.7.2) + version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) vite: specifier: ^6.0.2 version: 6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.3 - version: 5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) vitest: - specifier: ^2.1.6 + specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.1) zx: specifier: ^8.2.4 @@ -219,8 +219,8 @@ importers: packages: - '@adviser/cement@0.2.40': - resolution: {integrity: sha512-AJR27jKVGkbXmyFHdmPWGHiHflSeg1GwkUNEeb6t5Vv8I4uNPAnRs9Xw8TumMIj9OYgsn2QHxFEB6mpyk1xdsA==} + '@adviser/cement@0.2.41': + resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -246,8 +246,8 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.703.0': - resolution: {integrity: sha512-4TSrIamzASTeRPKXrTLcEwo+viPTuOSGcbXh4HC1R0m/rXwK0BHJ4btJ0Q34nZNF+WzvM+FiemXVjNc8qTAxog==} + '@aws-sdk/client-s3@3.705.0': + resolution: {integrity: sha512-Fm0Cbc4zr0yG0DnNycz7ywlL5tQFdLSb7xCIPfzrxJb3YQiTXWxH5eu61SSsP/Z6RBNRolmRPvst/iNgX0fWvA==} engines: {node: '>=16.0.0'} '@aws-sdk/client-sso-oidc@3.699.0': @@ -390,8 +390,8 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} - '@cloudflare/vitest-pool-workers@0.5.33': - resolution: {integrity: sha512-gsMArZ7fN9WB8blVIK8kVPXV8zI7JuoQN6n4grBYMmJgqfLrWE5N8NnEz0O5qagyLQJvD9TxD16WZOzVT/fbzw==} + '@cloudflare/vitest-pool-workers@0.5.34': + resolution: {integrity: sha512-OoC51MBgz0z/SNG5GnvE9VAyBB/xxJODb7OazoWyZlMWe8HIGjg/Dti1hyn18dugJeIL6WiT11E90CLVbNl48g==} peerDependencies: '@vitest/runner': 2.0.x - 2.1.x '@vitest/snapshot': 2.0.x - 2.1.x @@ -403,14 +403,8 @@ packages: cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-64@1.20241106.1': - resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==} - engines: {node: '>=16'} - cpu: [x64] - os: [darwin] - - '@cloudflare/workerd-darwin-64@1.20241106.2': - resolution: {integrity: sha512-p3PzgiMBp9xKo4dMINM1RkrC+miUtz65IuuMCEdCa5QZTM0eyEGcBj1A9/lmS3wW72oMfRTo6CxCkqPteFJeBA==} + '@cloudflare/workerd-darwin-64@1.20241205.0': + resolution: {integrity: sha512-TArEZkSZkHJyEwnlWWkSpCI99cF6lJ14OVeEoI9Um/+cD9CKZLM9vCmsLeKglKheJ0KcdCnkA+DbeD15t3VaWg==} engines: {node: '>=16'} cpu: [x64] os: [darwin] @@ -421,14 +415,8 @@ packages: cpu: [arm64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20241106.1': - resolution: {integrity: sha512-j3dg/42D/bPgfNP3cRUBxF+4waCKO/5YKwXNj+lnVOwHxDu+ne5pFw9TIkKYcWTcwn0ZUkbNZNM5rhJqRn4xbg==} - engines: {node: '>=16'} - cpu: [arm64] - os: [darwin] - - '@cloudflare/workerd-darwin-arm64@1.20241106.2': - resolution: {integrity: sha512-AZQTAKG6bP9z0SKSXQGlXR2K2MQnDMtKC78NGjN0NOcjALTsFlLFhczaLvmuJjsT16k9yJUq2Gl+NG4ao/qgvg==} + '@cloudflare/workerd-darwin-arm64@1.20241205.0': + resolution: {integrity: sha512-u5eqKa9QRdA8MugfgCoD+ADDjY6EpKbv3hSYJETmmUh17l7WXjWBzv4pUvOKIX67C0UzMUy4jZYwC53MymhX3w==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] @@ -439,14 +427,8 @@ packages: cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-64@1.20241106.1': - resolution: {integrity: sha512-Ih+Ye8E1DMBXcKrJktGfGztFqHKaX1CeByqshmTbODnWKHt6O65ax3oTecUwyC0+abuyraOpAtdhHNpFMhUkmw==} - engines: {node: '>=16'} - cpu: [x64] - os: [linux] - - '@cloudflare/workerd-linux-64@1.20241106.2': - resolution: {integrity: sha512-TWIcVdUzU7w7YP2OEIgTDtNl9jyzjxOptjRDw7jhSUsQy/02IjBLP+ZnNpgB5CUJ1tCbcOp1L2IGhZmayd7OEQ==} + '@cloudflare/workerd-linux-64@1.20241205.0': + resolution: {integrity: sha512-OYA7S5zpumMamWEW+IhhBU6YojIEocyE5X/YFPiTOCrDE3dsfr9t6oqNE7hxGm1VAAu+Irtl+a/5LwmBOU681w==} engines: {node: '>=16'} cpu: [x64] os: [linux] @@ -457,14 +439,8 @@ packages: cpu: [arm64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20241106.1': - resolution: {integrity: sha512-mdQFPk4+14Yywn7n1xIzI+6olWM8Ybz10R7H3h+rk0XulMumCWUCy1CzIDauOx6GyIcSgKIibYMssVHZR30ObA==} - engines: {node: '>=16'} - cpu: [arm64] - os: [linux] - - '@cloudflare/workerd-linux-arm64@1.20241106.2': - resolution: {integrity: sha512-f5Mn9IzfLs9yGjB2UCcKh+I7Ahiw6xqiQ9f/FGsHjsgLELjJ8JCKBwXmc9WdfNmVPae5jNCg2N5qVfDoWBKbCA==} + '@cloudflare/workerd-linux-arm64@1.20241205.0': + resolution: {integrity: sha512-qAzecONjFJGIAVJZKExQ5dlbic0f3d4A+GdKa+H6SoUJtPaWiE3K6WuePo4JOT7W3/Zfh25McmX+MmpMUUcM5Q==} engines: {node: '>=16'} cpu: [arm64] os: [linux] @@ -475,24 +451,14 @@ packages: cpu: [x64] os: [win32] - '@cloudflare/workerd-windows-64@1.20241106.1': - resolution: {integrity: sha512-4rtcss31E/Rb/PeFocZfr+B9i1MdrkhsTBWizh8siNR4KMmkslU2xs2wPaH1z8+ErxkOsHrKRa5EPLh5rIiFeg==} + '@cloudflare/workerd-windows-64@1.20241205.0': + resolution: {integrity: sha512-BEab+HiUgCdl6GXAT7EI2yaRtDPiRJlB94XLvRvXi1ZcmQqsrq6awGo6apctFo4WUL29V7c09LxmN4HQ3X2Tvg==} engines: {node: '>=16'} cpu: [x64] os: [win32] - '@cloudflare/workerd-windows-64@1.20241106.2': - resolution: {integrity: sha512-kdLExN3rktax23iHUKP7AHQP0HT0yGHik58fMP4kExjsMnwxw92TLI3n4HlmEqsbtMtwr9rhTJVaMBRUXq0aXw==} - engines: {node: '>=16'} - cpu: [x64] - os: [win32] - - '@cloudflare/workers-shared@0.9.0': - resolution: {integrity: sha512-eP6Ir45uPbKnpADVzUCtkRUYxYxjB1Ew6n/whTJvHu8H4m93USHAceCMm736VBZdlxuhXXUjEP3fCUxKPn+cfw==} - engines: {node: '>=16.7.0'} - - '@cloudflare/workers-shared@0.9.1': - resolution: {integrity: sha512-56w4pL5D6ODw7+SieMgdwrwNyyT7tY8H4UPD4/95TSBVjqDcMPq0Dr+D4rJ+nHK+290o4ZnSiOOiKqRMqy6tPg==} + '@cloudflare/workers-shared@0.10.0': + resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} engines: {node: '>=16.7.0'} '@cloudflare/workers-types@4.20240718.0': @@ -1661,8 +1627,8 @@ packages: '@types/ws@8.5.13': resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@typescript-eslint/eslint-plugin@8.16.0': - resolution: {integrity: sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==} + '@typescript-eslint/eslint-plugin@8.17.0': + resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -1672,8 +1638,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.16.0': - resolution: {integrity: sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==} + '@typescript-eslint/parser@8.17.0': + resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -1682,12 +1648,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@8.16.0': - resolution: {integrity: sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==} + '@typescript-eslint/scope-manager@8.17.0': + resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.16.0': - resolution: {integrity: sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==} + '@typescript-eslint/type-utils@8.17.0': + resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -1696,23 +1662,10 @@ packages: typescript: optional: true - '@typescript-eslint/types@8.16.0': - resolution: {integrity: sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.17.0': resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.16.0': - resolution: {integrity: sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/typescript-estree@8.17.0': resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1722,8 +1675,8 @@ packages: typescript: optional: true - '@typescript-eslint/utils@8.16.0': - resolution: {integrity: sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==} + '@typescript-eslint/utils@8.17.0': + resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -1732,10 +1685,6 @@ packages: typescript: optional: true - '@typescript-eslint/visitor-keys@8.16.0': - resolution: {integrity: sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.17.0': resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1975,8 +1924,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - better-sqlite3@11.6.0: - resolution: {integrity: sha512-2J6k/eVxcFYY2SsTxsXrj6XylzHWPxveCn4fKPKZFv/Vqn/Cd7lOuX4d7rGQXT5zL+97MkNL3nSbCrIoe3LkgA==} + better-sqlite3@11.7.0: + resolution: {integrity: sha512-mXpa5jnIKKHeoGzBrUJrc65cXFKcILGZpU3FXR0pradUEm9MA7UZz02qfEejaMcm9iXrSOCenwwYMJ/tZ1y5Ig==} big-counter-x@4.1.2: resolution: {integrity: sha512-rO414jDJf//NDNvIfbChPT+qAXrs5aXIWwq+327qWVn64eKpE+dMsr72o+18tYsSOnF79C6+LO9c756/h6Ghaw==} @@ -2063,8 +2012,8 @@ packages: carstream@2.2.0: resolution: {integrity: sha512-/gHkK0lQjmGM45fhdx8JD+x7a1XS1qUk3T9xWWSt3oZiWPLq4u/lnDstp+N55K7hqTKKlb0CCr43EHTrlbmJSQ==} - cborg@4.2.6: - resolution: {integrity: sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==} + cborg@4.2.7: + resolution: {integrity: sha512-zHTUAm+HAoRLtGEQ1b28HXBm8d/5YP+7eiSKzEu/mpFkptGYaMQCHv15OiQBuyNlIgbCBXvBbZQPl3xvcZTJXg==} hasBin: true chai@5.1.2: @@ -3020,8 +2969,8 @@ packages: resolution: {integrity: sha512-mQ2o1VayrZ6Jaz8VyP8B7h/hdn2iAnbUOrQh4rTiwbpULhktpD8IpHGBw8Qo2fmv97Z1P3YzLF3X/DkbIHBQmA==} engines: {node: '>=8.11.4', npm: 6.10.1} - memfs@4.14.1: - resolution: {integrity: sha512-Fq5CMEth+2iprLJ5mNizRcWuiwRZYjNkUD0zKk224jZunE9CRacTRDK8QLALbMBlNX2y3nY6lKZbesCwDwacig==} + memfs@4.15.0: + resolution: {integrity: sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==} engines: {node: '>= 4.0.0'} memoizee@0.4.17: @@ -3069,13 +3018,8 @@ packages: engines: {node: '>=16.13'} hasBin: true - miniflare@3.20241106.1: - resolution: {integrity: sha512-dM3RBlJE8rUFxnqlPCaFCq0E7qQqEQvKbYX7W/APGCK+rLcyLmEBzC4GQR/niXdNM/oV6gdg9AA50ghnn2ALuw==} - engines: {node: '>=16.13'} - hasBin: true - - miniflare@3.20241106.2: - resolution: {integrity: sha512-40JAPtNFMFrSW41CSxPgDykX4CgDokDfTZgDYYL8dsODb7pdAlj/dvlDPnaonkyXjRO7svyDwAavQT6IdagMwA==} + miniflare@3.20241205.0: + resolution: {integrity: sha512-Z0cTtIf6ZrcAJ3SrOI9EUM3s4dkGhNeU6Ubl8sroYhsPVD+rtz3m5+p6McHFWCkcMff1o60X5XEKVTmkz0gbpA==} engines: {node: '>=16.13'} hasBin: true @@ -3269,8 +3213,8 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-map@7.0.2: - resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} engines: {node: '>=18'} p-queue@8.0.1: @@ -3398,8 +3342,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.4.1: - resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==} + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} engines: {node: '>=14'} hasBin: true @@ -3500,10 +3444,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} - engines: {node: '>=10'} - resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -3906,8 +3846,8 @@ packages: type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - typescript-eslint@8.16.0: - resolution: {integrity: sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==} + typescript-eslint@8.17.0: + resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3943,8 +3883,8 @@ packages: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} - unenv-nightly@2.0.0-20241121-161142-806b5c0: - resolution: {integrity: sha512-RnFOasE/O0Q55gBkNB1b84OgKttgLEijGO0JCWpbn+O4XxpyCQg89NmcqQ5RGUiy4y+rMIrKzePTquQcLQF5pQ==} + unenv-nightly@2.0.0-20241204-140205-a5d5190: + resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -3990,8 +3930,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite-tsconfig-paths@5.1.3: - resolution: {integrity: sha512-0bz+PDlLpGfP2CigeSKL9NFTF1KtXkeHGZSSaGQSuPZH77GhoiQaA8IjYgOaynSuwlDTolSUEU0ErVvju3NURg==} + vite-tsconfig-paths@5.1.4: + resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==} peerDependencies: vite: '*' peerDependenciesMeta: @@ -4150,32 +4090,17 @@ packages: engines: {node: '>=16'} hasBin: true - workerd@1.20241106.1: - resolution: {integrity: sha512-1GdKl0kDw8rrirr/ThcK66Kbl4/jd4h8uHx5g7YHBrnenY5SX1UPuop2cnCzYUxlg55kPjzIqqYslz1muRFgFw==} + workerd@1.20241205.0: + resolution: {integrity: sha512-vso/2n0c5SdBDWiD+Sx5gM7unA6SiZXRVUHDqH1euoP/9mFVHZF8icoYsNLB87b/TX8zNgpae+I5N/xFpd9v0g==} engines: {node: '>=16'} hasBin: true - workerd@1.20241106.2: - resolution: {integrity: sha512-Xw2hVIXA9MvDSHx3IX55ouGRPsQUzG0oadRVeQRs5xwgmiKshR0ompyYDO1JUvozJazfjcCSdgV8jyLcPqNIDA==} - engines: {node: '>=16'} - hasBin: true - - wrangler@3.91.0: - resolution: {integrity: sha512-Hdzn6wbY9cz5kL85ZUvWLwLIH7nPaEVRblfms40jhRf4qQO/Zf74aFlku8rQFbe8/2aVZFaxJVfBd6JQMeMSBQ==} - engines: {node: '>=16.17.0'} - hasBin: true - peerDependencies: - '@cloudflare/workers-types': ^4.20241106.0 - peerDependenciesMeta: - '@cloudflare/workers-types': - optional: true - - wrangler@3.92.0: - resolution: {integrity: sha512-MC+s+stSYQKXEn7ucENhzrw+RyMc5bSIRQ2EVcjCtqjAtO82uKQBatW2YXK5hkQOZg9Kfcdqgkcnpf/Bn94FiA==} + wrangler@3.93.0: + resolution: {integrity: sha512-+wfxjOrtm6YgDS+NdJkB6aiBIS3ED97mNRQmfrEShRJW4pVo4sWY6oQ1FsGT+j4tGHplrTbWCE6U5yTgjNW/lw==} engines: {node: '>=16.17.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20241106.0 + '@cloudflare/workers-types': ^4.20241205.0 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -4235,7 +4160,7 @@ packages: snapshots: - '@adviser/cement@0.2.40(typescript@5.7.2)': + '@adviser/cement@0.2.41(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4246,13 +4171,13 @@ snapshots: dependencies: '@aws-crypto/util': 5.2.0 '@aws-sdk/types': 3.696.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 '@aws-sdk/types': 3.696.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: @@ -4261,7 +4186,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/sha256-browser@5.2.0': dependencies: @@ -4271,25 +4196,25 @@ snapshots: '@aws-sdk/types': 3.696.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 '@aws-sdk/types': 3.696.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@aws-crypto/util@5.2.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.7.0 + tslib: 2.8.1 - '@aws-sdk/client-s3@3.703.0': + '@aws-sdk/client-s3@3.705.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 @@ -4348,7 +4273,7 @@ snapshots: '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 '@smithy/util-waiter': 3.1.9 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -4393,7 +4318,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -4436,7 +4361,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -4481,7 +4406,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -4497,7 +4422,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-middleware': 3.0.10 fast-xml-parser: 4.4.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/credential-provider-env@3.696.0': dependencies: @@ -4505,7 +4430,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.696.0': dependencies: @@ -4518,7 +4443,7 @@ snapshots: '@smithy/smithy-client': 3.4.4 '@smithy/types': 3.7.1 '@smithy/util-stream': 3.3.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/credential-provider-ini@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0)': dependencies: @@ -4534,7 +4459,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -4552,7 +4477,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - '@aws-sdk/client-sts' @@ -4565,7 +4490,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/credential-provider-sso@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': dependencies: @@ -4576,7 +4501,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -4588,7 +4513,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-bucket-endpoint@3.696.0': dependencies: @@ -4598,14 +4523,14 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 '@smithy/util-config-provider': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-expect-continue@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-flexible-checksums@3.701.0': dependencies: @@ -4621,33 +4546,33 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-host-header@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-location-constraint@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-logger@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-sdk-s3@3.696.0': dependencies: @@ -4664,13 +4589,13 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-ssec@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.696.0': dependencies: @@ -4680,7 +4605,7 @@ snapshots: '@smithy/core': 2.5.3 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/region-config-resolver@3.696.0': dependencies: @@ -4689,7 +4614,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/signature-v4-multi-region@3.696.0': dependencies: @@ -4698,7 +4623,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/signature-v4': 4.2.3 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/token-providers@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': dependencies: @@ -4707,34 +4632,34 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/types@3.696.0': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/util-arn-parser@3.693.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/util-endpoints@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 '@smithy/util-endpoints': 2.1.6 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/util-locate-window@3.568.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/util-user-agent-browser@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 bowser: 2.11.0 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/util-user-agent-node@3.696.0': dependencies: @@ -4742,18 +4667,18 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/node-config-provider': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@aws-sdk/xml-builder@3.696.0': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@cloudflare/kv-asset-handler@0.3.4': dependencies: mime: 3.0.0 - '@cloudflare/vitest-pool-workers@0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1))': + '@cloudflare/vitest-pool-workers@0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1))': dependencies: '@vitest/runner': 2.1.8 '@vitest/snapshot': 2.1.8 @@ -4761,10 +4686,10 @@ snapshots: cjs-module-lexer: 1.4.1 devalue: 4.3.3 esbuild: 0.17.19 - miniflare: 3.20241106.2 + miniflare: 3.20241205.0 semver: 7.6.3 vitest: 2.1.8(@types/node@22.10.1) - wrangler: 3.92.0(@cloudflare/workers-types@4.20241205.0) + wrangler: 3.93.0(@cloudflare/workers-types@4.20241205.0) zod: 3.23.8 transitivePeerDependencies: - '@cloudflare/workers-types' @@ -4775,54 +4700,34 @@ snapshots: '@cloudflare/workerd-darwin-64@1.20240718.0': optional: true - '@cloudflare/workerd-darwin-64@1.20241106.1': - optional: true - - '@cloudflare/workerd-darwin-64@1.20241106.2': + '@cloudflare/workerd-darwin-64@1.20241205.0': optional: true '@cloudflare/workerd-darwin-arm64@1.20240718.0': optional: true - '@cloudflare/workerd-darwin-arm64@1.20241106.1': - optional: true - - '@cloudflare/workerd-darwin-arm64@1.20241106.2': + '@cloudflare/workerd-darwin-arm64@1.20241205.0': optional: true '@cloudflare/workerd-linux-64@1.20240718.0': optional: true - '@cloudflare/workerd-linux-64@1.20241106.1': - optional: true - - '@cloudflare/workerd-linux-64@1.20241106.2': + '@cloudflare/workerd-linux-64@1.20241205.0': optional: true '@cloudflare/workerd-linux-arm64@1.20240718.0': optional: true - '@cloudflare/workerd-linux-arm64@1.20241106.1': - optional: true - - '@cloudflare/workerd-linux-arm64@1.20241106.2': + '@cloudflare/workerd-linux-arm64@1.20241205.0': optional: true '@cloudflare/workerd-windows-64@1.20240718.0': optional: true - '@cloudflare/workerd-windows-64@1.20241106.1': + '@cloudflare/workerd-windows-64@1.20241205.0': optional: true - '@cloudflare/workerd-windows-64@1.20241106.2': - optional: true - - '@cloudflare/workers-shared@0.9.0': - dependencies: - mime: 3.0.0 - zod: 3.23.8 - - '@cloudflare/workers-shared@0.9.1': + '@cloudflare/workers-shared@0.10.0': dependencies: mime: 3.0.0 zod: 3.23.8 @@ -5167,20 +5072,20 @@ snapshots: '@fireproof/core@0.19.114(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.2.40(typescript@5.7.2) + '@adviser/cement': 0.2.41(typescript@5.7.2) '@ipld/car': 5.3.3 '@ipld/dag-cbor': 9.2.2 '@ipld/dag-json': 10.2.3 '@ipld/unixfs': 3.0.0 '@web3-storage/pail': 0.6.0 - cborg: 4.2.6 + cborg: 4.2.7 charwise: 3.0.1 idb: 8.0.0 ipfs-unixfs-exporter: 13.6.1 - memfs: 4.14.1 + memfs: 4.15.0 multiformats: 13.3.1 p-limit: 6.1.0 - p-map: 7.0.2 + p-map: 7.0.3 p-retry: 6.2.1 prolly-trees: 1.0.4 react: 18.3.1 @@ -5191,7 +5096,7 @@ snapshots: dependencies: '@ipld/car': 5.3.3 '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 + '@ipld/dag-json': 10.2.2 '@ipld/unixfs': 2.2.0 '@peculiar/webcrypto': 1.5.0 '@web3-storage/pail': 0.6.0 @@ -5260,30 +5165,30 @@ snapshots: '@ipld/car@5.3.2': dependencies: '@ipld/dag-cbor': 9.2.2 - cborg: 4.2.6 + cborg: 4.2.7 multiformats: 13.3.1 varint: 6.0.0 '@ipld/car@5.3.3': dependencies: '@ipld/dag-cbor': 9.2.2 - cborg: 4.2.6 + cborg: 4.2.7 multiformats: 13.3.1 varint: 6.0.0 '@ipld/dag-cbor@9.2.2': dependencies: - cborg: 4.2.6 + cborg: 4.2.7 multiformats: 13.3.1 '@ipld/dag-json@10.2.2': dependencies: - cborg: 4.2.6 + cborg: 4.2.7 multiformats: 13.3.1 '@ipld/dag-json@10.2.3': dependencies: - cborg: 4.2.6 + cborg: 4.2.7 multiformats: 13.3.1 '@ipld/dag-pb@4.1.2': @@ -5347,21 +5252,21 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jsonjoy.com/base64@1.1.2(tslib@2.7.0)': + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 - '@jsonjoy.com/json-pack@1.1.0(tslib@2.7.0)': + '@jsonjoy.com/json-pack@1.1.0(tslib@2.8.1)': dependencies: - '@jsonjoy.com/base64': 1.1.2(tslib@2.7.0) - '@jsonjoy.com/util': 1.5.0(tslib@2.7.0) + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) hyperdyperid: 1.2.0 - thingies: 1.21.0(tslib@2.7.0) - tslib: 2.7.0 + thingies: 1.21.0(tslib@2.8.1) + tslib: 2.8.1 - '@jsonjoy.com/util@1.5.0(tslib@2.7.0)': + '@jsonjoy.com/util@1.5.0(tslib@2.8.1)': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@jspm/core@2.1.0': {} @@ -5396,18 +5301,18 @@ snapshots: dependencies: asn1js: 3.0.5 pvtsutils: 1.3.6 - tslib: 2.7.0 + tslib: 2.8.1 '@peculiar/json-schema@1.1.12': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@peculiar/webcrypto@1.5.0': dependencies: '@peculiar/asn1-schema': 2.3.13 '@peculiar/json-schema': 1.1.12 pvtsutils: 1.3.6 - tslib: 2.7.0 + tslib: 2.8.1 webcrypto-core: 1.8.1 '@perma/map@1.0.3': @@ -5507,16 +5412,16 @@ snapshots: '@smithy/abort-controller@3.1.8': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/chunked-blob-reader-native@3.0.1': dependencies: '@smithy/util-base64': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/chunked-blob-reader@4.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/config-resolver@3.0.12': dependencies: @@ -5524,7 +5429,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/core@2.5.3': dependencies: @@ -5535,7 +5440,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/credential-provider-imds@3.2.7': dependencies: @@ -5543,37 +5448,37 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 '@smithy/url-parser': 3.0.10 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/eventstream-codec@3.1.9': dependencies: '@aws-crypto/crc32': 5.2.0 '@smithy/types': 3.7.1 '@smithy/util-hex-encoding': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/eventstream-serde-browser@3.0.13': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/eventstream-serde-config-resolver@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/eventstream-serde-node@3.0.12': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/eventstream-serde-universal@3.0.12': dependencies: '@smithy/eventstream-codec': 3.1.9 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/fetch-http-handler@4.1.1': dependencies: @@ -5581,52 +5486,52 @@ snapshots: '@smithy/querystring-builder': 3.0.10 '@smithy/types': 3.7.1 '@smithy/util-base64': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/hash-blob-browser@3.1.9': dependencies: '@smithy/chunked-blob-reader': 4.0.0 '@smithy/chunked-blob-reader-native': 3.0.1 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/hash-node@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/hash-stream-node@3.1.9': dependencies: '@smithy/types': 3.7.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/invalid-dependency@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/is-array-buffer@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/md5-js@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/middleware-content-length@3.0.12': dependencies: '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/middleware-endpoint@3.2.3': dependencies: @@ -5637,7 +5542,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/url-parser': 3.0.10 '@smithy/util-middleware': 3.0.10 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/middleware-retry@3.0.27': dependencies: @@ -5648,25 +5553,25 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 - tslib: 2.7.0 + tslib: 2.8.1 uuid: 9.0.1 '@smithy/middleware-serde@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/middleware-stack@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/node-config-provider@3.1.11': dependencies: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/node-http-handler@3.3.1': dependencies: @@ -5674,28 +5579,28 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/querystring-builder': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/property-provider@3.1.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/protocol-http@4.1.7': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/querystring-builder@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-uri-escape': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/querystring-parser@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/service-error-classification@3.0.10': dependencies: @@ -5704,7 +5609,7 @@ snapshots: '@smithy/shared-ini-file-loader@3.1.11': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/signature-v4@4.2.3': dependencies: @@ -5715,7 +5620,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-uri-escape': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/smithy-client@3.4.4': dependencies: @@ -5725,7 +5630,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 '@smithy/util-stream': 3.3.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/types@3.7.1': dependencies: @@ -5735,35 +5640,35 @@ snapshots: dependencies: '@smithy/querystring-parser': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-base64@3.0.0': dependencies: '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-body-length-browser@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-body-length-node@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-buffer-from@2.2.0': dependencies: '@smithy/is-array-buffer': 2.2.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-buffer-from@3.0.0': dependencies: '@smithy/is-array-buffer': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-config-provider@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-defaults-mode-browser@3.0.27': dependencies: @@ -5771,7 +5676,7 @@ snapshots: '@smithy/smithy-client': 3.4.4 '@smithy/types': 3.7.1 bowser: 2.11.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-defaults-mode-node@3.0.27': dependencies: @@ -5781,28 +5686,28 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/smithy-client': 3.4.4 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-endpoints@2.1.6': dependencies: '@smithy/node-config-provider': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-hex-encoding@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-middleware@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-retry@3.0.10': dependencies: '@smithy/service-error-classification': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-stream@3.3.1': dependencies: @@ -5813,27 +5718,27 @@ snapshots: '@smithy/util-buffer-from': 3.0.0 '@smithy/util-hex-encoding': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-uri-escape@3.0.0': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-utf8@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-utf8@3.0.0': dependencies: '@smithy/util-buffer-from': 3.0.0 - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/util-waiter@3.1.9': dependencies: '@smithy/abort-controller': 3.1.8 '@smithy/types': 3.7.1 - tslib: 2.7.0 + tslib: 2.8.1 '@storacha/one-webcrypto@1.0.1': {} @@ -5887,14 +5792,14 @@ snapshots: dependencies: '@types/node': 22.10.1 - '@typescript-eslint/eslint-plugin@8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.16.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.16.0 - '@typescript-eslint/type-utils': 8.16.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.16.0 + '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.17.0 eslint: 9.16.0 graphemer: 1.4.0 ignore: 5.3.2 @@ -5905,12 +5810,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.16.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.16.0 - '@typescript-eslint/types': 8.16.0 - '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.16.0 + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.17.0 debug: 4.3.7 eslint: 9.16.0 optionalDependencies: @@ -5918,15 +5823,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.16.0': + '@typescript-eslint/scope-manager@8.17.0': dependencies: - '@typescript-eslint/types': 8.16.0 - '@typescript-eslint/visitor-keys': 8.16.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 - '@typescript-eslint/type-utils@8.16.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) debug: 4.3.7 eslint: 9.16.0 ts-api-utils: 1.3.0(typescript@5.7.2) @@ -5935,25 +5840,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.16.0': {} - '@typescript-eslint/types@8.17.0': {} - '@typescript-eslint/typescript-estree@8.16.0(typescript@5.7.2)': - dependencies: - '@typescript-eslint/types': 8.16.0 - '@typescript-eslint/visitor-keys': 8.16.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.17.0 @@ -5969,23 +5857,18 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.16.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) - '@typescript-eslint/scope-manager': 8.16.0 - '@typescript-eslint/types': 8.16.0 - '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) eslint: 9.16.0 optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.16.0': - dependencies: - '@typescript-eslint/types': 8.16.0 - eslint-visitor-keys: 4.2.0 - '@typescript-eslint/visitor-keys@8.17.0': dependencies: '@typescript-eslint/types': 8.17.0 @@ -6158,7 +6041,7 @@ snapshots: '@ipld/car': 5.3.3 '@ipld/dag-cbor': 9.2.2 archy: 1.0.0 - cborg: 4.2.6 + cborg: 4.2.7 cli-color: 2.0.4 multiformats: 12.1.3 sade: 1.8.1 @@ -6341,7 +6224,7 @@ snapshots: dependencies: pvtsutils: 1.3.6 pvutils: 1.1.3 - tslib: 2.7.0 + tslib: 2.8.1 assert-is-function-x@3.1.2: dependencies: @@ -6394,7 +6277,7 @@ snapshots: base64-js@1.5.1: {} - better-sqlite3@11.6.0: + better-sqlite3@11.7.0: dependencies: bindings: 1.5.0 prebuild-install: 7.1.2 @@ -6488,7 +6371,7 @@ snapshots: capnp-ts@0.7.0: dependencies: debug: 4.3.7 - tslib: 2.7.0 + tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -6498,7 +6381,7 @@ snapshots: multiformats: 13.3.1 uint8arraylist: 2.4.8 - cborg@4.2.6: {} + cborg@4.2.7: {} chai@5.1.2: dependencies: @@ -7698,12 +7581,12 @@ snapshots: is-nan-x: 2.1.1 to-number-x: 3.2.2 - memfs@4.14.1: + memfs@4.15.0: dependencies: - '@jsonjoy.com/json-pack': 1.1.0(tslib@2.7.0) - '@jsonjoy.com/util': 1.5.0(tslib@2.7.0) - tree-dump: 1.0.2(tslib@2.7.0) - tslib: 2.7.0 + '@jsonjoy.com/json-pack': 1.1.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) + tslib: 2.8.1 memoizee@0.4.17: dependencies: @@ -7760,7 +7643,7 @@ snapshots: - supports-color - utf-8-validate - miniflare@3.20241106.1: + miniflare@3.20241205.0: dependencies: '@cspotcode/source-map-support': 0.8.1 acorn: 8.14.0 @@ -7770,26 +7653,7 @@ snapshots: glob-to-regexp: 0.4.1 stoppable: 1.1.0 undici: 5.28.4 - workerd: 1.20241106.1 - ws: 8.18.0 - youch: 3.3.4 - zod: 3.23.8 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - miniflare@3.20241106.2: - dependencies: - '@cspotcode/source-map-support': 0.8.1 - acorn: 8.14.0 - acorn-walk: 8.3.4 - capnp-ts: 0.7.0 - exit-hook: 2.2.1 - glob-to-regexp: 0.4.1 - stoppable: 1.1.0 - undici: 5.28.4 - workerd: 1.20241106.2 + workerd: 1.20241205.0 ws: 8.18.0 youch: 3.3.4 zod: 3.23.8 @@ -7994,7 +7858,7 @@ snapshots: dependencies: p-limit: 3.1.0 - p-map@7.0.2: {} + p-map@7.0.3: {} p-queue@8.0.1: dependencies: @@ -8121,7 +7985,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.4.1: {} + prettier@3.4.2: {} printable-characters@1.0.42: {} @@ -8236,8 +8100,6 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve.exports@2.0.2: {} - resolve@1.22.8: dependencies: is-core-module: 2.15.1 @@ -8480,9 +8342,9 @@ snapshots: dependencies: any-promise: 1.3.0 - thingies@1.21.0(tslib@2.7.0): + thingies@1.21.0(tslib@2.8.1): dependencies: - tslib: 2.7.0 + tslib: 2.8.1 timers-ext@0.1.8: dependencies: @@ -8571,9 +8433,9 @@ snapshots: dependencies: punycode: 2.3.1 - tree-dump@1.0.2(tslib@2.7.0): + tree-dump@1.0.2(tslib@2.8.1): dependencies: - tslib: 2.7.0 + tslib: 2.8.1 tree-kill@1.2.2: {} @@ -8662,11 +8524,11 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.16.0(eslint@9.16.0)(typescript@5.7.2): + typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.16.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.16.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) eslint: 9.16.0 optionalDependencies: typescript: 5.7.2 @@ -8700,7 +8562,7 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - unenv-nightly@2.0.0-20241121-161142-806b5c0: + unenv-nightly@2.0.0-20241204-140205-a5d5190: dependencies: defu: 6.1.4 ohash: 1.1.4 @@ -8767,7 +8629,7 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.3(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 @@ -8851,7 +8713,7 @@ snapshots: '@peculiar/json-schema': 1.1.12 asn1js: 3.0.5 pvtsutils: 1.3.6 - tslib: 2.7.0 + tslib: 2.8.1 webidl-conversions@3.0.1: {} @@ -8907,55 +8769,18 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20240718.0 '@cloudflare/workerd-windows-64': 1.20240718.0 - workerd@1.20241106.1: + workerd@1.20241205.0: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20241106.1 - '@cloudflare/workerd-darwin-arm64': 1.20241106.1 - '@cloudflare/workerd-linux-64': 1.20241106.1 - '@cloudflare/workerd-linux-arm64': 1.20241106.1 - '@cloudflare/workerd-windows-64': 1.20241106.1 - - workerd@1.20241106.2: - optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20241106.2 - '@cloudflare/workerd-darwin-arm64': 1.20241106.2 - '@cloudflare/workerd-linux-64': 1.20241106.2 - '@cloudflare/workerd-linux-arm64': 1.20241106.2 - '@cloudflare/workerd-windows-64': 1.20241106.2 - - wrangler@3.91.0(@cloudflare/workers-types@4.20241205.0): - dependencies: - '@cloudflare/kv-asset-handler': 0.3.4 - '@cloudflare/workers-shared': 0.9.0 - '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) - '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) - blake3-wasm: 2.1.5 - chokidar: 4.0.1 - date-fns: 4.1.0 - esbuild: 0.17.19 - itty-time: 1.0.6 - miniflare: 3.20241106.1 - nanoid: 3.3.7 - path-to-regexp: 6.3.0 - resolve: 1.22.8 - resolve.exports: 2.0.2 - selfsigned: 2.4.1 - source-map: 0.6.1 - unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0 - workerd: 1.20241106.1 - xxhash-wasm: 1.0.2 - optionalDependencies: - '@cloudflare/workers-types': 4.20241205.0 - fsevents: 2.3.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate + '@cloudflare/workerd-darwin-64': 1.20241205.0 + '@cloudflare/workerd-darwin-arm64': 1.20241205.0 + '@cloudflare/workerd-linux-64': 1.20241205.0 + '@cloudflare/workerd-linux-arm64': 1.20241205.0 + '@cloudflare/workerd-windows-64': 1.20241205.0 - wrangler@3.92.0(@cloudflare/workers-types@4.20241205.0): + wrangler@3.93.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 - '@cloudflare/workers-shared': 0.9.1 + '@cloudflare/workers-shared': 0.10.0 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) blake3-wasm: 2.1.5 @@ -8963,14 +8788,14 @@ snapshots: date-fns: 4.1.0 esbuild: 0.17.19 itty-time: 1.0.6 - miniflare: 3.20241106.2 + miniflare: 3.20241205.0 nanoid: 3.3.7 path-to-regexp: 6.3.0 resolve: 1.22.8 selfsigned: 2.4.1 source-map: 0.6.1 - unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0 - workerd: 1.20241106.2 + unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190 + workerd: 1.20241205.0 xxhash-wasm: 1.0.2 optionalDependencies: '@cloudflare/workers-types': 4.20241205.0 From 98f7a51406703fb2e3698adee5e8a3bd63d20fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:25:24 +0000 Subject: [PATCH 13/83] chore(deps): bump better-sqlite3 from 11.6.0 to 11.7.0 Bumps [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) from 11.6.0 to 11.7.0. - [Release notes](https://github.com/WiseLibs/better-sqlite3/releases) - [Commits](https://github.com/WiseLibs/better-sqlite3/compare/v11.6.0...v11.7.0) --- updated-dependencies: - dependency-name: better-sqlite3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e18b6ea7..2668fde5 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", "assert": "^2.1.0", - "better-sqlite3": "^11.6.0", + "better-sqlite3": "^11.7.0", "aws4fetch": "^1.0.20", "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", From 41152de865b37d0ca6eea91968cb2895d81836a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:25:07 +0000 Subject: [PATCH 14/83] chore(deps-dev): bump @typescript-eslint/typescript-estree Bumps [@typescript-eslint/typescript-estree](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-estree) from 8.16.0 to 8.17.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-estree/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.17.0/packages/typescript-estree) --- updated-dependencies: - dependency-name: "@typescript-eslint/typescript-estree" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2668fde5..ed25c9cb 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@types/node": "^22.10.1", "@types/wait-on": "^5.3.4", "@types/ws": "^8.5.13", - "@typescript-eslint/typescript-estree": "^8.16.0", + "@typescript-eslint/typescript-estree": "^8.17.0", "@web3-storage/access": "^20.1.0", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a51e8024..70d0ceac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -169,7 +169,7 @@ importers: specifier: ^8.5.13 version: 8.5.13 '@typescript-eslint/typescript-estree': - specifier: ^8.16.0 + specifier: ^8.17.0 version: 8.17.0(typescript@5.7.2) esbuild: specifier: ^0.24.0 From ec30e83a12b9631d787671d3faaf68ca1ae3fe71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:26:28 +0000 Subject: [PATCH 15/83] chore(deps): bump @adviser/cement from 0.2.40 to 0.2.41 Bumps [@adviser/cement](https://github.com/mabels/cement) from 0.2.40 to 0.2.41. - [Commits](https://github.com/mabels/cement/compare/v0.2.40...v0.2.41) --- updated-dependencies: - dependency-name: "@adviser/cement" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ed25c9cb..686ed007 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "@adviser/cement": "^0.2.40" }, "dependencies": { - "@adviser/cement": "^0.2.40", + "@adviser/cement": "^0.2.41", "@aws-sdk/client-s3": "^3.703.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70d0ceac..93f4e000 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,7 +9,7 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.40 + specifier: ^0.2.41 version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.703.0 From 264193dc6a3e93620726984e629c3d5193934376 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:38:40 +0000 Subject: [PATCH 16/83] chore(deps-dev): bump typescript-eslint from 8.16.0 to 8.17.0 Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.16.0 to 8.17.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.17.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 686ed007..9e1fb093 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "tsup": "^8.3.5", "tsx": "^4.19.2", "typescript": "^5.7.2", - "typescript-eslint": "^8.16.0", + "typescript-eslint": "^8.17.0", "vite": "^6.0.2", "vite-tsconfig-paths": "^5.1.3", "wait-on": "^8.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93f4e000..ef6c4f10 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -202,7 +202,7 @@ importers: specifier: ^5.7.2 version: 5.7.2 typescript-eslint: - specifier: ^8.16.0 + specifier: ^8.17.0 version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) vite: specifier: ^6.0.2 From 1b6c61e69448fb09edfb03080a5aedcb5f12fd09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:40:40 +0000 Subject: [PATCH 17/83] chore(deps): bump @aws-sdk/client-s3 from 3.703.0 to 3.705.0 Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.703.0 to 3.705.0. - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.705.0/clients/client-s3) --- updated-dependencies: - dependency-name: "@aws-sdk/client-s3" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9e1fb093..0f098d67 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ }, "dependencies": { "@adviser/cement": "^0.2.41", - "@aws-sdk/client-s3": "^3.703.0", + "@aws-sdk/client-s3": "^3.705.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", "@cloudflare/workers-types": "^4.20241112.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef6c4f10..f79ddc09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,7 +12,7 @@ importers: specifier: ^0.2.41 version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': - specifier: ^3.703.0 + specifier: ^3.705.0 version: 3.705.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 From 2c93d7dadca9d5850bdac763bef014d2652e2d83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:39:42 +0000 Subject: [PATCH 18/83] chore(deps): bump cborg from 4.2.6 to 4.2.7 Bumps [cborg](https://github.com/rvagg/cborg) from 4.2.6 to 4.2.7. - [Release notes](https://github.com/rvagg/cborg/releases) - [Changelog](https://github.com/rvagg/cborg/blob/master/CHANGELOG.md) - [Commits](https://github.com/rvagg/cborg/compare/v4.2.6...v4.2.7) --- updated-dependencies: - dependency-name: cborg dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f098d67..fee638ff 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "aws4fetch": "^1.0.20", "better-sqlite3": "^11.6.0", "aws4fetch": "^1.0.20", - "cborg": "^4.2.6", + "cborg": "^4.2.7", "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", "dotenv": "^16.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f79ddc09..c775400d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,11 +84,19 @@ importers: specifier: ^11.6.0 version: 11.7.0 cborg: +<<<<<<< HEAD specifier: ^4.2.6 version: 4.2.7 cmd-ts: specifier: ^0.13.0 version: 0.13.0 +||||||| parent of ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) + specifier: ^4.2.6 + version: 4.2.6 +======= + specifier: ^4.2.7 + version: 4.2.7 +>>>>>>> ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -5183,12 +5191,18 @@ snapshots: '@ipld/dag-json@10.2.2': dependencies: +<<<<<<< HEAD cborg: 4.2.7 multiformats: 13.3.1 '@ipld/dag-json@10.2.3': dependencies: cborg: 4.2.7 +||||||| parent of ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) + cborg: 4.2.6 +======= + cborg: 4.2.7 +>>>>>>> ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) multiformats: 13.3.1 '@ipld/dag-pb@4.1.2': From 48cbaeeea2198052579aaaaae2dab718a8e7da6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:24:37 +0000 Subject: [PATCH 19/83] chore(deps-dev): bump prettier from 3.4.1 to 3.4.2 Bumps [prettier](https://github.com/prettier/prettier) from 3.4.1 to 3.4.2. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.4.1...3.4.2) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index fee638ff..d1b94c94 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", "eslint": "^9.16.0", - "prettier": "^3.4.1", + "prettier": "^3.4.2", "semver": "^7.6.3", "std-env": "^3.8.0", "tsup": "^8.3.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c775400d..cec3f6a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,19 +84,11 @@ importers: specifier: ^11.6.0 version: 11.7.0 cborg: -<<<<<<< HEAD - specifier: ^4.2.6 + specifier: ^4.2.7 version: 4.2.7 cmd-ts: specifier: ^0.13.0 version: 0.13.0 -||||||| parent of ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) - specifier: ^4.2.6 - version: 4.2.6 -======= - specifier: ^4.2.7 - version: 4.2.7 ->>>>>>> ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -192,7 +184,7 @@ importers: specifier: ^9.16.0 version: 9.16.0 prettier: - specifier: ^3.4.1 + specifier: ^3.4.2 version: 3.4.2 semver: specifier: ^7.6.3 @@ -5191,18 +5183,12 @@ snapshots: '@ipld/dag-json@10.2.2': dependencies: -<<<<<<< HEAD cborg: 4.2.7 multiformats: 13.3.1 '@ipld/dag-json@10.2.3': dependencies: cborg: 4.2.7 -||||||| parent of ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) - cborg: 4.2.6 -======= - cborg: 4.2.7 ->>>>>>> ebf7197 (chore(deps): bump cborg from 4.2.6 to 4.2.7) multiformats: 13.3.1 '@ipld/dag-pb@4.1.2': From ea2c4047c4a52a54a828ca95e3a6b555b1879128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:42:00 +0000 Subject: [PATCH 20/83] chore(deps-dev): bump vite-tsconfig-paths from 5.1.3 to 5.1.4 Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 5.1.3 to 5.1.4. - [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases) - [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v5.1.3...v5.1.4) --- updated-dependencies: - dependency-name: vite-tsconfig-paths dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d1b94c94..1a657502 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "typescript": "^5.7.2", "typescript-eslint": "^8.17.0", "vite": "^6.0.2", - "vite-tsconfig-paths": "^5.1.3", + "vite-tsconfig-paths": "^5.1.4", "wait-on": "^8.0.1", "vitest": "^2.1.8", "wrangler": "^3.91.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cec3f6a6..f7380e4d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -208,7 +208,7 @@ importers: specifier: ^6.0.2 version: 6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: - specifier: ^5.1.3 + specifier: ^5.1.4 version: 5.1.4(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 From c5e0a967406adf1c1943adb4283c7f3ab7b41130 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:38:47 +0000 Subject: [PATCH 21/83] chore(deps-dev): bump wrangler from 3.91.0 to 3.93.0 Bumps [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) from 3.91.0 to 3.93.0. - [Release notes](https://github.com/cloudflare/workers-sdk/releases) - [Changelog](https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/CHANGELOG.md) - [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@3.93.0/packages/wrangler) --- updated-dependencies: - dependency-name: wrangler dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a657502..780d2c37 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "vite-tsconfig-paths": "^5.1.4", "wait-on": "^8.0.1", "vitest": "^2.1.8", - "wrangler": "^3.91.0", + "wrangler": "^3.93.0", "zx": "^8.2.4" }, "repository": { From aaccdd2e021ec687fe25f1e4411f92c39820d0ba Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 15 Nov 2024 09:20:11 +0100 Subject: [PATCH 22/83] chore: intro of local cloud tests chore: cloud now generated pre-signed-urls chore: fix signature chore: remove env version chore: remove console.log chore: now we have cloud-backend tests chore: the ng redirecting backend chore: everything except subscript --- package.json | 6 +- pnpm-lock.yaml | 2 +- src/cloud/msg-processor.ts | 253 +++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 src/cloud/msg-processor.ts diff --git a/package.json b/package.json index 780d2c37..ad28f0ae 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "xpretest:cloud": "bash ./tests/start-cloud.sh", + "pretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "xposttest:cloud": "docker rm -f cloud", + "posttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -104,12 +104,12 @@ "@aws-sdk/client-s3": "^3.705.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", - "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", "@fireproof/core": "0.19.114", "@fireproof/encrypted-blockstore": "^0.18.0", + "@cloudflare/workers-types": "^4.20241112.0", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7380e4d..78e47d33 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) '@cloudflare/workers-types': - specifier: ^4.20241127.0 + specifier: ^4.20241112.0 version: 4.20241205.0 '@fireproof/core': specifier: 0.19.114 diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts new file mode 100644 index 00000000..cf44f4b2 --- /dev/null +++ b/src/cloud/msg-processor.ts @@ -0,0 +1,253 @@ +import { exception2Result, Logger, Result } from "@adviser/cement"; +import { + buildErrorMsg, + buildResDelMeta, + buildResGestalt, + buildResGetMeta, + buildResPutMeta, + ConnectionKey, + defaultGestalt, + ErrorMsg, + getStoreFromType, + MsgBase, + MsgIsReqDelData, + MsgIsReqDelMeta, + MsgIsReqDelWAL, + MsgIsReqGestalt, + MsgIsReqGetData, + MsgIsReqGetMeta, + MsgIsReqGetWAL, + MsgIsReqPutData, + MsgIsReqPutMeta, + MsgIsReqPutWAL, + MsgIsReqSubscribeMeta, + ReqDelMeta, + ReqGetMeta, + ReqOptRes, + ReqPutMeta, + ReqRes, + ResDelMeta, + ResGetMeta, + ResPutMeta, +} from "./msg-types.js"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; + +export type WithErrorMsg = T | ErrorMsg + +export interface CtxBase { + readonly logger: Logger; +} + + +export interface ReqOptResCtx extends ReqOptRes { + readonly ctx?: C; +} + +export interface ReqResCtx extends ReqRes { + readonly ctx: C; +} + + +export interface MsgProcessor { + dispatch( + decodeFn: () => Promise + ): Promise, O>>; + + // signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise>; + // subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise>; + + // delMeta(req: ReqDelMeta, ctx: CtxBase): Promise>; + // putMeta(req: ReqPutMeta, ctx: CtxBase): Promise>; + // getMeta(req: ReqGetMeta, ctx: CtxBase): Promise>; +} + +export interface RequestOpts { + readonly waitType: string; + readonly timeout?: number; // ms +} +export interface Connection { + readonly ws: WebSocket; + readonly key: ConnectionKey; + request(msg: MsgBase, opts: RequestOpts): Promise>; + onMessage(msgFn: (msg: MsgBase) => void): () => void; + close(): Promise; +} + + +export abstract class MsgProcessorBase implements MsgProcessor { + + readonly logger: Logger; + readonly serverId: string + readonly ctx: O + constructor(logger: Logger, ctx: O, serverId: string) { + this.serverId = serverId + this.logger = logger + this.ctx = ctx + } + + async dispatch( + decodeFn: () => Promise, + reqFn: (msg: Q, ctx: O) => Promise> = async (req) => ({ req }) + ): Promise> { + const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); + if (rReqMsg.isErr()) { + const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); + return { + req: errMsg as unknown as Q, + res: errMsg, + ctx: this.ctx + }; + } + const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, this.ctx); + const ctx = { ...(optCtx || this.ctx) } + switch (true) { + case MsgIsReqGestalt(req): + return { + req, + res: buildResGestalt(req, defaultGestalt(this.serverId, true)) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqGetData(req): + case MsgIsReqGetWAL(req): + return { + req, + res: (await this.signedUrl({ + ...req, params: { + ...req.params, + method: "GET", + store: getStoreFromType(req).store + } + }, ctx)) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqPutData(req): + case MsgIsReqPutWAL(req): + if (req.payload) { + return { + req, + res: buildErrorMsg(this.logger, req, new Error("inband payload not implemented")) as S | ErrorMsg, + ctx, + }; + } + return { + req, + res: (await this.signedUrl({ + ...req, params: { + ...req.params, + method: "PUT", + store: getStoreFromType(req).store + } + }, ctx)) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqDelData(req): + case MsgIsReqDelWAL(req): + return { + req, + res: (await this.signedUrl({ + ...req, params: { + ...req.params, + method: "DELETE", + store: getStoreFromType(req).store + } + }, ctx)) as S | ErrorMsg, + ctx, + }; + + + // case MsgIsReqSignedUrl(req): + // return { + // req, + // res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, + // ctx, + // }; + case MsgIsReqSubscribeMeta(req): + return { + req, + res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqPutMeta(req): + return { + req, + res: (await this.putMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqGetMeta(req): + return { + req, + res: (await this.getMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqDelMeta(req): + return { + req, + res: (await this.delMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + } + return { + req: req, + res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, + ctx, + }; + } + + async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { + // delete meta does nothing in this implementation + // if you delete meta basically you are deleting the whole ledger + return buildResDelMeta(req, { + params: req.params, + status: "unsupported", + connId: ctx.group.connId, + }); + } + + async getMeta(req: ReqGetMeta, ctx: CF): Promise { + const rSignedUrl = await calculatePreSignedUrl( + { + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: { ...req.params, method: "GET" }, + }, + ctx.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + return buildResGetMeta(req, { + signedGetUrl: rSignedUrl.Ok().toString(), + status: "found", + metas: [], + connId: "", + }); + } + + async putMeta(req: ReqPutMeta, ctx: CtxHasGroup): Promise { + const rSignedUrl = await calculatePreSignedUrl( + { + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: { ...req.params, method: "PUT" }, + }, + ctx.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + // roughly time ordered + return buildResPutMeta(req, { + // metaId should be a hash of metas. + metaId: new Date().getTime().toString(), + metas: req.metas, + signedPutUrl: rSignedUrl.Ok().toString(), + connId: ctx.group.connId, + }); + } + +} From 03f4bae164d8bf355d7e93ff7e783904469e5866 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 28 Nov 2024 23:13:40 +0100 Subject: [PATCH 23/83] chore: almost done --- package.json | 11 +++++-- src/cloud/client/gateway.ts | 58 +++++++++++++++++-------------------- src/cloud/cloud.test.ts | 12 ++++++-- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index ad28f0ae..14286ecb 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "pretest:cloud": "bash ./tests/start-cloud.sh", + "xpretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "posttest:cloud": "docker rm -f cloud", + "xposttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -110,6 +110,7 @@ "@fireproof/core": "0.19.114", "@fireproof/encrypted-blockstore": "^0.18.0", "@cloudflare/workers-types": "^4.20241112.0", + "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", @@ -125,6 +126,12 @@ "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", + "@ucanto/client": "^9.0.1", + "@ucanto/core": "^10.0.1", + "@ucanto/interface": "^10.0.1", + "@ucanto/principal": "^9.0.1", + "@ucanto/transport": "^9.1.1", + "@ucanto/validator": "^9.0.2", "assert": "^2.1.0", "better-sqlite3": "^11.7.0", "aws4fetch": "^1.0.20", diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 3ffba1ac..102bc97c 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -66,7 +66,7 @@ export class ConnectionImpl implements Connection { this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); return; } - const msg = rMsg.Ok(); + const msg = rMsg.Ok() const waitFor = this.waitForTid.get(msg.tid); if (waitFor) { if (waitFor.type === msg.type || MsgIsError(msg)) { @@ -470,6 +470,21 @@ export class FireproofCloudGateway implements bs.Gateway { return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); } + async put(uri: URI, body: Uint8Array): Promise> { + const ret = await getStoreTypeGateway(this.sthis, uri).put(uri, body, this.getCloudConnection(uri)); + if (ret.isOk()) { + if (uri.getParam("testMode")) { + trackPuts.add(uri.toString()); + } + } + return ret; + } + + async delete(uri: URI): Promise { + trackPuts.delete(uri.toString()); + return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); + } + async close(uri: URI): Promise { const uriStr = uri.toString(); // CAUTION here is my happen a mutation of subscriptions caused by unsub @@ -511,15 +526,11 @@ export class FireproofCloudGateway implements bs.Gateway { .build() .protocol(params.protocol === "ws" ? "ws" : "wss") .appendRelative("ws") - .cleanParams(); + .cleanParams() + .toString(); - // forces to open a new websocket connection - const connId = uri.getParam("connId"); - if (connId) { - wsUrl.setParam("connId", connId); - } return Result.Ok( - await keyedConnections.get(wsUrl.toString()).once(async (cKey) => { + await keyedConnections.get(wsUrl).once(async (cKey) => { const ws = await newWebSocket(wsUrl); const waitOpen = new Future(); ws.onopen = () => { @@ -571,20 +582,11 @@ export class FireproofCloudGateway implements bs.Gateway { const fn = (subId: string) => (msg: MsgBase) => { if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { // console.log("onMessage", subId, conn.key, msg.metas); - const s = subscriptions.get(subId); - if (!s) { - return; - } - this.notifySubscribers( - this.sthis.txt.encode(JSON.stringify(msg.metas)), - s.map((s) => s.callback) - ); + this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), subscriptions.get(subId)); } }; conn.onMessage(fn(subId)); - return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { - waitType: "resSubscribeMeta", - }); + return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { waitType: "resSubscribeMeta"}); }); if (rResSubscribeMeta.isErr()) { return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); @@ -595,22 +597,14 @@ export class FireproofCloudGateway implements bs.Gateway { callbacks = []; subscriptions.set(subId, callbacks); } - const sid = this.sthis.nextId().str; - const unsub = () => { - const idx = callbacks.findIndex((c) => c.sid === sid); - if (idx !== -1) { - callbacks.splice(idx, 1); - } - if (callbacks.length === 0) { - subscriptions.delete(subId); - } - }; - callbacks.push({ uri: uri.toString(), callback, sid, unsub }); - return Result.Ok(unsub); + callbacks.push(callback); + return Result.Ok(() => { + subscriptions.delete(subId); + }); } async destroy(_uri: URI): Promise> { - await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))); + await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))) return Result.Ok(undefined); } } diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 84f5928c..80df7e00 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -206,7 +206,11 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), + base: wrangler + .build() + .protocol("fireproof:") + .setParam("protocol", "ws") + .setParam("testMode", "true") // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -218,8 +222,12 @@ describe("CloudBackendTest", () => { afterEach(async () => { // Clear the database before each test if (db) { + setInterval(() => console.log("Waiting for db to close"), 1000); + console.log("Closing db"); await db.close(); + console.log("Closed db"); await db.destroy(); + console.log("Destroyed db"); } }); @@ -340,7 +348,7 @@ describe("CloudBackendTest", () => { .setParam( "X-Amz-Signature", sthis.env.get("CF_PRESIGNED_SIGNATURE") || - "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" ) .asObj() ); From 0726f6ca63ef3531b5e836398dd32d2afe1cca9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:13:42 +0000 Subject: [PATCH 24/83] chore(deps): bump @web3-storage/w3up-client from 16.5.1 to 16.5.2 Bumps [@web3-storage/w3up-client](https://github.com/storacha/w3up/tree/HEAD/packages/w3up-client) from 16.5.1 to 16.5.2. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/w3up-client/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/w3up-client-v16.5.2/packages/w3up-client) --- updated-dependencies: - dependency-name: "@web3-storage/w3up-client" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package.json b/package.json index 14286ecb..88ab86de 100644 --- a/package.json +++ b/package.json @@ -126,12 +126,6 @@ "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", - "@ucanto/client": "^9.0.1", - "@ucanto/core": "^10.0.1", - "@ucanto/interface": "^10.0.1", - "@ucanto/principal": "^9.0.1", - "@ucanto/transport": "^9.1.1", - "@ucanto/validator": "^9.0.2", "assert": "^2.1.0", "better-sqlite3": "^11.7.0", "aws4fetch": "^1.0.20", From 849aab0d63d023f6eceb8860a7de9322ca18cb26 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 15 Nov 2024 09:20:11 +0100 Subject: [PATCH 25/83] chore: intro of local cloud tests chore: cloud now generated pre-signed-urls chore: fix signature chore: remove env version chore: remove console.log chore: now we have cloud-backend tests chore: the ng redirecting backend chore: everything except subscript --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 88ab86de..bb8186d7 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "pretest:ucan": "bash ./tests/start-ucan.sh", "pretest:partykit": "bash ./tests/start-partykit.sh", "pretest:netlify": "bash ./tests/start-netlify.sh", - "xpretest:cloud": "bash ./tests/start-cloud.sh", + "pretest:cloud": "bash ./tests/start-cloud.sh", "test": "vitest --run", "posttest-docker": "pnpm run '/^posttest:/'", - "xposttest:cloud": "docker rm -f cloud", + "posttest:cloud": "docker rm -f cloud", "posttest:ucan": "docker rm -f ucan", "posttest:partykit": "docker rm -f partykit", "posttest:netlify": "docker rm -f netlify", @@ -111,6 +111,8 @@ "@fireproof/encrypted-blockstore": "^0.18.0", "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", + "@cloudflare/vitest-pool-workers": "^0.5.30", + "@cloudflare/workers-types": "^4.20241112.0", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", From 895c5c1b0eeeb81a4d4591eb835a914390fd6c2c Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 2 Dec 2024 10:17:58 +0100 Subject: [PATCH 26/83] chore: wip --- package.json | 1 + pnpm-lock.yaml | 2 +- src/cloud/backend/server.ts | 38 ++++++++++++++++++++++++------------- src/cloud/client/gateway.ts | 30 ++++++++++++++++++++++------- src/cloud/cloud.test.ts | 13 +++++-------- 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index bb8186d7..4898d74c 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241112.0", + "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78e47d33..b434ef03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5096,7 +5096,7 @@ snapshots: dependencies: '@ipld/car': 5.3.3 '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.2 + '@ipld/dag-json': 10.2.3 '@ipld/unixfs': 2.2.0 '@peculiar/webcrypto': 1.5.0 '@web3-storage/pail': 0.6.0 diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 1c0eee3a..8606bfe8 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -202,6 +202,10 @@ export class FPMetaGroups extends DurableObject { } } + updateMeta(qs: ReqResCtx): void { + const wsSocks = qs.ctx.dobj.getWebSockets() + const groupWs = wsSocks.map(ws => ({ + ws, group: ws.deserializeAttachment() as FPMetaGroup // updateMeta(qs: ReqResCtx): void { updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { const wsSocks = ctx.dobj.getWebSockets(); @@ -213,6 +217,13 @@ export class FPMetaGroups extends DurableObject { if (group && group.lastMeta) { acc.push(...group.lastMeta.metas); } + return acc + }, [] as CRDTEntry[]) + const now = new Date() + const joinedQS = { + req: { ...qs.req, metas: joinedMeta }, + res: qs.res, + } return acc; }, [] as CRDTEntry[]); const now = new Date(); @@ -228,13 +239,14 @@ export class FPMetaGroups extends DurableObject { } satisfies FPMetaGroup); ws.send( // this is not the best way to do this - JSON.stringify({ - ...joinedUp, - subscriberId: group.group.subscriberId, - connId: group.group.connId, - }) - ); - }); + JSON.stringify( + buildUpdateMetaEvent(joinedQS, { + subscriberId: group.group.subscriberId, + connId: group.group.connId, + }) + ) + ) + }) } } @@ -259,9 +271,9 @@ interface CFMsgProcessorParams { } interface CtxBaseParam { - readonly env: Env; - readonly module?: string; - readonly dobj: DurableObjectState; + readonly env: Env + readonly module?: string + readonly dobj: DurableObjectState } interface CtxBase { @@ -365,7 +377,7 @@ class CFMsgProcessor implements MsgProcessor { params: req.params, status: "unsupported", connId: ctx.group.connId, - }); + }) } async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { @@ -385,8 +397,8 @@ class CFMsgProcessor implements MsgProcessor { signedGetUrl: rSignedUrl.Ok().toString(), status: "found", metas: [], - connId: "", - }); + connId: "" + }) } async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 102bc97c..87eb7feb 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -527,10 +527,14 @@ export class FireproofCloudGateway implements bs.Gateway { .protocol(params.protocol === "ws" ? "ws" : "wss") .appendRelative("ws") .cleanParams() - .toString(); + // forces to open a new websocket connection + const connId = uri.getParam("connId"); + if (connId) { + wsUrl.setParam("connId", connId); + } return Result.Ok( - await keyedConnections.get(wsUrl).once(async (cKey) => { + await keyedConnections.get(wsUrl.toString()).once(async (cKey) => { const ws = await newWebSocket(wsUrl); const waitOpen = new Future(); ws.onopen = () => { @@ -582,7 +586,11 @@ export class FireproofCloudGateway implements bs.Gateway { const fn = (subId: string) => (msg: MsgBase) => { if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { // console.log("onMessage", subId, conn.key, msg.metas); - this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), subscriptions.get(subId)); + const s = subscriptions.get(subId); + if (!s) { + return; + } + this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), s.map((s) => s.callback)); } }; conn.onMessage(fn(subId)); @@ -597,10 +605,18 @@ export class FireproofCloudGateway implements bs.Gateway { callbacks = []; subscriptions.set(subId, callbacks); } - callbacks.push(callback); - return Result.Ok(() => { - subscriptions.delete(subId); - }); + const sid = this.sthis.nextId().str; + const unsub = () => { + const idx = callbacks.findIndex((c) => c.sid === sid); + if (idx !== -1) { + callbacks.splice(idx, 1); + } + if (callbacks.length === 0) { + subscriptions.delete(subId); + } + } + callbacks.push({ uri: uri.toString(), callback, sid, unsub }); + return Result.Ok(unsub); } async destroy(_uri: URI): Promise> { diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 80df7e00..a29ba451 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -6,12 +6,13 @@ import { $ } from "zx"; import fs from "fs/promises"; import * as toml from "smol-toml"; import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; +import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; import { AwsClient } from "aws4fetch"; -import { smokeDB } from "../../tests/helper.js"; -import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.js"; -import { calculatePreSignedUrl } from "./pre-signed-url.js"; -import { newWebSocket } from "./new-websocket.js"; +import { smokeDB } from "../../tests/helper"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway"; +import { calculatePreSignedUrl } from "./pre-signed-url"; +import { newWebSocket } from "./new-websocket"; function testReqSignedUrl(tid = "test") { return { @@ -222,12 +223,8 @@ describe("CloudBackendTest", () => { afterEach(async () => { // Clear the database before each test if (db) { - setInterval(() => console.log("Waiting for db to close"), 1000); - console.log("Closing db"); await db.close(); - console.log("Closed db"); await db.destroy(); - console.log("Destroyed db"); } }); From 4d383263f6ec5f00f14c6201debd745fa9384f89 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 2 Dec 2024 16:55:23 +0100 Subject: [PATCH 27/83] chore: runs the tsc --- package.json | 2 +- pnpm-lock.yaml | 2 +- src/cloud/backend/server.ts | 32 +++++++++++++------------------- src/cloud/client/gateway.ts | 17 +++++++++++------ src/cloud/cloud.test.ts | 8 ++------ 5 files changed, 28 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 4898d74c..f34cf75a 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@cloudflare/workers-types": "^4.20241112.0", "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", - "@cloudflare/workers-types": "^4.20241112.0", + "@cloudflare/workers-types": "^4.20241127.0", "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b434ef03..85109ba0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) '@cloudflare/workers-types': - specifier: ^4.20241112.0 + specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': specifier: 0.19.114 diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 8606bfe8..fc139153 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -202,11 +202,6 @@ export class FPMetaGroups extends DurableObject { } } - updateMeta(qs: ReqResCtx): void { - const wsSocks = qs.ctx.dobj.getWebSockets() - const groupWs = wsSocks.map(ws => ({ - ws, group: ws.deserializeAttachment() as FPMetaGroup - // updateMeta(qs: ReqResCtx): void { updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { const wsSocks = ctx.dobj.getWebSockets(); const groupWs = wsSocks.map((ws) => ({ @@ -239,14 +234,13 @@ export class FPMetaGroups extends DurableObject { } satisfies FPMetaGroup); ws.send( // this is not the best way to do this - JSON.stringify( - buildUpdateMetaEvent(joinedQS, { - subscriberId: group.group.subscriberId, - connId: group.group.connId, - }) - ) - ) - }) + JSON.stringify({ + ...joinedUp, + subscriberId: group.group.subscriberId, + connId: group.group.connId, + }) + ); + }); } } @@ -271,9 +265,9 @@ interface CFMsgProcessorParams { } interface CtxBaseParam { - readonly env: Env - readonly module?: string - readonly dobj: DurableObjectState + readonly env: Env; + readonly module?: string; + readonly dobj: DurableObjectState; } interface CtxBase { @@ -377,7 +371,7 @@ class CFMsgProcessor implements MsgProcessor { params: req.params, status: "unsupported", connId: ctx.group.connId, - }) + }); } async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { @@ -397,8 +391,8 @@ class CFMsgProcessor implements MsgProcessor { signedGetUrl: rSignedUrl.Ok().toString(), status: "found", metas: [], - connId: "" - }) + connId: "", + }); } async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 87eb7feb..1bd14d56 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -66,7 +66,7 @@ export class ConnectionImpl implements Connection { this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); return; } - const msg = rMsg.Ok() + const msg = rMsg.Ok(); const waitFor = this.waitForTid.get(msg.tid); if (waitFor) { if (waitFor.type === msg.type || MsgIsError(msg)) { @@ -526,7 +526,7 @@ export class FireproofCloudGateway implements bs.Gateway { .build() .protocol(params.protocol === "ws" ? "ws" : "wss") .appendRelative("ws") - .cleanParams() + .cleanParams(); // forces to open a new websocket connection const connId = uri.getParam("connId"); @@ -590,11 +590,16 @@ export class FireproofCloudGateway implements bs.Gateway { if (!s) { return; } - this.notifySubscribers(this.sthis.txt.encode(JSON.stringify(msg.metas)), s.map((s) => s.callback)); + this.notifySubscribers( + this.sthis.txt.encode(JSON.stringify(msg.metas)), + s.map((s) => s.callback) + ); } }; conn.onMessage(fn(subId)); - return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { waitType: "resSubscribeMeta"}); + return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { + waitType: "resSubscribeMeta", + }); }); if (rResSubscribeMeta.isErr()) { return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); @@ -614,13 +619,13 @@ export class FireproofCloudGateway implements bs.Gateway { if (callbacks.length === 0) { subscriptions.delete(subId); } - } + }; callbacks.push({ uri: uri.toString(), callback, sid, unsub }); return Result.Ok(unsub); } async destroy(_uri: URI): Promise> { - await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))) + await Promise.all(Array.from(trackPuts).map(async (k) => this.delete(URI.from(k)))); return Result.Ok(undefined); } } diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index a29ba451..563ff45b 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -207,11 +207,7 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler - .build() - .protocol("fireproof:") - .setParam("protocol", "ws") - .setParam("testMode", "true") + base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -345,7 +341,7 @@ describe("CloudBackendTest", () => { .setParam( "X-Amz-Signature", sthis.env.get("CF_PRESIGNED_SIGNATURE") || - "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" ) .asObj() ); From 0b2463dc9794e7edd1c342325db7514cdc2ee917 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 9 Dec 2024 09:01:22 -0500 Subject: [PATCH 28/83] WIP --- package.json | 17 +- pnpm-lock.yaml | 279 ++++++++++---------------------- src/cloud/backend/server.ts | 153 ++++++++++++------ src/cloud/backend/wrangler.toml | 4 +- src/cloud/client/gateway.ts | 90 ++++++++--- src/cloud/cloud.test.ts | 44 +++-- tsconfig.json | 4 +- 7 files changed, 295 insertions(+), 296 deletions(-) diff --git a/package.json b/package.json index f34cf75a..115bfce2 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "wait-on": "^8.0.1", "vitest": "^2.1.8", "wrangler": "^3.93.0", + "ws": "^8.18.0", "zx": "^8.2.4" }, "repository": { @@ -97,23 +98,15 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.40" + "@adviser/cement": "^0.2.41" }, "dependencies": { "@adviser/cement": "^0.2.41", "@aws-sdk/client-s3": "^3.705.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", - "@fireproof/core": "0.19.114", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "0.19.114", - "@fireproof/encrypted-blockstore": "^0.18.0", - "@cloudflare/workers-types": "^4.20241112.0", - "@fireproof/core": "0.19.114", - "@cloudflare/vitest-pool-workers": "^0.5.30", - "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "0.19.114", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", @@ -132,8 +125,6 @@ "assert": "^2.1.0", "better-sqlite3": "^11.7.0", "aws4fetch": "^1.0.20", - "better-sqlite3": "^11.6.0", - "aws4fetch": "^1.0.20", "cborg": "^4.2.7", "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", @@ -152,9 +143,7 @@ "util": "^0.12.5", "valibot": "1.0.0-beta.7", "vitest-pool-workers": "^0.0.1", - "wait-on": "^8.0.1", - "wrangler": "^3.87.0", - "ws": "^8.18.0" + "wait-on": "^8.0.1" }, "exports": { "./ucan": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85109ba0..2974d364 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,11 +21,8 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: 0.19.114 - version: 0.19.114(react@18.3.1)(typescript@5.7.2) - '@fireproof/encrypted-blockstore': - specifier: ^0.18.0 - version: 0.18.0(encoding@0.1.13)(eslint@9.16.0) + specifier: 0.19.116 + version: 0.19.116(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 @@ -140,12 +137,22 @@ importers: wait-on: specifier: ^8.0.1 version: 8.0.1 +<<<<<<< HEAD wrangler: specifier: ^3.87.0 version: 3.93.0(@cloudflare/workers-types@4.20241205.0) ws: specifier: ^8.18.0 version: 8.18.0 +||||||| parent of 9801ea3 (WIP) + wrangler: + specifier: ^3.87.0 + version: 3.92.0(@cloudflare/workers-types@4.20241205.0) + ws: + specifier: ^8.18.0 + version: 8.18.0 +======= +>>>>>>> 9801ea3 (WIP) devDependencies: '@eslint/js': specifier: ^9.16.0 @@ -213,6 +220,12 @@ importers: vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.1) + wrangler: + specifier: ^3.93.0 + version: 3.93.0(@cloudflare/workers-types@4.20241205.0) + ws: + specifier: ^8.18.0 + version: 8.18.0 zx: specifier: ^8.2.4 version: 8.2.4 @@ -1077,14 +1090,11 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.114': - resolution: {integrity: sha512-b/UTsxqazHYkIglllhKIaZl+veik6zuBO8gJGAKBZhxCwAEz5NQOUPDz4Dhk0c5YIeu1ODi9tv2cQ2VFUUDvBg==} + '@fireproof/core@0.19.116': + resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} peerDependencies: react: ^18.3.1 - '@fireproof/encrypted-blockstore@0.18.0': - resolution: {integrity: sha512-W9uUl3LH2o6+TqE4uv9879w9GyRw+YA7aMc4RLfwBr+uZU/12qLPFBCd90YCyIUsYboX4AhghBRLCc2K2yOWiw==} - '@fireproof/vendor@1.0.0': resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} @@ -1142,10 +1152,6 @@ packages: resolution: {integrity: sha512-NnU8HdHKwAoGyrW3S09NMa8aZw0tImLRyR64hoafpLpDpAbA9g1+fb24JsdlugbL4sXUQVwDVA+qK4Ud8V83lA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@ipld/dag-json@10.2.3': - resolution: {integrity: sha512-itacv1j1hvYgLox2B42Msn70QLzcr0MEo5yGIENuw2SM/lQzq9bmBiMky+kDsIrsqqblKTXcHBZnnmK7D4a6ZQ==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@ipld/dag-pb@4.1.2': resolution: {integrity: sha512-BSztO4l3C+ya9HjCaQot26Y4AVsqIKtnn6+23ubc1usucnf6yoTBme18oCCdM6gKBMxuPqju5ye3lh9WEJsdeQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -1236,17 +1242,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@peculiar/asn1-schema@2.3.13': - resolution: {integrity: sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g==} - - '@peculiar/json-schema@1.1.12': - resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} - engines: {node: '>=8.0.0'} - - '@peculiar/webcrypto@1.5.0': - resolution: {integrity: sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==} - engines: {node: '>=10.12.0'} - '@perma/map@1.0.3': resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} @@ -1879,10 +1874,6 @@ packages: as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} - asn1js@3.0.5: - resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} - engines: {node: '>=12.0.0'} - assert-is-function-x@3.1.2: resolution: {integrity: sha512-FiMv0RYR/eMQk2EOMYJKvm+QFQa2AQzjccI9rN4cpvNd6M+UuobnV6m0sqIO5U+Q2LillGwaya16MRGa2Sr6+w==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -1973,13 +1964,6 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - - builtins@5.1.0: - resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==} - bundle-require@5.0.0: resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2245,24 +2229,6 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-compat-utils@0.5.1: - resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=6.0.0' - - eslint-plugin-es-x@7.8.0: - resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '>=8' - - eslint-plugin-n@16.6.2: - resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} - engines: {node: '>=16.0.0'} - peerDependencies: - eslint: '>=7.0.0' - eslint-scope@8.2.0: resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2494,10 +2460,6 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -2582,9 +2544,6 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} - idb@7.1.1: - resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} - idb@8.0.0: resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} @@ -2626,9 +2585,6 @@ packages: interface-store@6.0.2: resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} - ipfs-unixfs-exporter@13.6.1: - resolution: {integrity: sha512-pYPI4oBTWao2//sFzAL0pURyojn79q/u5BuK6L5/nVbVUQVw6DcVP5uB1ySdWlTM2H+0Zlhp9+OL9aJBRIICpg==} - ipfs-unixfs@11.2.0: resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} @@ -2666,10 +2622,6 @@ packages: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -3201,10 +3153,6 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-limit@6.1.0: resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} engines: {node: '>=18'} @@ -3381,13 +3329,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - pvtsutils@1.3.6: - resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} - - pvutils@1.1.3: - resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} - engines: {node: '>=6.0.0'} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -3831,10 +3772,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} @@ -3910,10 +3847,6 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - uuidv7@0.6.3: - resolution: {integrity: sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==} - hasBin: true - valibot@1.0.0-beta.7: resolution: {integrity: sha512-8CsDu3tqyg7quEHMzCOYdQ/d9NlmVQKtd4AlFje6oJpvqo70EIZjSakKIeWltJyNAiUtdtLe0LAk4625gavoeQ==} peerDependencies: @@ -4042,9 +3975,6 @@ packages: engines: {node: '>=12.0.0'} hasBin: true - webcrypto-core@1.8.1: - resolution: {integrity: sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==} - webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -5070,19 +5000,30 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.114(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': dependencies: '@adviser/cement': 0.2.41(typescript@5.7.2) - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 + '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 +<<<<<<< HEAD '@web3-storage/pail': 0.6.0 cborg: 4.2.7 +||||||| parent of 9801ea3 (WIP) + '@web3-storage/pail': 0.6.0 + cborg: 4.2.6 +======= +>>>>>>> 9801ea3 (WIP) charwise: 3.0.1 idb: 8.0.0 +<<<<<<< HEAD ipfs-unixfs-exporter: 13.6.1 memfs: 4.15.0 +||||||| parent of 9801ea3 (WIP) + ipfs-unixfs-exporter: 13.6.1 + memfs: 4.14.1 +======= + memfs: 4.14.1 +>>>>>>> 9801ea3 (WIP) multiformats: 13.3.1 p-limit: 6.1.0 p-map: 7.0.3 @@ -5092,27 +5033,6 @@ snapshots: transitivePeerDependencies: - typescript - '@fireproof/encrypted-blockstore@0.18.0(encoding@0.1.13)(eslint@9.16.0)': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 - '@ipld/unixfs': 2.2.0 - '@peculiar/webcrypto': 1.5.0 - '@web3-storage/pail': 0.6.0 - charwise: 3.0.1 - cross-fetch: 4.0.0(encoding@0.1.13) - eslint-plugin-n: 16.6.2(eslint@9.16.0) - idb: 7.1.1 - ipfs-unixfs-exporter: 13.6.1 - multiformats: 12.1.3 - p-limit: 4.0.0 - prolly-trees: 1.0.4 - uuidv7: 0.6.3 - transitivePeerDependencies: - - encoding - - eslint - '@fireproof/vendor@1.0.0': dependencies: '@ipld/dag-pb': 4.1.2 @@ -5186,11 +5106,20 @@ snapshots: cborg: 4.2.7 multiformats: 13.3.1 +<<<<<<< HEAD '@ipld/dag-json@10.2.3': dependencies: cborg: 4.2.7 multiformats: 13.3.1 +||||||| parent of 9801ea3 (WIP) + '@ipld/dag-json@10.2.3': + dependencies: + cborg: 4.2.6 + multiformats: 13.3.1 + +======= +>>>>>>> 9801ea3 (WIP) '@ipld/dag-pb@4.1.2': dependencies: multiformats: 13.3.1 @@ -5297,6 +5226,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 +<<<<<<< HEAD '@peculiar/asn1-schema@2.3.13': dependencies: asn1js: 3.0.5 @@ -5315,6 +5245,27 @@ snapshots: tslib: 2.8.1 webcrypto-core: 1.8.1 +||||||| parent of 9801ea3 (WIP) + '@peculiar/asn1-schema@2.3.13': + dependencies: + asn1js: 3.0.5 + pvtsutils: 1.3.6 + tslib: 2.7.0 + + '@peculiar/json-schema@1.1.12': + dependencies: + tslib: 2.7.0 + + '@peculiar/webcrypto@1.5.0': + dependencies: + '@peculiar/asn1-schema': 2.3.13 + '@peculiar/json-schema': 1.1.12 + pvtsutils: 1.3.6 + tslib: 2.7.0 + webcrypto-core: 1.8.1 + +======= +>>>>>>> 9801ea3 (WIP) '@perma/map@1.0.3': dependencies: '@multiformats/murmur3': 2.1.8 @@ -6220,12 +6171,22 @@ snapshots: dependencies: printable-characters: 1.0.42 +<<<<<<< HEAD asn1js@3.0.5: dependencies: pvtsutils: 1.3.6 pvutils: 1.1.3 tslib: 2.8.1 +||||||| parent of 9801ea3 (WIP) + asn1js@3.0.5: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.3 + tslib: 2.7.0 + +======= +>>>>>>> 9801ea3 (WIP) assert-is-function-x@3.1.2: dependencies: is-function-x: 4.1.2 @@ -6334,12 +6295,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - builtin-modules@3.3.0: {} - - builtins@5.1.0: - dependencies: - semver: 7.6.3 - bundle-require@5.0.0(esbuild@0.24.0): dependencies: esbuild: 0.24.0 @@ -6726,33 +6681,6 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.16.0): - dependencies: - eslint: 9.16.0 - semver: 7.6.3 - - eslint-plugin-es-x@7.8.0(eslint@9.16.0): - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) - '@eslint-community/regexpp': 4.12.1 - eslint: 9.16.0 - eslint-compat-utils: 0.5.1(eslint@9.16.0) - - eslint-plugin-n@16.6.2(eslint@9.16.0): - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) - builtins: 5.1.0 - eslint: 9.16.0 - eslint-plugin-es-x: 7.8.0(eslint@9.16.0) - get-tsconfig: 4.8.1 - globals: 13.24.0 - ignore: 5.3.2 - is-builtin-module: 3.2.1 - is-core-module: 2.15.1 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 7.6.3 - eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 @@ -7026,10 +6954,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - globals@14.0.0: {} globrex@0.1.2: {} @@ -7101,8 +7025,6 @@ snapshots: idb-keyval@6.2.1: {} - idb@7.1.1: {} - idb@8.0.0: {} ieee754@1.2.1: {} @@ -7147,25 +7069,6 @@ snapshots: interface-store@6.0.2: {} - ipfs-unixfs-exporter@13.6.1: - dependencies: - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 - '@ipld/dag-pb': 4.1.2 - '@multiformats/murmur3': 2.1.8 - hamt-sharding: 3.0.6 - interface-blockstore: 5.3.1 - ipfs-unixfs: 11.2.0 - it-filter: 3.1.1 - it-last: 3.0.6 - it-map: 3.1.1 - it-parallel: 3.0.8 - it-pipe: 3.0.1 - it-pushable: 3.2.3 - multiformats: 13.3.1 - p-queue: 8.0.1 - progress-events: 1.0.1 - ipfs-unixfs@11.2.0: dependencies: protons-runtime: 5.5.0 @@ -7233,10 +7136,6 @@ snapshots: is-buffer@2.0.5: {} - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-callable@1.2.7: {} is-core-module@2.15.1: @@ -7846,10 +7745,6 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: - dependencies: - yocto-queue: 1.1.1 - p-limit@6.1.0: dependencies: yocto-queue: 1.1.1 @@ -8034,12 +7929,6 @@ snapshots: punycode@2.3.1: {} - pvtsutils@1.3.6: - dependencies: - tslib: 2.8.1 - - pvutils@1.1.3: {} - queue-microtask@1.2.3: {} rabin-rs@2.1.0: {} @@ -8516,8 +8405,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-fest@0.20.2: {} - type-fest@2.19.0: {} type-fest@4.26.1: {} @@ -8603,8 +8490,6 @@ snapshots: uuid@9.0.1: {} - uuidv7@0.6.3: {} - valibot@1.0.0-beta.7(typescript@5.7.2): optionalDependencies: typescript: 5.7.2 @@ -8707,6 +8592,7 @@ snapshots: transitivePeerDependencies: - debug +<<<<<<< HEAD webcrypto-core@1.8.1: dependencies: '@peculiar/asn1-schema': 2.3.13 @@ -8715,6 +8601,17 @@ snapshots: pvtsutils: 1.3.6 tslib: 2.8.1 +||||||| parent of 9801ea3 (WIP) + webcrypto-core@1.8.1: + dependencies: + '@peculiar/asn1-schema': 2.3.13 + '@peculiar/json-schema': 1.1.12 + asn1js: 3.0.5 + pvtsutils: 1.3.6 + tslib: 2.7.0 + +======= +>>>>>>> 9801ea3 (WIP) webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index fc139153..07f280cf 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,6 +1,6 @@ // / import type { Env } from "./env.js"; -import { exception2Result, Logger, LoggerImpl, URI } from "@adviser/cement"; +import { exception2Result, JSONFormatter, Logger, LoggerImpl, URI, YAMLFormatter } from "@adviser/cement"; import { buildErrorMsg, buildResDelMeta, @@ -51,21 +51,37 @@ function json(data: T, status = 200) { } function ensureLogger(env: Env, module = "Fireproof"): Logger { - return ( - new LoggerImpl() - .With() - .Module(module) - .SetDebug(env.FP_DEBUG) - // .SetFormatter((env.FP_FORMAT || "json") as LogFormatter) - .SetExposeStack(!!env.FP_STACK || false) - .Logger() - ); + const logger = new LoggerImpl() + .With() + .Module(module) + .SetDebug(env.FP_DEBUG) + .SetExposeStack(!!env.FP_STACK || false) + switch (env.FP_FORMAT) { + case "jsonice": + logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); + break; + case "yaml": + logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); + break; + case "json": + default: + logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); + break; + } + return logger.Logger(); +} + +interface MsgStats { + readonly msgSeq: number; } interface FPMetaGroup { readonly group: ResSubscribeMeta; readonly connId: string; - readonly msgSeq: number; + readonly qs: { + readonly q: Record; + readonly s: Record; + }; readonly lastUsed: Date; readonly lastMeta: ReqPutMeta; } @@ -94,7 +110,7 @@ export class FPMetaGroups extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); - this.logger = ensureLogger(env, "FPMetaGroups"); + this.logger = ensureLogger(env, "FPMetaGroups") // this.ctx.getWebSockets().forEach((webSocket) => { // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { @@ -110,42 +126,58 @@ export class FPMetaGroups extends DurableObject { } return CFMsgProcessor.dispatch( - () => JSON.parse(msg.toString()), - { - env: this.env, - dobj: this.ctx, - }, + () => JSON.parse(msg.toString()), { env: this.env, }, async (req: MsgBase, ictx: CtxBase) => { if (req.auth) { // do ucan magic } - let group = (ws.deserializeAttachment() || { msgSeq: 0 }) as FPMetaGroup; + let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; group = { ...group, - msgSeq: group.msgSeq + 1, + qs: { + ...group.qs, + q: { + ...group.qs.q, + [req.type]: { + msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, + }, + }, + }, connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), lastUsed: new Date(), } satisfies FPMetaGroup; ws.serializeAttachment(group); - const ctx = { ...ictx, group } satisfies CtxWithGroup; + const ctx = { ...ictx, group } satisfies CtxHasGroup; return { req, ctx }; } ).then((qs) => { + let group = { + ...qs.ctx.group, + qs: { + ...qs.ctx.group.qs, + s: { + ...qs.ctx.group.qs.s, + [qs.req.type]: { + msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, + } + }, + } + } satisfies FPMetaGroup; switch (true) { case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): { - const group = { ...qs.ctx.group, lastMeta: qs.req } satisfies FPMetaGroup; + group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup ws.serializeAttachment(group); - this.updateMeta( + (qs.res as {metas: CRDTEntry[]}).metas = this.updateMeta( buildUpdateMetaEvent(qs, { connId: qs.res.connId, subscriberId: "later-overriden", - }), - qs.ctx - ); + })); + this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); break; } case MsgIsResSubscribeMeta(qs): { - const group = { ...qs.ctx.group, group: qs.res } satisfies FPMetaGroup; + group = { ...group, group: qs.res } satisfies FPMetaGroup + // console.log("subscribeMeta group", group); ws.serializeAttachment(group); this.updateMeta( { @@ -157,12 +189,12 @@ export class FPMetaGroups extends DurableObject { metaId: "later-overriden", metas: [], version: qs.res.version, - }, - qs.ctx + } ); break; } } + // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); ws.send(JSON.stringify(qs.res)); }); } @@ -171,7 +203,7 @@ export class FPMetaGroups extends DurableObject { const path = URI.from(req.url).pathname; switch (path) { case "/fp": { - const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env, dobj: this.ctx }); + const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); return json(rq.res, MsgIsQSError(rq) ? 422 : 200); } case "/ws": { @@ -181,7 +213,7 @@ export class FPMetaGroups extends DurableObject { } const { 0: fromClient, 1: toClient } = new WebSocketPair(); this.ctx.acceptWebSocket(toClient); - this.logger.Debug().Msg("fetch"); + // this.logger.Debug().Msg("fetch"); return new Response(null, { status: 101, webSocket: fromClient, @@ -197,7 +229,11 @@ export class FPMetaGroups extends DurableObject { webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { try { ws.close(code, reason); - } finally { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + // ignore + } + finally { this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); } } @@ -227,20 +263,37 @@ export class FPMetaGroups extends DurableObject { metas: joinedMeta, }; groupWs.forEach(({ ws, group }) => { - ws.serializeAttachment({ + // console.log("group->", group); + // group = { + // ...group, + // msgSeq: (group ? group.msgSeq : 0) + 1, + // } + group = { ...group, - msgSeq: group.msgSeq + 1, + qs: { + ...group.qs, + s: { + ...group.qs.s, + [up.type]: { + msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, + } + } + }, lastUsed: now, - } satisfies FPMetaGroup); + } satisfies FPMetaGroup + ws.serializeAttachment(group); + const toSend = { + ...joinedUp, + subscriberId: group.group.subscriberId, + connId: group.group.connId, + }; + this.logger.Debug().Any("event", toSend).Msg("updateMeta"); ws.send( // this is not the best way to do this - JSON.stringify({ - ...joinedUp, - subscriberId: group.group.subscriberId, - connId: group.group.connId, - }) + JSON.stringify(toSend) ); }); + return joinedMeta; } } @@ -259,24 +312,17 @@ interface MsgProcessor { getMeta(req: ReqGetMeta, ctx: CtxBase): Promise; } -interface CFMsgProcessorParams { - readonly env: Env; - readonly logger: Logger; -} - interface CtxBaseParam { readonly env: Env; readonly module?: string; - readonly dobj: DurableObjectState; } interface CtxBase { - readonly dobj: DurableObjectState; readonly env: Env; readonly logger: Logger; } -type CtxWithGroup = CtxBase & { readonly group: FPMetaGroup }; +type CtxHasGroup = CtxBase & { readonly group: FPMetaGroup }; interface ReqOptResCtx extends ReqOptRes { readonly ctx?: C; @@ -301,7 +347,7 @@ class CFMsgProcessor implements MsgProcessor { }).dispatch(decodeFn, reqFn); } - constructor(cfp: CFMsgProcessorParams) { + constructor(cfp: CtxBase) { this.env = cfp.env; this.logger = cfp.logger; } @@ -311,9 +357,10 @@ class CFMsgProcessor implements MsgProcessor { reqFn: (msg: Q, ctx: C) => Promise> = async (req) => ({ req }) ): Promise> { const ictx = { + // dobj: this.env.FP_META_GROUPS, env: this.env, logger: this.logger, - } as CtxBase; + } satisfies CtxBase; const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); if (rReqMsg.isErr()) { const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); @@ -364,7 +411,7 @@ class CFMsgProcessor implements MsgProcessor { }; } - async delMeta(req: ReqDelMeta, ctx: CtxWithGroup): Promise { + async delMeta(req: ReqDelMeta, ctx: CtxHasGroup): Promise { // delete meta does nothing in this implementation // if you delete meta basically you are deleting the whole ledger return buildResDelMeta(req, { @@ -374,7 +421,7 @@ class CFMsgProcessor implements MsgProcessor { }); } - async getMeta(req: ReqGetMeta, _ctx: CtxWithGroup): Promise { + async getMeta(req: ReqGetMeta, _ctx: CtxHasGroup): Promise { const rSignedUrl = await calculatePreSignedUrl( { tid: req.tid, @@ -395,7 +442,7 @@ class CFMsgProcessor implements MsgProcessor { }); } - async putMeta(req: ReqPutMeta, ctx: CtxWithGroup): Promise { + async putMeta(req: ReqPutMeta, ctx: CtxHasGroup): Promise { const rSignedUrl = await calculatePreSignedUrl( { tid: req.tid, @@ -426,7 +473,7 @@ class CFMsgProcessor implements MsgProcessor { return resSignedUrl; } - async subscribeMeta(req: ReqSubscribeMeta, ctx: CtxWithGroup): Promise { + async subscribeMeta(req: ReqSubscribeMeta, ctx: CtxHasGroup): Promise { // console.log("subscribeMeta", req) return buildResSubscriptMeta(req, ctx.group); } diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 622c7d4f..68b2b7ac 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -23,9 +23,11 @@ VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" +FP_DEBUG = "FPMetaGroups" +FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" [env.test.durable_objects] bindings = [ { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, -] \ No newline at end of file +] diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 1bd14d56..5bad2899 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -28,13 +28,14 @@ const VERSION = "v0.1-fp-cloud"; interface RequestOpts { readonly waitType: string; - readonly timeout: number; // ms + readonly timeout?: number; // ms } interface Connection { readonly ws: WebSocket; readonly key: ConnectionKey; - request(msg: MsgBase, opts?: Partial): Promise>; + request(msg: MsgBase, opts: RequestOpts): Promise>; onMessage(msgFn: (msg: MsgBase) => void): () => void; + close(): Promise; } interface WaitForTid { @@ -51,14 +52,17 @@ export class ConnectionImpl implements Connection { readonly msgCallbacks = new Map void>(); readonly sthis: SuperThis; readonly logger: Logger; - constructor(sthis: SuperThis, ws: WebSocket, key: ConnectionKey) { + readonly onClose: () => void; + readonly id: string; + constructor(sthis: SuperThis, ws: WebSocket, key: ConnectionKey, onClose: () => void) { this.ws = ws; this.key = key; this.sthis = sthis; + this.onClose = onClose; this.logger = ensureLogger(sthis, "ConnectionImpl", { this: true, }); - this.logger.Debug().Any("key", key).Msg("constructor"); + this.id = sthis.nextId().str; // this.params = params; ws.onmessage = async (event) => { const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); @@ -69,13 +73,36 @@ export class ConnectionImpl implements Connection { const msg = rMsg.Ok(); const waitFor = this.waitForTid.get(msg.tid); if (waitFor) { - if (waitFor.type === msg.type || MsgIsError(msg)) { + if (MsgIsError(msg)) { this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else if (waitFor.type) { + // what for a specific type + if (waitFor.type === msg.type) { + this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else { + this.msgCallbacks.forEach((cb) => cb(msg)); + } + } else { + // wild-card + this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); } - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); + } else { + this.msgCallbacks.forEach((cb) => cb(msg)); } - }; + } + } + + async close(): Promise { + this.logger.Debug().Msg("close"); + console.log("ConnectionImpl.close", this.id); + this.ws.close(); + this.onClose(); } onMessage(msgFn: (msg: MsgBase) => void): () => void { @@ -86,7 +113,7 @@ export class ConnectionImpl implements Connection { }; } - async request(req: Q, opts: Partial = {}): Promise> { + async request(req: Q, opts: RequestOpts): Promise> { opts = { ...{ timeout: 1000, @@ -291,12 +318,19 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { constructor(sthis: SuperThis) { super(sthis, "MetaGateway"); } + async getConn(uri: URI, conn: Connection): Promise> { - const rsu = this.prepareReqSignedUrl(uri, "GET", conn.key); - if (rsu.isErr()) { - return Result.Err(rsu.Err()); - } - const rRes = await conn.request(buildReqGetMeta(this.sthis, conn.key, rsu.Ok().params), { + const rkey = uri.getParamResult("key"); + if (rkey.isErr()) { + return Result.Err(rkey.Err()); + } + const rsu = buildReqGetMeta(this.sthis, conn.key, { + ...conn.key, + method: "GET", + store: "meta", + key: rkey.Ok(), + }) + const rRes = await conn.request(rsu, { waitType: "resGetMeta", }); if (rRes.isErr()) { @@ -312,22 +346,23 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); } async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { - const bodyRes = await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); + const bodyRes = Result.Ok(body)// await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); if (bodyRes.isErr()) { return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); } - const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; - this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); const rsu = this.prepareReqSignedUrl(uri, "PUT", conn.key); if (rsu.isErr()) { return Result.Err(rsu.Err()); } - const res = await conn.request(buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas), { - waitType: "resPutMeta", - }); + const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; + this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); + const req = buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas) + const res = await conn.request(req, { waitType: "resPutMeta" }); if (res.isErr()) { return Result.Err(res.Err()); } + console.log("putMeta", JSON.stringify({dbMetas, res})); + this.logger.Debug().Any("qs", { req, res}).Msg("putMeta"); this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); return res; } @@ -495,6 +530,12 @@ export class FireproofCloudGateway implements bs.Gateway { } } } + const rConn = await this.getCloudConnection(uri) + if (rConn.isErr()) { + return this.logger.Error().Err(rConn).Msg("Error in getCloudConnection").ResultError(); + } + const conn = rConn.Ok(); + conn.close(); return Result.Ok(undefined); } @@ -502,12 +543,12 @@ export class FireproofCloudGateway implements bs.Gateway { async getCloudConnection(uri: URI): Promise> { const rParams = uri.getParamsResult({ name: 0, - protocol: 0, + protocol: "wss", store: 0, storekey: 0, }); if (rParams.isErr()) { - return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); + return this.logger.Error().Url(uri).Err(rParams).Msg("getCloudConnection:err").ResultError(); } const params = rParams.Ok(); const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); @@ -550,7 +591,9 @@ export class FireproofCloudGateway implements bs.Gateway { this.logger.Debug().Url(wsUrl).Msg("ws close"); }; await waitOpen.asPromise(); - return new ConnectionImpl(this.sthis, ws, connectionKey); + return new ConnectionImpl(this.sthis, ws, connectionKey, () => { + keyedConnections.unget(cKey); + }); }) ); } @@ -590,6 +633,7 @@ export class FireproofCloudGateway implements bs.Gateway { if (!s) { return; } + console.log("msg", JSON.stringify(msg)); this.notifySubscribers( this.sthis.txt.encode(JSON.stringify(msg.metas)), s.map((s) => s.callback) diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 563ff45b..e1c6293a 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -5,14 +5,13 @@ import { Env } from "./backend/env.js"; import { $ } from "zx"; import fs from "fs/promises"; import * as toml from "smol-toml"; -import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; -import { bs, CRDTEntry, Database, fireproof, isNotFoundError } from "@fireproof/core"; +import { bs, CRDTEntry, Database, fireproof, isNotFoundError, rt } from "@fireproof/core"; import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; import { AwsClient } from "aws4fetch"; -import { smokeDB } from "../../tests/helper"; -import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway"; -import { calculatePreSignedUrl } from "./pre-signed-url"; -import { newWebSocket } from "./new-websocket"; +import { smokeDB } from "../../tests/helper.js"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.js"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; +import { newWebSocket } from "./new-websocket.js"; function testReqSignedUrl(tid = "test") { return { @@ -207,7 +206,10 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), + base: wrangler.build() + .protocol("fireproof:") + .setParam("protocol", "ws") + .setParam("testMode", "true"), // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -356,10 +358,13 @@ describe("CloudBackendTest", () => { beforeAll(async () => { gw = new FireproofCloudGateway(sthis); const id = sthis.nextId().str; - uri = BuildURI.from("fireproof://localhost:1968") + uri = BuildURI.from("fireproof://localhost") + .port("" + port) .setParam("store", store) .setParam("name", id) + .setParam("protocol", "ws") .setParam("storekey", id) + .setParam("testMode", "true") .URI(); const last: Uint8Array[] = []; @@ -378,6 +383,9 @@ describe("CloudBackendTest", () => { })) as bs.VoidResult; expect(rOk.isOk()).toBeTruthy(); }); + + const keyBag = await rt.kb.getKeyBag(sthis) + await keyBag.getNamedKey(`@${id}:data@`) }); afterAll(async () => { @@ -400,7 +408,7 @@ describe("CloudBackendTest", () => { const connId = sthis.nextId().str; const uriConnId = uri.build().setParam("connId", connId).URI(); const unsub = (await gw.subscribe?.(uriConnId, (meta: Uint8Array) => - cb(meta, connId) + cb(sthis.txt.decode(meta), connId) )) as bs.UnsubscribeResult; subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }); }) @@ -443,7 +451,8 @@ describe("CloudBackendTest", () => { it(`unsubscribe`, async () => { subscribeCallbacks.forEach((sub) => sub.unsub.Ok()()); - const rOk = await gw.put(uri, crdtEntry()); + const rOk = await gw.put(uri.build().setParam("key", "main").URI(), crdtEntry()); + // console.log(rOk); expect(rOk.isOk()).toBeTruthy(); subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); }); @@ -459,21 +468,27 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } + console.log('getNotFound-pre') // get not found await getNotFound(); // put async function put() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.put(u.build().setParam("key", key).URI(), crdtEntry(u.getParam("connId", "default"))); + + const rOk = await gw.put(u.build().setParam("key", key).URI(), + crdtEntry(`${key}:${u.getParam("connId", "default")}`) + ); expect(rOk.isOk()).toBeTruthy(); } } + // console.log('put', subscribeCallbacks.map(({ cb }) => cb.mock.calls)); subscribeCallbacks.forEach(({ cb, connId }) => { - expect(cb).toHaveBeenCalledTimes(1); - expect(cb).toHaveBeenCalledWith(crdtEntry(connId), connId); + expect(cb).toHaveBeenCalledTimes(subscribeCallbacks.length * 2); + expect(cb).toHaveBeenCalledWith(sthis.txt.decode(crdtEntry(connId)), connId); }); } + // console.log('put-pre') await put(); subscribeCallbacks.forEach(({ cb }) => cb.mockClear()); @@ -487,6 +502,7 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } + console.log('get-pre') await get(); async function del() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { @@ -497,8 +513,10 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } + console.log('del-pre') await del(); // get not found + console.log('getNotFound-pre') await getNotFound(); }); it(`close`, async () => { diff --git a/tsconfig.json b/tsconfig.json index 439ee72a..2fc28ed2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -40,7 +40,9 @@ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ "types": [ "vitest/globals", - "@cloudflare/workers-types" + "@cloudflare/workers-types", + "@cloudflare/workers-types/2023-07-01" + // node_modules/@cloudflare/workers-types/2023-07-01/index.d.ts // "@cloudflare/vitest-pool-workers" ], // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ From 54ff872d3c387917692596d5d0ea25463a43b21b Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Tue, 17 Dec 2024 13:43:55 +0100 Subject: [PATCH 29/83] WIP --- package.json | 8 +- pnpm-lock.yaml | 482 +------------------------ src/cloud/backend/server.ts | 207 ++++------- src/cloud/backend/wrangler.toml | 2 +- src/cloud/client/cli-pre-signed-url.ts | 4 +- src/cloud/client/gateway.ts | 151 +------- src/cloud/cloud.test.ts | 42 ++- src/cloud/msg-request.ts | 372 +++++++++++++++++++ src/cloud/msg-types.ts | 293 +++++++++++++-- src/cloud/pre-signed-url.ts | 1 + src/connector.test.ts | 5 +- src/partykit/partykit-gateway.test.ts | 5 +- 12 files changed, 761 insertions(+), 811 deletions(-) create mode 100644 src/cloud/msg-request.ts diff --git a/package.json b/package.json index 115bfce2..b4433647 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@types/ws": "^8.5.13", "@typescript-eslint/typescript-estree": "^8.17.0", "@web3-storage/access": "^20.1.0", + "cborg": "^4.2.7", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", @@ -83,8 +84,8 @@ "typescript-eslint": "^8.17.0", "vite": "^6.0.2", "vite-tsconfig-paths": "^5.1.4", - "wait-on": "^8.0.1", "vitest": "^2.1.8", + "wait-on": "^8.0.1", "wrangler": "^3.93.0", "ws": "^8.18.0", "zx": "^8.2.4" @@ -103,8 +104,6 @@ "dependencies": { "@adviser/cement": "^0.2.41", "@aws-sdk/client-s3": "^3.705.0", - "@fireproof/core": "0.19.116", - "@fireproof/vendor": "1.0.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", "@hono/node-ws": "^1.0.4", @@ -123,9 +122,8 @@ "@web3-storage/pail": "^0.6.0", "@web3-storage/w3up-client": "^16.5.2", "assert": "^2.1.0", - "better-sqlite3": "^11.7.0", "aws4fetch": "^1.0.20", - "cborg": "^4.2.7", + "better-sqlite3": "^11.7.0", "cmd-ts": "^0.13.0", "cross-fetch": "^4.0.0", "dotenv": "^16.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2974d364..ab79a6d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,12 +20,6 @@ importers: '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 - '@fireproof/core': - specifier: 0.19.116 - version: 0.19.116(react@18.3.1)(typescript@5.7.2) - '@fireproof/vendor': - specifier: 1.0.0 - version: 1.0.0 '@hono/node-ws': specifier: ^1.0.4 version: 1.0.4(@hono/node-server@1.13.7(hono@4.6.13)) @@ -78,11 +72,8 @@ importers: specifier: ^1.0.20 version: 1.0.20 better-sqlite3: - specifier: ^11.6.0 + specifier: ^11.7.0 version: 11.7.0 - cborg: - specifier: ^4.2.7 - version: 4.2.7 cmd-ts: specifier: ^0.13.0 version: 0.13.0 @@ -137,22 +128,6 @@ importers: wait-on: specifier: ^8.0.1 version: 8.0.1 -<<<<<<< HEAD - wrangler: - specifier: ^3.87.0 - version: 3.93.0(@cloudflare/workers-types@4.20241205.0) - ws: - specifier: ^8.18.0 - version: 8.18.0 -||||||| parent of 9801ea3 (WIP) - wrangler: - specifier: ^3.87.0 - version: 3.92.0(@cloudflare/workers-types@4.20241205.0) - ws: - specifier: ^8.18.0 - version: 8.18.0 -======= ->>>>>>> 9801ea3 (WIP) devDependencies: '@eslint/js': specifier: ^9.16.0 @@ -178,6 +153,9 @@ importers: '@typescript-eslint/typescript-estree': specifier: ^8.17.0 version: 8.17.0(typescript@5.7.2) + cborg: + specifier: ^4.2.7 + version: 4.2.7 esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -1090,14 +1068,6 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.116': - resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} - peerDependencies: - react: ^18.3.1 - - '@fireproof/vendor@1.0.0': - resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} - '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1162,9 +1132,6 @@ packages: '@ipld/unixfs@2.2.0': resolution: {integrity: sha512-lDQ2eRhJlbFaBoO3bhOmDVCLmpOnhwtwbilqUgAAhbhoPSmLrnv7gsBuToZjXOdPaEGSL7apkmm6nFrcU6zh4Q==} - '@ipld/unixfs@3.0.0': - resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1190,24 +1157,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@jsonjoy.com/base64@1.1.2': - resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/json-pack@1.1.0': - resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/util@1.5.0': - resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} @@ -1922,10 +1871,6 @@ packages: resolution: {integrity: sha512-rO414jDJf//NDNvIfbChPT+qAXrs5aXIWwq+327qWVn64eKpE+dMsr72o+18tYsSOnF79C6+LO9c756/h6Ghaw==} engines: {node: '>=8.11.4', npm: 6.10.1} - big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - bigint-mod-arith@3.3.1: resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} engines: {node: '>=10.4.0'} @@ -2008,9 +1953,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - charwise@3.0.1: - resolution: {integrity: sha512-RcdumNsM6fJZ5HHbYunqj2bpurVRGsXour3OR+SlLEHFhG6ALm54i6Osnh+OvO7kEoSBzwExpblYFH8zKQiEPw==} - check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -2288,9 +2230,6 @@ packages: resolution: {integrity: sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==} engines: {node: '>=10.13.0'} - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -2473,9 +2412,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - hamt-sharding@3.0.6: - resolution: {integrity: sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==} - has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -2533,10 +2469,6 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - hyperdyperid@1.2.0: - resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} - engines: {node: '>=10.18'} - iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2544,9 +2476,6 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} - idb@8.0.0: - resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2579,15 +2508,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - interface-blockstore@5.3.1: - resolution: {integrity: sha512-nhgrQnz6yUQEqxTFLhlOBurQOy5lWlwCpgFmZ3GTObTVTQS9RZjK/JTozY6ty9uz2lZs7VFJSqwjWAltorJ4Vw==} - - interface-store@6.0.2: - resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} - - ipfs-unixfs@11.2.0: - resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} - ipfs-utils@9.0.14: resolution: {integrity: sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -2791,37 +2711,9 @@ packages: it-all@1.0.6: resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} - it-filter@3.1.1: - resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} - it-glob@1.0.2: resolution: {integrity: sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==} - it-last@3.0.6: - resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} - - it-map@3.1.1: - resolution: {integrity: sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==} - - it-merge@3.0.5: - resolution: {integrity: sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==} - - it-parallel@3.0.8: - resolution: {integrity: sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==} - - it-peekable@3.0.5: - resolution: {integrity: sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==} - - it-pipe@3.0.1: - resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - it-pushable@3.2.3: - resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} - - it-stream-types@2.0.2: - resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} - it-to-stream@1.0.0: resolution: {integrity: sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==} @@ -2838,9 +2730,6 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2894,10 +2783,6 @@ packages: long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - loupe@3.1.2: resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} @@ -2921,10 +2806,6 @@ packages: resolution: {integrity: sha512-mQ2o1VayrZ6Jaz8VyP8B7h/hdn2iAnbUOrQh4rTiwbpULhktpD8IpHGBw8Qo2fmv97Z1P3YzLF3X/DkbIHBQmA==} engines: {node: '>=8.11.4', npm: 6.10.1} - memfs@4.15.0: - resolution: {integrity: sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==} - engines: {node: '>= 4.0.0'} - memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} engines: {node: '>=0.12'} @@ -3066,10 +2947,6 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} - node-sql-parser@3.9.4: - resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} - engines: {node: '>=8'} - node-sqlite3-wasm@0.8.28: resolution: {integrity: sha512-QK5Q0+sgsHNPWiOPFHiBWrfXuJa9UDXi7nUDHhyIlVgoVzltWKDGqoNOERjga+o+ncr5Od7A7kkB4GEmsoUuSA==} @@ -3153,22 +3030,10 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@6.1.0: - resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} - engines: {node: '>=18'} - p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-map@7.0.3: - resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} - engines: {node: '>=18'} - - p-queue@8.0.1: - resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} - engines: {node: '>=18'} - p-retry@5.1.2: resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3177,14 +3042,6 @@ packages: resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} engines: {node: '>=16.17'} - p-retry@6.2.1: - resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} - engines: {node: '>=16.17'} - - p-timeout@6.1.2: - resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} - engines: {node: '>=14.16'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -3302,12 +3159,6 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - progress-events@1.0.1: - resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} - - prolly-trees@1.0.4: - resolution: {integrity: sha512-vtnxfw5wnUHbGa0IIIk9B9DRztJWZw+t9d0s0iGxY/VzEGCg2EMl8GgGU3EhSquFLWapwbGjFTL1ipbezaXR3g==} - property-is-enumerable-x@2.1.2: resolution: {integrity: sha512-lRqJh4yGnwiZUx7x8abWhfucNsImqwxbFoCQzRjfwJflOBenZoFq/YMlWJShdzBmqd9i2/RrrvFW8cBs1+H+3w==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -3316,9 +3167,6 @@ packages: resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} engines: {node: '>=12.0.0'} - protons-runtime@5.5.0: - resolution: {integrity: sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -3342,10 +3190,6 @@ packages: react-native-fetch-api@3.0.0: resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -3502,9 +3346,6 @@ packages: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead - sparse-array@1.3.2: - resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} - split-if-boxed-bug-x@2.1.2: resolution: {integrity: sha512-s16LLvA6VVqayT560dGsP1AXGWAIBsd/1KotRSjoPiaAMPKLbyio9iAsR+b6RGBF22zdlBLGjc4KyU5KCfmzIA==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -3604,12 +3445,6 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thingies@1.21.0: - resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} - engines: {node: '>=10.18'} - peerDependencies: - tslib: ^2 - timers-ext@0.1.8: resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} engines: {node: '>=0.12'} @@ -3686,12 +3521,6 @@ packages: tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - tree-dump@1.0.2: - resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -3801,9 +3630,6 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - uint8-varint@2.0.4: - resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} - uint8arraylist@2.4.8: resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} @@ -4070,10 +3896,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.1.1: - resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} - engines: {node: '>=12.20'} - yoga-wasm-web@0.3.3: resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} @@ -5000,57 +4822,6 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': - dependencies: - '@adviser/cement': 0.2.41(typescript@5.7.2) - '@fireproof/vendor': 1.0.0 - '@ipld/unixfs': 3.0.0 -<<<<<<< HEAD - '@web3-storage/pail': 0.6.0 - cborg: 4.2.7 -||||||| parent of 9801ea3 (WIP) - '@web3-storage/pail': 0.6.0 - cborg: 4.2.6 -======= ->>>>>>> 9801ea3 (WIP) - charwise: 3.0.1 - idb: 8.0.0 -<<<<<<< HEAD - ipfs-unixfs-exporter: 13.6.1 - memfs: 4.15.0 -||||||| parent of 9801ea3 (WIP) - ipfs-unixfs-exporter: 13.6.1 - memfs: 4.14.1 -======= - memfs: 4.14.1 ->>>>>>> 9801ea3 (WIP) - multiformats: 13.3.1 - p-limit: 6.1.0 - p-map: 7.0.3 - p-retry: 6.2.1 - prolly-trees: 1.0.4 - react: 18.3.1 - transitivePeerDependencies: - - typescript - - '@fireproof/vendor@1.0.0': - dependencies: - '@ipld/dag-pb': 4.1.2 - '@multiformats/murmur3': 2.1.8 - hamt-sharding: 3.0.6 - interface-blockstore: 5.3.1 - ipfs-unixfs: 11.2.0 - it-filter: 3.1.1 - it-last: 3.0.6 - it-map: 3.1.1 - it-parallel: 3.0.8 - it-pipe: 3.0.1 - it-pushable: 3.2.3 - multiformats: 13.3.1 - p-queue: 8.0.1 - progress-events: 1.0.1 - varint: 6.0.0 - '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -5106,20 +4877,6 @@ snapshots: cborg: 4.2.7 multiformats: 13.3.1 -<<<<<<< HEAD - '@ipld/dag-json@10.2.3': - dependencies: - cborg: 4.2.7 - multiformats: 13.3.1 - -||||||| parent of 9801ea3 (WIP) - '@ipld/dag-json@10.2.3': - dependencies: - cborg: 4.2.6 - multiformats: 13.3.1 - -======= ->>>>>>> 9801ea3 (WIP) '@ipld/dag-pb@4.1.2': dependencies: multiformats: 13.3.1 @@ -5140,16 +4897,6 @@ snapshots: protobufjs: 7.4.0 rabin-rs: 2.1.0 - '@ipld/unixfs@3.0.0': - dependencies: - '@ipld/dag-pb': 4.1.2 - '@multiformats/murmur3': 2.1.8 - '@perma/map': 1.0.3 - actor: 2.3.1 - multiformats: 13.3.1 - protobufjs: 7.4.0 - rabin-rs: 2.1.0 - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -5181,22 +4928,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/json-pack@1.1.0(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) - '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) - hyperdyperid: 1.2.0 - thingies: 1.21.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/util@1.5.0(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - '@jspm/core@2.1.0': {} '@multiformats/murmur3@2.1.8': @@ -5226,46 +4957,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 -<<<<<<< HEAD - '@peculiar/asn1-schema@2.3.13': - dependencies: - asn1js: 3.0.5 - pvtsutils: 1.3.6 - tslib: 2.8.1 - - '@peculiar/json-schema@1.1.12': - dependencies: - tslib: 2.8.1 - - '@peculiar/webcrypto@1.5.0': - dependencies: - '@peculiar/asn1-schema': 2.3.13 - '@peculiar/json-schema': 1.1.12 - pvtsutils: 1.3.6 - tslib: 2.8.1 - webcrypto-core: 1.8.1 - -||||||| parent of 9801ea3 (WIP) - '@peculiar/asn1-schema@2.3.13': - dependencies: - asn1js: 3.0.5 - pvtsutils: 1.3.6 - tslib: 2.7.0 - - '@peculiar/json-schema@1.1.12': - dependencies: - tslib: 2.7.0 - - '@peculiar/webcrypto@1.5.0': - dependencies: - '@peculiar/asn1-schema': 2.3.13 - '@peculiar/json-schema': 1.1.12 - pvtsutils: 1.3.6 - tslib: 2.7.0 - webcrypto-core: 1.8.1 - -======= ->>>>>>> 9801ea3 (WIP) '@perma/map@1.0.3': dependencies: '@multiformats/murmur3': 2.1.8 @@ -6171,22 +5862,6 @@ snapshots: dependencies: printable-characters: 1.0.42 -<<<<<<< HEAD - asn1js@3.0.5: - dependencies: - pvtsutils: 1.3.6 - pvutils: 1.1.3 - tslib: 2.8.1 - -||||||| parent of 9801ea3 (WIP) - asn1js@3.0.5: - dependencies: - pvtsutils: 1.3.6 - pvutils: 1.1.3 - tslib: 2.7.0 - -======= ->>>>>>> 9801ea3 (WIP) assert-is-function-x@3.1.2: dependencies: is-function-x: 4.1.2 @@ -6250,8 +5925,6 @@ snapshots: object-define-properties-x: 5.1.2 to-boolean-x: 2.1.1 - big-integer@1.6.52: {} - bigint-mod-arith@3.3.1: {} bindings@1.5.0: @@ -6351,8 +6024,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - charwise@3.0.1: {} - check-error@2.1.1: {} chokidar@4.0.1: @@ -6767,8 +6438,6 @@ snapshots: event-target-shim@6.0.2: {} - eventemitter3@5.0.1: {} - events@3.3.0: {} execa@8.0.1: @@ -6964,11 +6633,6 @@ snapshots: graphemer@1.4.0: {} - hamt-sharding@3.0.6: - dependencies: - sparse-array: 1.3.2 - uint8arrays: 5.1.0 - has-bigints@1.0.2: {} has-boxed-string-x@2.1.1: {} @@ -7017,16 +6681,12 @@ snapshots: human-signals@5.0.0: {} - hyperdyperid@1.2.0: {} - iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 idb-keyval@6.2.1: {} - idb@8.0.0: {} - ieee754@1.2.1: {} ignore@5.3.2: {} @@ -7062,18 +6722,6 @@ snapshots: ini@1.3.8: {} - interface-blockstore@5.3.1: - dependencies: - interface-store: 6.0.2 - multiformats: 13.3.1 - - interface-store@6.0.2: {} - - ipfs-unixfs@11.2.0: - dependencies: - protons-runtime: 5.5.0 - uint8arraylist: 2.4.8 - ipfs-utils@9.0.14(encoding@0.1.13): dependencies: any-signal: 3.0.1 @@ -7344,43 +6992,11 @@ snapshots: it-all@1.0.6: {} - it-filter@3.1.1: - dependencies: - it-peekable: 3.0.5 - it-glob@1.0.2: dependencies: '@types/minimatch': 3.0.5 minimatch: 3.1.2 - it-last@3.0.6: {} - - it-map@3.1.1: - dependencies: - it-peekable: 3.0.5 - - it-merge@3.0.5: - dependencies: - it-pushable: 3.2.3 - - it-parallel@3.0.8: - dependencies: - p-defer: 4.0.1 - - it-peekable@3.0.5: {} - - it-pipe@3.0.1: - dependencies: - it-merge: 3.0.5 - it-pushable: 3.2.3 - it-stream-types: 2.0.2 - - it-pushable@3.2.3: - dependencies: - p-defer: 4.0.1 - - it-stream-types@2.0.2: {} - it-to-stream@1.0.0: dependencies: buffer: 6.0.3 @@ -7408,8 +7024,6 @@ snapshots: joycon@3.1.1: {} - js-tokens@4.0.0: {} - js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -7451,10 +7065,6 @@ snapshots: long@5.2.3: {} - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - loupe@3.1.2: {} lru-cache@10.4.3: {} @@ -7480,13 +7090,6 @@ snapshots: is-nan-x: 2.1.1 to-number-x: 3.2.2 - memfs@4.15.0: - dependencies: - '@jsonjoy.com/json-pack': 1.1.0(tslib@2.8.1) - '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) - tree-dump: 1.0.2(tslib@2.8.1) - tslib: 2.8.1 - memoizee@0.4.17: dependencies: d: 1.0.2 @@ -7623,10 +7226,6 @@ snapshots: node-forge@1.3.1: {} - node-sql-parser@3.9.4: - dependencies: - big-integer: 1.6.52 - node-sqlite3-wasm@0.8.28: {} noop-x@1.2.1: {} @@ -7745,21 +7344,10 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@6.1.0: - dependencies: - yocto-queue: 1.1.1 - p-locate@5.0.0: dependencies: p-limit: 3.1.0 - p-map@7.0.3: {} - - p-queue@8.0.1: - dependencies: - eventemitter3: 5.0.1 - p-timeout: 6.1.2 - p-retry@5.1.2: dependencies: '@types/retry': 0.12.1 @@ -7771,14 +7359,6 @@ snapshots: is-network-error: 1.1.0 retry: 0.13.1 - p-retry@6.2.1: - dependencies: - '@types/retry': 0.12.2 - is-network-error: 1.1.0 - retry: 0.13.1 - - p-timeout@6.1.2: {} - package-json-from-dist@1.0.1: {} parent-module@1.0.1: @@ -7886,13 +7466,6 @@ snapshots: process@0.11.10: {} - progress-events@1.0.1: {} - - prolly-trees@1.0.4: - dependencies: - bl: 4.1.0 - node-sql-parser: 3.9.4 - property-is-enumerable-x@2.1.2: dependencies: simple-methodize-x: 1.0.4 @@ -7914,12 +7487,6 @@ snapshots: '@types/node': 22.10.1 long: 5.2.3 - protons-runtime@5.5.0: - dependencies: - uint8-varint: 2.0.4 - uint8arraylist: 2.4.8 - uint8arrays: 5.1.0 - proxy-from-env@1.1.0: {} pump@3.0.2: @@ -7944,10 +7511,6 @@ snapshots: dependencies: p-defer: 3.0.0 - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -8120,8 +7683,6 @@ snapshots: sourcemap-codec@1.4.8: {} - sparse-array@1.3.2: {} - split-if-boxed-bug-x@2.1.2: dependencies: has-boxed-string-x: 2.1.1 @@ -8231,10 +7792,6 @@ snapshots: dependencies: any-promise: 1.3.0 - thingies@1.21.0(tslib@2.8.1): - dependencies: - tslib: 2.8.1 - timers-ext@0.1.8: dependencies: es5-ext: 0.10.64 @@ -8322,10 +7879,6 @@ snapshots: dependencies: punycode: 2.3.1 - tree-dump@1.0.2(tslib@2.8.1): - dependencies: - tslib: 2.8.1 - tree-kill@1.2.2: {} trim-left-x@4.1.2: @@ -8426,11 +7979,6 @@ snapshots: ufo@1.5.4: {} - uint8-varint@2.0.4: - dependencies: - uint8arraylist: 2.4.8 - uint8arrays: 5.1.0 - uint8arraylist@2.4.8: dependencies: uint8arrays: 5.1.0 @@ -8592,26 +8140,6 @@ snapshots: transitivePeerDependencies: - debug -<<<<<<< HEAD - webcrypto-core@1.8.1: - dependencies: - '@peculiar/asn1-schema': 2.3.13 - '@peculiar/json-schema': 1.1.12 - asn1js: 3.0.5 - pvtsutils: 1.3.6 - tslib: 2.8.1 - -||||||| parent of 9801ea3 (WIP) - webcrypto-core@1.8.1: - dependencies: - '@peculiar/asn1-schema': 2.3.13 - '@peculiar/json-schema': 1.1.12 - asn1js: 3.0.5 - pvtsutils: 1.3.6 - tslib: 2.7.0 - -======= ->>>>>>> 9801ea3 (WIP) webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} @@ -8724,8 +8252,6 @@ snapshots: yocto-queue@0.1.0: {} - yocto-queue@1.1.1: {} - yoga-wasm-web@0.3.3: {} youch@3.3.4: diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 07f280cf..ec50708b 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,6 +1,6 @@ // / import type { Env } from "./env.js"; -import { exception2Result, JSONFormatter, Logger, LoggerImpl, URI, YAMLFormatter } from "@adviser/cement"; +import { JSONFormatter, Logger, LoggerImpl, URI, YAMLFormatter } from "@adviser/cement"; import { buildErrorMsg, buildResDelMeta, @@ -12,18 +12,12 @@ import { ErrorMsg, MsgBase, MsgIsQSError, - MsgIsReqDelMeta, - MsgIsReqGetMeta, MsgIsReqPutMeta, - MsgIsReqSignedUrl, - MsgIsReqSubscribeMeta, MsgIsResPutMeta, MsgIsResSubscribeMeta, ReqDelMeta, ReqGetMeta, - ReqOptRes, ReqPutMeta, - ReqRes, ReqSignedUrl, ReqSubscribeMeta, ResDelMeta, @@ -38,6 +32,7 @@ import { CRDTEntry, NotFoundError } from "@fireproof/core"; // import { DurableObject } from "cloudflare:workers"; import { DurableObject } from "cloudflare:workers"; import { calculatePreSignedUrl } from "../pre-signed-url.js"; +import { CtxBase, MsgProcessorBase, ReqOptResCtx, ReqResCtx, WithErrorMsg } from "../msg-processor.js"; const CORS = { "Content-Type": "application/json", @@ -55,7 +50,7 @@ function ensureLogger(env: Env, module = "Fireproof"): Logger { .With() .Module(module) .SetDebug(env.FP_DEBUG) - .SetExposeStack(!!env.FP_STACK || false) + .SetExposeStack(!!env.FP_STACK || false); switch (env.FP_FORMAT) { case "jsonice": logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); @@ -110,7 +105,7 @@ export class FPMetaGroups extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); - this.logger = ensureLogger(env, "FPMetaGroups") + this.logger = ensureLogger(env, "FPMetaGroups"); // this.ctx.getWebSockets().forEach((webSocket) => { // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { @@ -126,8 +121,9 @@ export class FPMetaGroups extends DurableObject { } return CFMsgProcessor.dispatch( - () => JSON.parse(msg.toString()), { env: this.env, }, - async (req: MsgBase, ictx: CtxBase) => { + () => JSON.parse(msg.toString()), + { env: this.env }, + async (req: MsgBase, ictx: CFCtxBase) => { if (req.auth) { // do ucan magic } @@ -147,7 +143,7 @@ export class FPMetaGroups extends DurableObject { lastUsed: new Date(), } satisfies FPMetaGroup; ws.serializeAttachment(group); - const ctx = { ...ictx, group } satisfies CtxHasGroup; + const ctx = { ...ictx, group } satisfies CFCtxWithGroup; return { req, ctx }; } ).then((qs) => { @@ -159,28 +155,31 @@ export class FPMetaGroups extends DurableObject { ...qs.ctx.group.qs.s, [qs.req.type]: { msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, - } + }, }, - } - } satisfies FPMetaGroup; + }, + } satisfies FPMetaGroup; switch (true) { - case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): { - group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup - ws.serializeAttachment(group); - (qs.res as {metas: CRDTEntry[]}).metas = this.updateMeta( - buildUpdateMetaEvent(qs, { - connId: qs.res.connId, - subscriberId: "later-overriden", - })); - this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); + case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): + { + group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; + ws.serializeAttachment(group); + // console.log("putMeta group", group); + (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( + buildUpdateMetaEvent(qs, { + connId: qs.res.connId, + subscriberId: "later-overriden", + }) + ); + this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); + } break; - } - case MsgIsResSubscribeMeta(qs): { - group = { ...group, group: qs.res } satisfies FPMetaGroup - // console.log("subscribeMeta group", group); - ws.serializeAttachment(group); - this.updateMeta( - { + case MsgIsResSubscribeMeta(qs): + { + group = { ...group, group: qs.res } satisfies FPMetaGroup; + // console.log("subscribeMeta group", group); + ws.serializeAttachment(group); + this.updateMeta({ connId: qs.res.connId, subscriberId: "later-overriden", tid: qs.res.tid, @@ -189,10 +188,9 @@ export class FPMetaGroups extends DurableObject { metaId: "later-overriden", metas: [], version: qs.res.version, - } - ); + }); + } break; - } } // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); ws.send(JSON.stringify(qs.res)); @@ -232,8 +230,7 @@ export class FPMetaGroups extends DurableObject { // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { // ignore - } - finally { + } finally { this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); } } @@ -257,6 +254,9 @@ export class FPMetaGroups extends DurableObject { } return acc; }, [] as CRDTEntry[]); + if (joinedMeta.length === 0) { + return []; + } const now = new Date(); const joinedUp = { ...up, @@ -276,11 +276,11 @@ export class FPMetaGroups extends DurableObject { ...group.qs.s, [up.type]: { msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, - } - } + }, + }, }, lastUsed: now, - } satisfies FPMetaGroup + } satisfies FPMetaGroup; ws.serializeAttachment(group); const toSend = { ...joinedUp, @@ -299,119 +299,50 @@ export class FPMetaGroups extends DurableObject { // const app = new Hono<{ Bindings: Env }>(); -interface MsgProcessor { - dispatch( - decodeFn: () => Promise - ): Promise>; - signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise; - subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise; - - delMeta(req: ReqDelMeta, ctx: CtxBase): Promise; - putMeta(req: ReqPutMeta, ctx: CtxBase): Promise; - getMeta(req: ReqGetMeta, ctx: CtxBase): Promise; -} - -interface CtxBaseParam { +interface CFCtxBaseParam { readonly env: Env; readonly module?: string; } -interface CtxBase { +interface CFCtxBase extends CtxBase { readonly env: Env; - readonly logger: Logger; } -type CtxHasGroup = CtxBase & { readonly group: FPMetaGroup }; +type CFCtxWithGroup = CFCtxBase & { readonly group: FPMetaGroup }; -interface ReqOptResCtx extends ReqOptRes { - readonly ctx?: C; -} - -interface ReqResCtx extends ReqRes { - readonly ctx: C; -} +const serverId = "Cloudflare-Fireproof"; -class CFMsgProcessor implements MsgProcessor { - private readonly env: Env; - private readonly logger: Logger; +class CFMsgProcessor extends MsgProcessorBase { - static dispatch( + static dispatch( decodeFn: () => Promise, - ctx: CtxBaseParam, - reqFn?: (msg: Q, ctx: C) => Promise> - ): Promise> { + ctx: CFCtxBaseParam, + reqFn?: (msg: Q, ctx: CFCtxBase) => Promise> + ): Promise, CFCtxWithGroup>> { return new CFMsgProcessor({ env: ctx.env, logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor"), - }).dispatch(decodeFn, reqFn); + }).dispatch(decodeFn, reqFn); } - constructor(cfp: CtxBase) { - this.env = cfp.env; - this.logger = cfp.logger; + constructor(cfp: CFCtxBase) { + super(cfp.logger, cfp, "CFMsgProcessor") } - async dispatch( + async dispatch( decodeFn: () => Promise, - reqFn: (msg: Q, ctx: C) => Promise> = async (req) => ({ req }) - ): Promise> { - const ictx = { - // dobj: this.env.FP_META_GROUPS, - env: this.env, - logger: this.logger, - } satisfies CtxBase; - const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); - if (rReqMsg.isErr()) { - const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); - return { - req: errMsg as unknown as Q, - res: errMsg, - ctx: ictx as C, - }; - } - const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, ictx as C); - const ctx = { ...ictx, ...optCtx } as C & { readonly group: FPMetaGroup }; - switch (true) { - case MsgIsReqSignedUrl(req): - return { - req, - res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqSubscribeMeta(req): - return { - req, - res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqPutMeta(req): - return { - req, - res: (await this.putMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqGetMeta(req): - return { - req, - res: (await this.getMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqDelMeta(req): - return { - req, - res: (await this.delMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - } - return { - req: req, - res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, - ctx, - }; + reqFn: (msg: Q, ctx: CFCtxBase) => Promise> = async (req) => ({ req }) + ): Promise, CFCtxWithGroup>> { + return super.dispatch(decodeFn, async (msg: Q, ctx: CFCtxBase) => { + const { req, res, ctx: optCtx } = await reqFn(msg, ctx) + return { req, res, ctx: optCtx || ctx} + }) } - async delMeta(req: ReqDelMeta, ctx: CtxHasGroup): Promise { + + + async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { // delete meta does nothing in this implementation // if you delete meta basically you are deleting the whole ledger return buildResDelMeta(req, { @@ -421,7 +352,7 @@ class CFMsgProcessor implements MsgProcessor { }); } - async getMeta(req: ReqGetMeta, _ctx: CtxHasGroup): Promise { + async getMeta(req: ReqGetMeta, ctx: CFCtxWithGroup): Promise { const rSignedUrl = await calculatePreSignedUrl( { tid: req.tid, @@ -429,7 +360,7 @@ class CFMsgProcessor implements MsgProcessor { version: req.version, params: { ...req.params, method: "GET" }, }, - this.env + ctx.env ); if (rSignedUrl.isErr()) { return buildErrorMsg(this.logger, req, rSignedUrl.Err()); @@ -442,7 +373,7 @@ class CFMsgProcessor implements MsgProcessor { }); } - async putMeta(req: ReqPutMeta, ctx: CtxHasGroup): Promise { + async putMeta(req: ReqPutMeta, ctx: CFCtxWithGroup): Promise { const rSignedUrl = await calculatePreSignedUrl( { tid: req.tid, @@ -450,13 +381,14 @@ class CFMsgProcessor implements MsgProcessor { version: req.version, params: { ...req.params, method: "PUT" }, }, - this.env + ctx.env ); if (rSignedUrl.isErr()) { return buildErrorMsg(this.logger, req, rSignedUrl.Err()); } // roughly time ordered return buildResPutMeta(req, { + // metaId should be a hash of metas. metaId: new Date().getTime().toString(), metas: req.metas, signedPutUrl: rSignedUrl.Ok().toString(), @@ -464,8 +396,8 @@ class CFMsgProcessor implements MsgProcessor { }); } - async signedUrl(req: ReqSignedUrl, _ctx: CtxBase): Promise { - const rSignedUrl = await calculatePreSignedUrl(req, this.env); + async signedUrl(req: Q, ctx: CFCtxBase): Promise { + const rSignedUrl = await calculatePreSignedUrl(req, ctx.env); if (rSignedUrl.isErr()) { return buildErrorMsg(this.logger, req, rSignedUrl.Err()); } @@ -473,7 +405,8 @@ class CFMsgProcessor implements MsgProcessor { return resSignedUrl; } - async subscribeMeta(req: ReqSubscribeMeta, ctx: CtxHasGroup): Promise { + + async subscribeMeta(req: ReqSubscribeMeta, ctx: CFCtxWithGroup): Promise { // console.log("subscribeMeta", req) return buildResSubscriptMeta(req, ctx.group); } diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 68b2b7ac..9f108778 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -24,7 +24,7 @@ STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" FP_DEBUG = "FPMetaGroups" -FP_FORMAT = "yaml" +#FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" [env.test.durable_objects] diff --git a/src/cloud/client/cli-pre-signed-url.ts b/src/cloud/client/cli-pre-signed-url.ts index b89e7185..8419d631 100644 --- a/src/cloud/client/cli-pre-signed-url.ts +++ b/src/cloud/client/cli-pre-signed-url.ts @@ -2,15 +2,15 @@ // curl $(npx tsx src/cloud/client/cli-pre-signed-url.ts GET) // curl -X PUT --data-binary @/etc/protocols $(npx tsx src/cloud/client/cli-pre-signed-url.ts) import { BuildURI } from "@adviser/cement"; -import { mockSuperThis } from "../../../node_modules/@fireproof/core/tests/helpers.js"; import { AwsClient } from "aws4fetch"; import dotenv from "dotenv"; import { command, run, option, oneOf, string } from "cmd-ts"; +import { ensureSuperThis } from "@fireproof/core"; // import * as t from 'io-ts'; (async () => { dotenv.config(); - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); const cmd = command({ name: "cli-pre-signed-url", description: "sign a url for cloud storage", diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 5bad2899..e6e1e3a5 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -2,14 +2,12 @@ import { Result, URI, KeyedResolvOnce, exception2Result, Future } from "@adviser/cement"; import { bs, CRDTEntry, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; import { - buildErrorMsg, buildReqDelMeta, buildReqGetMeta, buildReqPutMeta, - buildReqSignedUrl, buildReqSubscriptMeta, + Connection, ConnectionKey, - FPStoreTypes, HttpMethods, MsgBase, MsgIsError, @@ -26,135 +24,6 @@ import { to_uint8 } from "../../coerce-binary.js"; const VERSION = "v0.1-fp-cloud"; -interface RequestOpts { - readonly waitType: string; - readonly timeout?: number; // ms -} -interface Connection { - readonly ws: WebSocket; - readonly key: ConnectionKey; - request(msg: MsgBase, opts: RequestOpts): Promise>; - onMessage(msgFn: (msg: MsgBase) => void): () => void; - close(): Promise; -} - -interface WaitForTid { - readonly tid: string; - readonly future: Future; - // undefined match all - readonly type?: string; -} - -export class ConnectionImpl implements Connection { - readonly ws: WebSocket; - readonly key: ConnectionKey; - readonly waitForTid = new Map(); - readonly msgCallbacks = new Map void>(); - readonly sthis: SuperThis; - readonly logger: Logger; - readonly onClose: () => void; - readonly id: string; - constructor(sthis: SuperThis, ws: WebSocket, key: ConnectionKey, onClose: () => void) { - this.ws = ws; - this.key = key; - this.sthis = sthis; - this.onClose = onClose; - this.logger = ensureLogger(sthis, "ConnectionImpl", { - this: true, - }); - this.id = sthis.nextId().str; - // this.params = params; - ws.onmessage = async (event) => { - const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); - if (rMsg.isErr()) { - this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); - return; - } - const msg = rMsg.Ok(); - const waitFor = this.waitForTid.get(msg.tid); - if (waitFor) { - if (MsgIsError(msg)) { - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } else if (waitFor.type) { - // what for a specific type - if (waitFor.type === msg.type) { - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } else { - this.msgCallbacks.forEach((cb) => cb(msg)); - } - } else { - // wild-card - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } - } else { - this.msgCallbacks.forEach((cb) => cb(msg)); - } - } - } - - async close(): Promise { - this.logger.Debug().Msg("close"); - console.log("ConnectionImpl.close", this.id); - this.ws.close(); - this.onClose(); - } - - onMessage(msgFn: (msg: MsgBase) => void): () => void { - const fnId = this.sthis.nextId().str; - this.msgCallbacks.set(fnId, msgFn); - return () => { - this.msgCallbacks.delete(fnId); - }; - } - - async request(req: Q, opts: RequestOpts): Promise> { - opts = { - ...{ - timeout: 1000, - }, - ...opts, - }; - const future = new Future(); - this.waitForTid.set(req.tid, { - tid: req.tid, - future, - type: opts.waitType, - }); - const start = Date.now(); - const logger = ensureLogger(this.sthis, "ConnectionImpl.request") - .With() - .Str("tid", req.tid) - .Uint64("timeout", opts.timeout) - .Ref("start", () => new Date().getTime() - start) - .Any("req", req) - .Logger(); - this.ws.send(JSON.stringify(req)); - const clean = setTimeout(() => { - this.waitForTid.delete(req.tid); - future.reject(new Error("Timeout")); - }, opts.timeout); - // add timeout handling - logger.Debug().Msg("request-enter"); - return future - .asPromise() - .finally(() => clearTimeout(clean)) - .then((res) => { - logger.Debug().Any("res", res).Msg("request-ok"); - return Result.Ok(res as S); - }) - .catch((err) => { - logger.Error().Err(err).Msg("request-error"); - return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); - }); - } -} - export interface StoreTypeGateway { get(uri: URI, conn: Promise>): Promise>; put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; @@ -210,8 +79,8 @@ abstract class BaseGateway { return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); } const { store, key } = rParams.Ok(); - return Result.Ok( - buildReqSignedUrl(this.sthis, { + return Result.Ok({ + buildReqSignedUrl({ // auth: await getUcanAuthFromUri(uri), params: { ...cKey, @@ -329,7 +198,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { method: "GET", store: "meta", key: rkey.Ok(), - }) + }); const rRes = await conn.request(rsu, { waitType: "resGetMeta", }); @@ -346,7 +215,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); } async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { - const bodyRes = Result.Ok(body)// await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); + const bodyRes = Result.Ok(body); // await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); if (bodyRes.isErr()) { return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); } @@ -356,13 +225,13 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { } const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); - const req = buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas) + const req = buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas); const res = await conn.request(req, { waitType: "resPutMeta" }); if (res.isErr()) { return Result.Err(res.Err()); } - console.log("putMeta", JSON.stringify({dbMetas, res})); - this.logger.Debug().Any("qs", { req, res}).Msg("putMeta"); + // console.log("putMeta", JSON.stringify({dbMetas, res})); + this.logger.Debug().Any("qs", { req, res: res.Ok() }).Msg("putMeta"); this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); return res; } @@ -530,12 +399,12 @@ export class FireproofCloudGateway implements bs.Gateway { } } } - const rConn = await this.getCloudConnection(uri) + const rConn = await this.getCloudConnection(uri); if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in getCloudConnection").ResultError(); } const conn = rConn.Ok(); - conn.close(); + await conn.close(); return Result.Ok(undefined); } diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index e1c6293a..629466fe 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -5,8 +5,7 @@ import { Env } from "./backend/env.js"; import { $ } from "zx"; import fs from "fs/promises"; import * as toml from "smol-toml"; -import { bs, CRDTEntry, Database, fireproof, isNotFoundError, rt } from "@fireproof/core"; -import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; +import { bs, CRDTEntry, Database, ensureSuperThis, fireproof, isNotFoundError, rt } from "@fireproof/core"; import { AwsClient } from "aws4fetch"; import { smokeDB } from "../../tests/helper.js"; import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.js"; @@ -47,7 +46,7 @@ async function testResSignedUrl(env: Env, tid?: string, amzDate?: string): Promi } describe("CloudBackendTest", () => { - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); let env: Env; let pid: number; const port = +(process.env.FP_WRANGLER_PORT || 0) || ~~(1024 + Math.random() * (0x10000 - 1024)); @@ -206,10 +205,7 @@ describe("CloudBackendTest", () => { const config = { store: { stores: { - base: wrangler.build() - .protocol("fireproof:") - .setParam("protocol", "ws") - .setParam("testMode", "true"), + base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", }, }, @@ -316,7 +312,7 @@ describe("CloudBackendTest", () => { }); describe("AwsClient R2", () => { it("make presigned url", async () => { - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); const a4f = new AwsClient({ accessKeyId: sthis.env.get("CF_ACCESS_KEY_ID") || "accessKeyId", secretAccessKey: sthis.env.get("CF_SECRET_ACCESS_KEY") || "secretAccessKey", @@ -353,7 +349,7 @@ describe("CloudBackendTest", () => { describe(`store=meta`, () => { const store = "meta"; let gw: bs.Gateway; - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); let uri: URI; beforeAll(async () => { gw = new FireproofCloudGateway(sthis); @@ -384,8 +380,8 @@ describe("CloudBackendTest", () => { expect(rOk.isOk()).toBeTruthy(); }); - const keyBag = await rt.kb.getKeyBag(sthis) - await keyBag.getNamedKey(`@${id}:data@`) + const keyBag = await rt.kb.getKeyBag(sthis); + await keyBag.getNamedKey(`@${id}:data@`); }); afterAll(async () => { @@ -401,7 +397,7 @@ describe("CloudBackendTest", () => { }[] = []; beforeEach(async () => { await Promise.all( - Array(4) + Array(1) .fill(null) .map(async () => { const cb = vitest.fn(); @@ -468,15 +464,19 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } - console.log('getNotFound-pre') + console.log("getNotFound-pre"); + + subscribeCallbacks.forEach(({ cb }) => { + expect(cb).toHaveBeenCalledTimes(0); + }); // get not found await getNotFound(); // put async function put() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { for (const key of ["KEY1", "KEY2"]) { - - const rOk = await gw.put(u.build().setParam("key", key).URI(), + const rOk = await gw.put( + u.build().setParam("key", key).URI(), crdtEntry(`${key}:${u.getParam("connId", "default")}`) ); expect(rOk.isOk()).toBeTruthy(); @@ -484,8 +484,10 @@ describe("CloudBackendTest", () => { } // console.log('put', subscribeCallbacks.map(({ cb }) => cb.mock.calls)); subscribeCallbacks.forEach(({ cb, connId }) => { - expect(cb).toHaveBeenCalledTimes(subscribeCallbacks.length * 2); - expect(cb).toHaveBeenCalledWith(sthis.txt.decode(crdtEntry(connId)), connId); + // expect(cb).toHaveBeenCalledTimes(subscribeCallbacks.length * 2); + for (const key of ["KEY1", "KEY2"]) { + expect(cb).toHaveBeenCalledWith(sthis.txt.decode(crdtEntry(`${key}:${connId}`)), connId); + } }); } // console.log('put-pre') @@ -502,7 +504,7 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } - console.log('get-pre') + console.log("get-pre"); await get(); async function del() { for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { @@ -513,10 +515,10 @@ describe("CloudBackendTest", () => { } subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); } - console.log('del-pre') + console.log("del-pre"); await del(); // get not found - console.log('getNotFound-pre') + console.log("getNotFound-pre"); await getNotFound(); }); it(`close`, async () => { diff --git a/src/cloud/msg-request.ts b/src/cloud/msg-request.ts new file mode 100644 index 00000000..09009312 --- /dev/null +++ b/src/cloud/msg-request.ts @@ -0,0 +1,372 @@ +import { Future, Logger, exception2Result, Result, CoerceURI, KeyedResolvOnce, URI } from "@adviser/cement"; +import { SuperThis, ensureLogger } from "@fireproof/core"; +import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; +import { MsgBase, AuthType, Gestalt, defaultGestalt, ResGestalt, ReqGestalt, buildErrorMsg } from "./msg-types.js"; + +import * as json from 'multiformats/codecs/json'; +import * as cborg from '@fireproof/vendor/cborg'; + +export interface EnDeCoder { + encode(node: T): Uint8Array; + decode(data: Uint8Array): T; +} + +export interface WaitForTid { + readonly tid: string; + readonly future: Future; + // undefined match all + readonly type?: string; +} + +export interface Connection { + // readonly ws: WebSocket; + // readonly params: ConnectionKey; + request(req: Q, opts: RequestOpts): Promise>> + +} + +export interface FetchGestaltParams { + readonly auth?: AuthType; + readonly sthis: SuperThis; + readonly gestaltURL: URI; + readonly uniqServerId?: string; + readonly getConn: () => Promise; +} + +export interface HttpConnectionParams { + readonly gestaltURL: CoerceURI; + readonly fetchConnection?: Connection; + readonly ende?: EnDeCoder; + readonly uniqServerId?: string; +} + +export interface GestaltItem { + readonly ende: EnDeCoder; + readonly mime: string; + readonly auth?: AuthType; + readonly params: Gestalt; +} + +export type RequestFN = (req: Q, opts: RequestOpts) => Promise> + +const serverId = "FP-Universal-Client" + +export function encoded(logger: Logger, g: "JSON" | "CBOR") { + let ende: EnDeCoder + let mime: string + switch (g) { + case "JSON": + ende = json + mime = "application/json" + break; + case "CBOR": + ende = cborg + mime = "application/cbor" + break; + default: + throw logger.Error().Str("typ", g).Msg(`Unknown encoding: ${g}`).AsError() + } + return { ende, mime } +} + +const getGestalts = new KeyedResolvOnce(); + +async function fetchGestalt(fgp: FetchGestaltParams): Promise { + return getGestalts.get(fgp.gestaltURL.toString()).once(async () => { + const conn = await fgp.getConn(); + const rGestalt = await conn.request({ + type: "reqGestalt", + tid: fgp.sthis.nextId().str, + version: serverId, + gestalt: defaultGestalt(fgp.uniqServerId || serverId, false), + }, { waitType: "resGestalt" }); + if (rGestalt.isErr()) { + throw rGestalt.Err(); + } + const gestalt = rGestalt.Ok() as ResGestalt; + const ende = encoded(fgp.sthis.logger, gestalt.params.encodings[0]) + return { + ende: ende.ende, + mime: ende.mime, + auth: gestalt.auth, + params: gestalt.params + } + }) +} + +function selectRandom(arr: T[]): T { + return arr[Math.floor(Math.random() * arr.length)]; +} + +export class HttpConnection implements Connection { + readonly sthis: SuperThis; + readonly logger: Logger; + readonly gestaltItem: GestaltItem; + readonly mec: MsgErrorClose; + constructor(sthis: SuperThis, gi: GestaltItem, mec: MsgErrorClose = {}) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "HttpConnection"); + this.gestaltItem = gi; + this.mec = mec; + } + + async request(req: Q, _opts: RequestOpts): Promise>> { + const headers = new Headers(); + headers.append("Content-Type", this.gestaltItem.mime); + headers.append("Accept", this.gestaltItem.mime); + const rReqBody = exception2Result(() => this.gestaltItem.ende.encode(req)); + if (rReqBody.isErr()) { + return this.toOnMessage(buildErrorMsg(this.logger, req, + this.logger.Error().Err(rReqBody.Err()).Msg("encode error").AsError() + )); + } + headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); + const url = selectRandom(this.gestaltItem.params.httpEndpoints) + const rRes = await exception2Result(() => fetch(url, { + method: "PUT", + headers, + body: rReqBody.Ok(), + })); + if (rRes.isErr()) { + return this.toOnMessage(buildErrorMsg(this.logger, req, + this.logger.Error().Err(rRes.Ok()).Msg("fetch error").AsError() + )); + } + const res = rRes.Ok(); + if (!res.ok) { + return this.toOnMessage( + buildErrorMsg(this.logger, req, this.logger.Error() + .Url(url) + .Str("status", res.status.toString()) + .Str("statusText", res.statusText).Msg("HTTP Error").AsError())); + } + const data = new Uint8Array(await res.arrayBuffer()); + const ret = await exception2Result(async () => this.gestaltItem.ende.decode(data) as S); + if (ret.isErr()) { + return this.toOnMessage(buildErrorMsg(this.logger, req, + this.logger.Error().Err(ret.Err()).Msg("decode error").AsError() + )); + } + return this.toOnMessage(ret.Ok()) + } + + toOnMessage(msg: WithErrorMsg): Result> { + this.mec.msgFn?.(msg as unknown as MessageEvent); + return Result.Ok(msg); + } + +} + +export interface MsgErrorClose { + readonly msgFn: (msg: MessageEvent) => void; + readonly errFn: (err: Event) => void; + readonly closeFn: () => void; + readonly openFn: () => void; +} + +export class WSAttachConnection implements Connection { + readonly ws: WebSocket; + // readonly key: ConnectionKey; + readonly sthis: SuperThis; + readonly logger: Logger; + + // readonly errFns = new Map void>(); + // readonly closeFns = new Map void>(); + // readonly msgFns = new Map void>(); + + readonly waitForTid: WSAttachable["waitForTid"]; + constructor(sthis: SuperThis, ws: WebSocket, waitForTid: WSAttachable["waitForTid"], mec: MsgErrorClose) { + this.ws = ws; + // this.key = key; + this.sthis = sthis; + // this.onClose = onClose; + this.logger = ensureLogger(sthis, "WSAttachConnection", { + this: true, + }); + this.waitForTid = waitForTid; + ws.onmessage = mec.msgFn + ws.onopen = mec.openFn; + ws.onerror = mec.errFn + ws.onclose = mec.closeFn + } + + async close(): Promise { + this.logger.Debug().Msg("close"); + this.ws.close(); + } + + async request(req: Q, opts: RequestOpts): Promise> { + opts = { + ...{ + timeout: 1000, + }, + ...opts, + }; + const future = new Future(); + this.waitForTid.set(req.tid, { + tid: req.tid, + future, + type: opts.waitType, + }); + const start = Date.now(); + const logger = ensureLogger(this.sthis, "ConnectionImpl.request") + .With() + .Str("tid", req.tid) + .Uint64("timeout", opts.timeout) + .Ref("start", () => new Date().getTime() - start) + .Any("req", req) + .Logger(); + this.ws.send(JSON.stringify(req)); + const clean = setTimeout(() => { + this.waitForTid.delete(req.tid); + future.reject(new Error("Timeout")); + }, opts.timeout); + // add timeout handling + logger.Debug().Msg("request-enter"); + return future + .asPromise() + .finally(() => clearTimeout(clean)) + .then((res) => { + logger.Debug().Any("res", res).Msg("request-ok"); + return Result.Ok(res as S); + }) + .catch((err) => { + logger.Error().Err(err).Msg("request-error"); + return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); + }); + } +} + + + +export interface GestaltParams { + readonly auth?: AuthType; + readonly sthis: SuperThis; + readonly gestaltURL: URI; + readonly uniqServerId?: string; +} + +const keyedHttpConnection = new KeyedResolvOnce(); +function httpFactory(sthis: SuperThis, uniqServerId: string, auth?: AuthType): (() => Promise) { + return () => keyedHttpConnection.get(uniqServerId || serverId).once(async () => { + return new HttpConnection(sthis, { + ende: json, + mime: "application/json", + auth: auth, + params: defaultGestalt(uniqServerId || serverId, false), + }) + }) +} + +const keyedWSConnection = new KeyedResolvOnce(); + +export interface Attachable { + attach(t: T): Promise +} + +export class WSAttachable implements Attachable { + readonly gestalt: GestaltItem + readonly sthis: SuperThis + readonly waitForTid = new Map(); + constructor(sthis: SuperThis, gestalt: GestaltItem) { + this.gestalt = gestalt + this.sthis = sthis + } + attach(t: WebSocket): Promise { + return keyedWSConnection.get(this.gestalt.params.id).once(async () => { + const c = new WSAttachConnection(this.sthis, t, this.waitForTid, { + openFn: () => this.open(t), + errFn: (err) => this.error(t, err), + msgFn: (msg) => this.msg(t, msg), + closeFn: () => this.close(t) + }) + return c + }) + } + + open(ws: WebSocket) { + this.sthis.logger.Info().Msg("open") + } + + error(ws: WebSocket, err: Event) { + this.sthis.logger.Error().Msg("error") + + } + msg(ws: WebSocket, msg: MessageEvent) { + this.sthis.logger.Info().Any("msg", msg).Msg("msg") + ws.onmessage = async (event) => { + const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); + if (rMsg.isErr()) { + this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); + return; + } + const msg = rMsg.Ok(); + const waitFor = this.waitForTid.get(msg.tid); + if (waitFor) { + if (MsgIsError(msg)) { + this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else if (waitFor.type) { + // what for a specific type + if (waitFor.type === msg.type) { + this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else { + this.msgCallbacks.forEach((cb) => cb(msg)); + } + } else { + // wild-card + this.msgCallbacks.forEach((cb) => cb(msg)); + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } + } else { + this.msgCallbacks.forEach((cb) => cb(msg)); + } + }; + } + + close(ws: WebSocket) { + this.sthis.logger.Info().Msg("close") + } + + // this.params = params; + +} + +export async function getAttachable(p: FetchGestaltParams): Promise> { + const g = await fetchGestalt({ + gestaltURL: p.gestaltURL, + sthis: p.sthis, + getConn: httpFactory(p.sthis, p.uniqServerId || serverId, p.auth), + }) + if (g.params.wsEndpoints.length > 0) { + return new WSAttachable(p.sthis, g) as Attachable + } + return { + attach: async () => new HttpConnection(p.sthis, g) + } +} + + + +// export class ConnectionImpl implements Connection { +// readonly sthis: SuperThis; +// constructor(sthis: SuperThis) { +// this.sthis = sthis; +// } + + + +// async request(req: Q, opts: RequestOpts): Promise> { + +// } + + +// } + +// export class ConnectionImpl implements Connection { + +// } diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index e74880c2..434d6388 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -27,7 +27,6 @@ export interface MsgBase { readonly version: string; readonly auth?: AuthType; } - export interface ErrorMsg extends MsgBase { readonly type: "error"; readonly message: string; @@ -42,6 +41,166 @@ export function MsgIsQSError(rq: ReqRes): rq is ReqRes { readonly req: Q; readonly res: S; @@ -93,12 +247,9 @@ const VERSION = "FP-MSG-1.0"; /* Signed URL */ -export function buildReqSignedUrl(sthis: NextId, req: ReqSignedUrlParam): ReqSignedUrl { +export function buildReqSignedUrl(req: ReqSignedUrlParam): ReqSignedUrlParam { return { - tid: sthis.nextId().str, - type: "reqSignedUrl", - version: VERSION, - ...req, + tid: req.tid, params: { // protocol: "wss", ...req.params, @@ -106,14 +257,31 @@ export function buildReqSignedUrl(sthis: NextId, req: ReqSignedUrlParam): ReqSig }; } -export function MsgIsReqSignedUrl(msg: MsgBase): msg is ReqSignedUrl { - return msg.type === "reqSignedUrl"; +// export function MsgIsReqSignedUrl(msg: MsgBase): msg is ReqSignedUrl { +// return msg.type === "reqSignedUrl"; +// } + +interface StoreAndType { + readonly store: FPStoreTypes; + readonly resType: string; +} +const reqToRes: Record = { + reqGetData: { store: "data", resType: "resGetData" }, + reqPutData: { store: "data", resType: "resPutData" }, + reqDelData: { store: "data", resType: "resDelData" }, + reqGetWAL: { store: "wal", resType: "resGetWAL" }, + reqPutWAL: { store: "wal", resType: "resPutWAL" }, + reqDelWAL: { store: "wal", resType: "resDelWAL" }, +} + +export function getStoreFromType(req: MsgBase): StoreAndType { + return reqToRes[req.type] || (() => { throw new Error(`unknown req.type=${req.type}`) })(); } export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { return { tid: req.tid, - type: "resSignedUrl", + type: getStoreFromType(req).resType, version: VERSION, params: req.params, signedUrl, @@ -132,17 +300,12 @@ export function buildErrorMsg(logger: Logger, base: Partial, error: Err } export interface ReqSignedUrl extends MsgBase { - readonly type: "reqSignedUrl"; - readonly params: SignedUrlParam; -} - -export interface ReqSignedUrl extends MsgBase { - readonly type: "reqSignedUrl"; + // readonly type: "reqSignedUrl"; readonly params: SignedUrlParam; } export interface ResSignedUrl extends MsgBase { - readonly type: "resSignedUrl"; + // readonly type: "resSignedUrl"; readonly params: SignedUrlParam; readonly signedUrl: string; } @@ -264,6 +427,17 @@ export interface ConnSubId { readonly subscriberId: string; } +/** + * This is used for non WebSocket server implementations + * to retrieve the meta data. It should be done by polling + * and might implement long polling. + * It will answer with a UpdateMetaEvent. + */ +export interface ReqUpdateMeta extends MsgBase, ConnSubId { + readonly type: "reqUpdateMeta"; + readonly key: ConnectionKey; +} + export interface UpdateMetaEvent extends MsgBase, ConnSubId { readonly type: "updateMeta"; readonly key: ConnectionKey; @@ -398,3 +572,80 @@ export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDe export function MsgIsResDelMeta(qs: ReqRes): qs is ReqRes { return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; } + +export interface ReqGetData extends ReqSignedUrl { + readonly type: "reqGetData"; +} + +export function MsgIsReqGetData(msg: MsgBase): msg is ReqGetData { + return msg.type === "reqGetData"; +} + +export interface ResGetData extends ResSignedUrl { + readonly type: "resGetData"; + readonly payload: Uint8Array; // transfered via JSON base64 +} + +export interface ReqPutData extends ReqSignedUrl { + readonly type: "reqPutData"; + readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsReqPutData(msg: MsgBase): msg is ReqPutData { + return msg.type === "reqPutData"; +} + +export interface ResPutData extends ResSignedUrl { + readonly type: "resPutData"; +} + +export interface ReqDelData extends ReqSignedUrl { + readonly type: "reqGetData"; +} + +export function MsgIsReqDelData(msg: MsgBase): msg is ReqDelData { + return msg.type === "reqDelData"; +} + +export interface ResDelData extends ResSignedUrl { + readonly type: "resDelData"; +} + +export interface ReqGetWAL extends ReqSignedUrl { + readonly type: "reqGetWAL"; +} + +export function MsgIsReqGetWAL(msg: MsgBase): msg is ReqGetWAL { + return msg.type === "reqGetWAL"; +} + +export interface ResGetWAL extends ResSignedUrl { + readonly type: "resGetWAL"; + readonly payload: Uint8Array; // transfered via JSON base64 +} + + +export interface ReqPutWAL extends Omit { + readonly type: "reqPutWAL"; + readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsReqPutWAL(msg: MsgBase): msg is ReqPutWAL { + return msg.type === "reqPutWAL"; +} + +export interface ResPutWAL extends Omit { + readonly type: "resPutWAL"; +} + +export interface ReqDelWAL extends Omit { + readonly type: "reqGetWAL"; +} + +export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { + return msg.type === "reqDelWAL"; +} + +export interface ResDelWAL extends Omit { + readonly type: "resDelWAL"; +} \ No newline at end of file diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts index 70104a2c..b811faaa 100644 --- a/src/cloud/pre-signed-url.ts +++ b/src/cloud/pre-signed-url.ts @@ -4,6 +4,7 @@ import { Env } from "./backend/env.js"; import { ReqSignedUrl } from "./msg-types.js"; export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env, amzDate?: string): Promise> { + // verify if you are not overriding let store: string = req.params.store; if (req.params.index?.length) { store = `${store}-${req.params.index}`; diff --git a/src/connector.test.ts b/src/connector.test.ts index 4a2e85c5..66904cf1 100644 --- a/src/connector.test.ts +++ b/src/connector.test.ts @@ -1,8 +1,7 @@ // import { connectionFactory } from "./connection-from-store"; // import { registerS3StoreProtocol } from "./s3/s3-gateway"; import { URI, runtimeFn } from "@adviser/cement"; -import { type Database, type SuperThis, bs, fireproof } from "@fireproof/core"; -import { mockSuperThis } from "../node_modules/@fireproof/core/tests/helpers.js"; +import { type Database, type SuperThis, bs, ensureSuperThis, fireproof } from "@fireproof/core"; import { type TaskContext, describe } from "vitest"; import type { ConnectFunction } from "./connection-from-store.js"; import { smokeDB } from "../tests/helper.js"; @@ -37,7 +36,7 @@ describe("loading the base store", () => { let emptyDbName: string; let remoteDbName: string; let connect: ConnectFunction; - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); let resetFPStorageUrl: string; afterEach(async () => { diff --git a/src/partykit/partykit-gateway.test.ts b/src/partykit/partykit-gateway.test.ts index 47b669ac..b9c8a7b0 100644 --- a/src/partykit/partykit-gateway.test.ts +++ b/src/partykit/partykit-gateway.test.ts @@ -1,9 +1,8 @@ -import { fireproof, Database, bs } from "@fireproof/core"; +import { fireproof, Database, bs, ensureSuperThis } from "@fireproof/core"; import { registerPartyKitStoreProtocol } from "./gateway.js"; import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { URI } from "@adviser/cement"; import { smokeDB } from "../../tests/helper.js"; -import { mockSuperThis } from "../../node_modules/@fireproof/core/tests/helpers.js"; // has to leave interface ExtendedGateway extends bs.Gateway { @@ -21,7 +20,7 @@ interface ExtendedStore { describe("PartyKitGateway", () => { let db: Database; let unregister: () => void; - const sthis = mockSuperThis(); + const sthis = ensureSuperThis(); beforeAll(() => { unregister = registerPartyKitStoreProtocol("partykit:"); From 730b0aa00d0aeb441b35e37609a081eeffc594ab Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Sun, 22 Dec 2024 12:24:21 +0100 Subject: [PATCH 30/83] chore: MsgConnection --- package.json | 10 +- pnpm-lock.yaml | 370 +++++++++++++++++- setup.cloud.ts | 4 +- src/cloud/backend/server.ts | 3 + .../client/{gateway.ts => gateway.ts-off} | 8 +- src/cloud/client/index.ts | 2 +- src/cloud/cloud.test.ts | 14 +- src/cloud/connection.test.ts | 254 ++++++++++++ src/cloud/http-connection.ts | 109 ++++++ src/cloud/msg-processor.ts | 16 +- src/cloud/msg-request.ts | 171 +------- src/cloud/msg-types.ts | 155 +++++++- src/cloud/msger.ts | 100 +++++ src/cloud/ws-connection.ts | 215 ++++++++++ src/coerce-binary.ts | 15 +- 15 files changed, 1249 insertions(+), 197 deletions(-) rename src/cloud/client/{gateway.ts => gateway.ts-off} (98%) create mode 100644 src/cloud/connection.test.ts create mode 100644 src/cloud/http-connection.ts create mode 100644 src/cloud/msger.ts create mode 100644 src/cloud/ws-connection.ts diff --git a/package.json b/package.json index b4433647..d8ca37ab 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "@types/ws": "^8.5.13", "@typescript-eslint/typescript-estree": "^8.17.0", "@web3-storage/access": "^20.1.0", - "cborg": "^4.2.7", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", @@ -99,13 +98,16 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.41" + "@adviser/cement": "^0.2.43" }, "dependencies": { - "@adviser/cement": "^0.2.41", + "@adviser/cement": "^0.2.43", "@aws-sdk/client-s3": "^3.705.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", + "@fireproof/core": "^0.19.118", + "@fireproof/vendor": "^1.0.0", + "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", @@ -128,7 +130,7 @@ "cross-fetch": "^4.0.0", "dotenv": "^16.4.5", "events": "^3.3.0", - "hono": "^4.6.11", + "hono": "^4.6.13", "idb-keyval": "^6.2.1", "is-deep-strict-equal-x": "^1.1.2", "multiformats": "^13.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab79a6d1..78b82366 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.41 - version: 0.2.41(typescript@5.7.2) + specifier: ^0.2.43 + version: 0.2.43(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.705.0 version: 3.705.0 @@ -20,6 +20,15 @@ importers: '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 + '@fireproof/core': + specifier: ^0.19.118 + version: 0.19.118(react@18.3.1)(typescript@5.7.2) + '@fireproof/vendor': + specifier: ^1.0.0 + version: 1.0.0 + '@hono/node-server': + specifier: ^1.13.7 + version: 1.13.7(hono@4.6.13) '@hono/node-ws': specifier: ^1.0.4 version: 1.0.4(@hono/node-server@1.13.7(hono@4.6.13)) @@ -87,7 +96,7 @@ importers: specifier: ^3.3.0 version: 3.3.0 hono: - specifier: ^4.6.11 + specifier: ^4.6.13 version: 4.6.13 idb-keyval: specifier: ^6.2.1 @@ -153,9 +162,6 @@ importers: '@typescript-eslint/typescript-estree': specifier: ^8.17.0 version: 8.17.0(typescript@5.7.2) - cborg: - specifier: ^4.2.7 - version: 4.2.7 esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -210,8 +216,8 @@ importers: packages: - '@adviser/cement@0.2.41': - resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} + '@adviser/cement@0.2.43': + resolution: {integrity: sha512-jBxv0bbzHODe7KrCrknQgy6g0KV/vq92olbXNgI+O87hiThALTv0FKfBgxY7NrMoHmEM4+89s+hHCuoH+l7NSg==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -1068,6 +1074,14 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} + '@fireproof/core@0.19.118': + resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} + peerDependencies: + react: ^18.3.1 + + '@fireproof/vendor@1.0.0': + resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1132,6 +1146,9 @@ packages: '@ipld/unixfs@2.2.0': resolution: {integrity: sha512-lDQ2eRhJlbFaBoO3bhOmDVCLmpOnhwtwbilqUgAAhbhoPSmLrnv7gsBuToZjXOdPaEGSL7apkmm6nFrcU6zh4Q==} + '@ipld/unixfs@3.0.0': + resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1157,6 +1174,24 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.1.1': + resolution: {integrity: sha512-osjeBqMJ2lb/j/M8NCPjs1ylqWIcTRTycIhVB5pt6LgzgeRSb0YRZ7j9RfA8wIUrsr/medIuhVyonXRZWLyfdw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.5.0': + resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} @@ -1871,6 +1906,10 @@ packages: resolution: {integrity: sha512-rO414jDJf//NDNvIfbChPT+qAXrs5aXIWwq+327qWVn64eKpE+dMsr72o+18tYsSOnF79C6+LO9c756/h6Ghaw==} engines: {node: '>=8.11.4', npm: 6.10.1} + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + bigint-mod-arith@3.3.1: resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} engines: {node: '>=10.4.0'} @@ -1953,6 +1992,9 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + charwise@3.0.1: + resolution: {integrity: sha512-RcdumNsM6fJZ5HHbYunqj2bpurVRGsXour3OR+SlLEHFhG6ALm54i6Osnh+OvO7kEoSBzwExpblYFH8zKQiEPw==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -2230,6 +2272,9 @@ packages: resolution: {integrity: sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==} engines: {node: '>=10.13.0'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -2412,6 +2457,9 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + hamt-sharding@3.0.6: + resolution: {integrity: sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==} + has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -2469,6 +2517,10 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2476,6 +2528,9 @@ packages: idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + idb@8.0.1: + resolution: {integrity: sha512-EkBCzUZSdhJV8PxMSbeEV//xguVKZu9hZZulM+2gHXI0t2hGVU3eYE6/XnH77DS6FM2FY8wl17aDcu9vXpvLWQ==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2508,6 +2563,15 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + interface-blockstore@5.3.1: + resolution: {integrity: sha512-nhgrQnz6yUQEqxTFLhlOBurQOy5lWlwCpgFmZ3GTObTVTQS9RZjK/JTozY6ty9uz2lZs7VFJSqwjWAltorJ4Vw==} + + interface-store@6.0.2: + resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} + + ipfs-unixfs@11.2.0: + resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} + ipfs-utils@9.0.14: resolution: {integrity: sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -2711,9 +2775,37 @@ packages: it-all@1.0.6: resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} + it-filter@3.1.1: + resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} + it-glob@1.0.2: resolution: {integrity: sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==} + it-last@3.0.6: + resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} + + it-map@3.1.1: + resolution: {integrity: sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==} + + it-merge@3.0.5: + resolution: {integrity: sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==} + + it-parallel@3.0.8: + resolution: {integrity: sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==} + + it-peekable@3.0.5: + resolution: {integrity: sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==} + + it-pipe@3.0.1: + resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + it-pushable@3.2.3: + resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} + + it-stream-types@2.0.2: + resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} + it-to-stream@1.0.0: resolution: {integrity: sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==} @@ -2730,6 +2822,9 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2783,6 +2878,10 @@ packages: long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + loupe@3.1.2: resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} @@ -2806,6 +2905,10 @@ packages: resolution: {integrity: sha512-mQ2o1VayrZ6Jaz8VyP8B7h/hdn2iAnbUOrQh4rTiwbpULhktpD8IpHGBw8Qo2fmv97Z1P3YzLF3X/DkbIHBQmA==} engines: {node: '>=8.11.4', npm: 6.10.1} + memfs@4.15.0: + resolution: {integrity: sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==} + engines: {node: '>= 4.0.0'} + memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} engines: {node: '>=0.12'} @@ -2947,6 +3050,10 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} + node-sql-parser@3.9.4: + resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} + engines: {node: '>=8'} + node-sqlite3-wasm@0.8.28: resolution: {integrity: sha512-QK5Q0+sgsHNPWiOPFHiBWrfXuJa9UDXi7nUDHhyIlVgoVzltWKDGqoNOERjga+o+ncr5Od7A7kkB4GEmsoUuSA==} @@ -3030,10 +3137,22 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + engines: {node: '>=18'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + p-retry@5.1.2: resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3042,6 +3161,14 @@ packages: resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} engines: {node: '>=16.17'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + + p-timeout@6.1.3: + resolution: {integrity: sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==} + engines: {node: '>=14.16'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -3159,6 +3286,12 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + progress-events@1.0.1: + resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} + + prolly-trees@1.0.4: + resolution: {integrity: sha512-vtnxfw5wnUHbGa0IIIk9B9DRztJWZw+t9d0s0iGxY/VzEGCg2EMl8GgGU3EhSquFLWapwbGjFTL1ipbezaXR3g==} + property-is-enumerable-x@2.1.2: resolution: {integrity: sha512-lRqJh4yGnwiZUx7x8abWhfucNsImqwxbFoCQzRjfwJflOBenZoFq/YMlWJShdzBmqd9i2/RrrvFW8cBs1+H+3w==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -3167,6 +3300,9 @@ packages: resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} engines: {node: '>=12.0.0'} + protons-runtime@5.5.0: + resolution: {integrity: sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -3190,6 +3326,10 @@ packages: react-native-fetch-api@3.0.0: resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -3346,6 +3486,9 @@ packages: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead + sparse-array@1.3.2: + resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} + split-if-boxed-bug-x@2.1.2: resolution: {integrity: sha512-s16LLvA6VVqayT560dGsP1AXGWAIBsd/1KotRSjoPiaAMPKLbyio9iAsR+b6RGBF22zdlBLGjc4KyU5KCfmzIA==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -3445,6 +3588,12 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + timers-ext@0.1.8: resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} engines: {node: '>=0.12'} @@ -3521,6 +3670,12 @@ packages: tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -3630,6 +3785,9 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + uint8-varint@2.0.4: + resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} + uint8arraylist@2.4.8: resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} @@ -3896,6 +4054,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + yoga-wasm-web@0.3.3: resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} @@ -3912,7 +4074,7 @@ packages: snapshots: - '@adviser/cement@0.2.41(typescript@5.7.2)': + '@adviser/cement@0.2.43(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4822,6 +4984,41 @@ snapshots: '@fastify/busboy@2.1.1': {} + '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': + dependencies: + '@adviser/cement': 0.2.43(typescript@5.7.2) + '@fireproof/vendor': 1.0.0 + '@ipld/unixfs': 3.0.0 + charwise: 3.0.1 + idb: 8.0.1 + memfs: 4.15.0 + multiformats: 13.3.1 + p-limit: 6.1.0 + p-map: 7.0.3 + p-retry: 6.2.1 + prolly-trees: 1.0.4 + react: 18.3.1 + transitivePeerDependencies: + - typescript + + '@fireproof/vendor@1.0.0': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + varint: 6.0.0 + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -4897,6 +5094,16 @@ snapshots: protobufjs: 7.4.0 rabin-rs: 2.1.0 + '@ipld/unixfs@3.0.0': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + '@perma/map': 1.0.3 + actor: 2.3.1 + multiformats: 13.3.1 + protobufjs: 7.4.0 + rabin-rs: 2.1.0 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -4928,6 +5135,22 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.1.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.5.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + '@jspm/core@2.1.0': {} '@multiformats/murmur3@2.1.8': @@ -5925,6 +6148,8 @@ snapshots: object-define-properties-x: 5.1.2 to-boolean-x: 2.1.1 + big-integer@1.6.52: {} + bigint-mod-arith@3.3.1: {} bindings@1.5.0: @@ -6024,6 +6249,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + charwise@3.0.1: {} + check-error@2.1.1: {} chokidar@4.0.1: @@ -6438,6 +6665,8 @@ snapshots: event-target-shim@6.0.2: {} + eventemitter3@5.0.1: {} + events@3.3.0: {} execa@8.0.1: @@ -6633,6 +6862,11 @@ snapshots: graphemer@1.4.0: {} + hamt-sharding@3.0.6: + dependencies: + sparse-array: 1.3.2 + uint8arrays: 5.1.0 + has-bigints@1.0.2: {} has-boxed-string-x@2.1.1: {} @@ -6681,12 +6915,16 @@ snapshots: human-signals@5.0.0: {} + hyperdyperid@1.2.0: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 idb-keyval@6.2.1: {} + idb@8.0.1: {} + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -6722,6 +6960,18 @@ snapshots: ini@1.3.8: {} + interface-blockstore@5.3.1: + dependencies: + interface-store: 6.0.2 + multiformats: 13.3.1 + + interface-store@6.0.2: {} + + ipfs-unixfs@11.2.0: + dependencies: + protons-runtime: 5.5.0 + uint8arraylist: 2.4.8 + ipfs-utils@9.0.14(encoding@0.1.13): dependencies: any-signal: 3.0.1 @@ -6992,11 +7242,43 @@ snapshots: it-all@1.0.6: {} + it-filter@3.1.1: + dependencies: + it-peekable: 3.0.5 + it-glob@1.0.2: dependencies: '@types/minimatch': 3.0.5 minimatch: 3.1.2 + it-last@3.0.6: {} + + it-map@3.1.1: + dependencies: + it-peekable: 3.0.5 + + it-merge@3.0.5: + dependencies: + it-pushable: 3.2.3 + + it-parallel@3.0.8: + dependencies: + p-defer: 4.0.1 + + it-peekable@3.0.5: {} + + it-pipe@3.0.1: + dependencies: + it-merge: 3.0.5 + it-pushable: 3.2.3 + it-stream-types: 2.0.2 + + it-pushable@3.2.3: + dependencies: + p-defer: 4.0.1 + + it-stream-types@2.0.2: {} + it-to-stream@1.0.0: dependencies: buffer: 6.0.3 @@ -7024,6 +7306,8 @@ snapshots: joycon@3.1.1: {} + js-tokens@4.0.0: {} + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -7065,6 +7349,10 @@ snapshots: long@5.2.3: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + loupe@3.1.2: {} lru-cache@10.4.3: {} @@ -7090,6 +7378,13 @@ snapshots: is-nan-x: 2.1.1 to-number-x: 3.2.2 + memfs@4.15.0: + dependencies: + '@jsonjoy.com/json-pack': 1.1.1(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) + tslib: 2.8.1 + memoizee@0.4.17: dependencies: d: 1.0.2 @@ -7226,6 +7521,10 @@ snapshots: node-forge@1.3.1: {} + node-sql-parser@3.9.4: + dependencies: + big-integer: 1.6.52 + node-sqlite3-wasm@0.8.28: {} noop-x@1.2.1: {} @@ -7344,10 +7643,21 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-limit@6.1.0: + dependencies: + yocto-queue: 1.1.1 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-map@7.0.3: {} + + p-queue@8.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.3 + p-retry@5.1.2: dependencies: '@types/retry': 0.12.1 @@ -7359,6 +7669,14 @@ snapshots: is-network-error: 1.1.0 retry: 0.13.1 + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + + p-timeout@6.1.3: {} + package-json-from-dist@1.0.1: {} parent-module@1.0.1: @@ -7466,6 +7784,13 @@ snapshots: process@0.11.10: {} + progress-events@1.0.1: {} + + prolly-trees@1.0.4: + dependencies: + bl: 4.1.0 + node-sql-parser: 3.9.4 + property-is-enumerable-x@2.1.2: dependencies: simple-methodize-x: 1.0.4 @@ -7487,6 +7812,12 @@ snapshots: '@types/node': 22.10.1 long: 5.2.3 + protons-runtime@5.5.0: + dependencies: + uint8-varint: 2.0.4 + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + proxy-from-env@1.1.0: {} pump@3.0.2: @@ -7511,6 +7842,10 @@ snapshots: dependencies: p-defer: 3.0.0 + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -7683,6 +8018,8 @@ snapshots: sourcemap-codec@1.4.8: {} + sparse-array@1.3.2: {} + split-if-boxed-bug-x@2.1.2: dependencies: has-boxed-string-x: 2.1.1 @@ -7792,6 +8129,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thingies@1.21.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + timers-ext@0.1.8: dependencies: es5-ext: 0.10.64 @@ -7879,6 +8220,10 @@ snapshots: dependencies: punycode: 2.3.1 + tree-dump@1.0.2(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + tree-kill@1.2.2: {} trim-left-x@4.1.2: @@ -7979,6 +8324,11 @@ snapshots: ufo@1.5.4: {} + uint8-varint@2.0.4: + dependencies: + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + uint8arraylist@2.4.8: dependencies: uint8arrays: 5.1.0 @@ -8252,6 +8602,8 @@ snapshots: yocto-queue@0.1.0: {} + yocto-queue@1.1.1: {} + yoga-wasm-web@0.3.3: {} youch@3.3.4: diff --git a/setup.cloud.ts b/setup.cloud.ts index 07650fdb..eb624898 100644 --- a/setup.cloud.ts +++ b/setup.cloud.ts @@ -1,8 +1,8 @@ import { BuildURI } from "@adviser/cement"; -import { registerFireproofCloudStoreProtocol } from "./src/cloud/client/gateway.ts"; +// import { registerFireproofCloudStoreProtocol } from "./src/cloud/client/gateway.ts"; import dotenv from "dotenv"; -registerFireproofCloudStoreProtocol(); +// registerFireproofCloudStoreProtocol(); dotenv.config(); diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index ec50708b..a3ef1a64 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -414,6 +414,9 @@ class CFMsgProcessor extends MsgProcessorBase { export default { async fetch(req, env, _ctx): Promise { + + + const id = env.FP_META_GROUPS.idFromName("fireproof"); const stub = env.FP_META_GROUPS.get(id); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts-off similarity index 98% rename from src/cloud/client/gateway.ts rename to src/cloud/client/gateway.ts-off index e6e1e3a5..0c9c431b 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts-off @@ -6,7 +6,6 @@ import { buildReqGetMeta, buildReqPutMeta, buildReqSubscriptMeta, - Connection, ConnectionKey, HttpMethods, MsgBase, @@ -21,13 +20,14 @@ import { } from "../msg-types.js"; import { newWebSocket } from "../new-websocket.js"; import { to_uint8 } from "../../coerce-binary.js"; +import { MsgConnection } from "../msger.js"; const VERSION = "v0.1-fp-cloud"; export interface StoreTypeGateway { - get(uri: URI, conn: Promise>): Promise>; - put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; - delete(uri: URI, conn: Promise>): Promise>; + get(uri: URI, conn: Promise>): Promise>; + put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; + delete(uri: URI, conn: Promise>): Promise>; } abstract class BaseGateway { diff --git a/src/cloud/client/index.ts b/src/cloud/client/index.ts index 48804cd3..2c2610e6 100644 --- a/src/cloud/client/index.ts +++ b/src/cloud/client/index.ts @@ -1,7 +1,7 @@ import { BuildURI, CoerceURI, KeyedResolvOnce, runtimeFn, URI } from "@adviser/cement"; import { bs, Database, fireproof } from "@fireproof/core"; import { ConnectFunction, connectionFactory, makeKeyBagUrlExtractable } from "../../connection-from-store.js"; -import { registerFireproofCloudStoreProtocol } from "./gateway.js"; +import { registerFireproofCloudStoreProtocol } from "./gateway.ts-off"; interface ConnectData { readonly remoteName: string; diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 629466fe..995be4c5 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -8,7 +8,7 @@ import * as toml from "smol-toml"; import { bs, CRDTEntry, Database, ensureSuperThis, fireproof, isNotFoundError, rt } from "@fireproof/core"; import { AwsClient } from "aws4fetch"; import { smokeDB } from "../../tests/helper.js"; -import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.js"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.ts-off"; import { calculatePreSignedUrl } from "./pre-signed-url.js"; import { newWebSocket } from "./new-websocket.js"; @@ -19,7 +19,7 @@ function testReqSignedUrl(tid = "test") { params: { // protocol: "ws", path: "/hallo", - name: "test-name", + ledgerName: "test-name", method: "GET", tenantId: "tenantId", store: "wal", @@ -146,6 +146,16 @@ describe("CloudBackendTest", () => { expect(res.status).toBe(200); expect(await res.json()).toEqual(await testResSignedUrl(env)); }); + + it("reqOpen without websocket", async () => { + const conn = await msgOpen(cfURL, { } + }); + + it("reqOpen with websocket", async () => { + }); + + + it("use websockets SignedUrl", async () => { await Promise.all( Array(100) diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts new file mode 100644 index 00000000..a53f5540 --- /dev/null +++ b/src/cloud/connection.test.ts @@ -0,0 +1,254 @@ +import { ensureSuperThis, SuperThis } from "@fireproof/core"; +import { Result, URI } from "@adviser/cement"; +import { + buildErrorMsg, + buildReqGestalt, + buildReqOpen, + buildResGestalt, + buildResOpen, + MsgIsError, + MsgIsReqOpen, + MsgIsReqGestalt, + MsgIsResGestalt, + MsgIsResOpen, + MsgBase, + ReqOpen +} from "./msg-types.js"; +import { serve, ServerType } from '@hono/node-server' +import { createNodeWebSocket } from '@hono/node-ws' +import { Hono } from 'hono' +import { defaultGestaltItem, MsgConnection, Msger } from "./msger.js"; +import { top_uint8 } from "../coerce-binary.js"; + +function dispatch(sthis: SuperThis, msg: MsgBase, send: (msg: MsgBase) => void) { + switch (true) { + case MsgIsReqGestalt(msg): + return send(buildResGestalt(msg, defaultGestaltItem(sthis, { id: "server", hasPersistent: true }).gestalt)); + case MsgIsReqOpen(msg): + return send(buildResOpen(msg)); + default: + // c.status(501) + return send(buildErrorMsg(sthis, sthis.logger, msg, new Error("unexpected message"))); + } +} + +async function applyStart(prC: Promise>): Promise> { + const rC = await prC + if (rC.isErr()) { + return rC + } + const c = rC.Ok() + const r = await c.start() + if (r.isErr()) { + return Result.Ok(c) + } + return rC +} + +describe("Connection", () => { + const sthis = ensureSuperThis(); + const gsi = defaultGestaltItem(sthis, { id: "test", hasPersistent: true }) + let server: ServerType + let port: number + beforeAll(async () => { + const app = new Hono() + const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }) + // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) + // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) + app.put('/fp', async (c) => { + const msg = await c.req.json() + return dispatch(sthis, msg, (msg) => c.json(msg)) + }) + app.get("/ws", upgradeWebSocket((c) => { + return { + onOpen: () => { + // console.log('Connection opened', c.req.url) + }, + onError: (error) => { + console.error(`WebSocket error: ${error}`) + }, + async onMessage(event, ws) { + // console.log('onMsg event', event, event.data); + dispatch(sthis, gsi.ende.decode(await top_uint8(event.data)), (msg) => { + const str = gsi.ende.encode(msg) + ws.send(str) + }) + }, + onClose: () => { + // console.log('Connection closed') + }, + } + }) + ) + + port = 1024 + Math.floor(Math.random() * (65536 - 1024)) + server = await new Promise((resolve) => { + const server = serve({ fetch: app.fetch, port }, () => resolve(server)) + injectWebSocket(server) + return server + }) + }) + afterAll(async () => { + await new Promise((resolve) => server.close(resolve)) + }) + + const qOpen = { + tid: "WS-OPEN", + version: "FP-MSG-1.0", + type: "reqOpen", + key: { + ledgerName: "test", + tenantId: "test", + }, + streamId: { + req: "req-open-test", + } + } satisfies ReqOpen + + for (const style of [{ + name: "HTTP", + url: () => URI.from(`http://localhost:${port}/fp`), + open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], gsi)) + }, { + name: "WS", + url: () => URI.from(`http://localhost:${port}/ws`), + open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), gsi)) + }]) { + describe(style.name, () => { + + let c: MsgConnection + beforeEach(async () => { + const rC = await style.open() + expect(rC.isOk()).toBeTruthy() + c = rC.Ok() + expect(c.conn).toEqual({ + "key": { + "ledgerName": "test", + "tenantId": "test", + }, + "streamId": { + "req": "req-open-test", + "res": "res-req-open-test", + }, + "tid": "WS-OPEN", + "type": "resOpen", + "version": "FP-MSG-1.0", + }) + }) + afterEach(async () => { + await c.close() + }) + + it("kaputt url http", async () => { + const r = await c.request({ + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, { waitFor: () => true }) + if (!MsgIsError(r)) { + assert.fail("expected MsgError") + return + } + expect(r).toEqual({ + "message": "unexpected message", + "tid": "test", + "type": "error", + "version": "FP-MSG-1.0", + }) + }) + it("gestalt url http", async () => { + const gsi = defaultGestaltItem(sthis, { id: "test" }) + const req = buildReqGestalt(sthis, gsi.gestalt) + const r = await c.request(req, { waitFor: MsgIsResGestalt }) + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)) + } + expect(r).toEqual({ + "gestalt": { + "auth": [], + "encodings": [ + "JSON", + ], + "eventTypes": [ + "updateMeta", + ], + "httpEndpoints": [ + "/fp", + ], + "id": "server", + "protocolCapabilities": [ + "stream", + "reqRes", + ], + "reqTypes": [ + "reqOpen", + "reqGestalt", + "reqSubscribeMeta", + "reqPutMeta", + "reqGetMeta", + "reqDelMeta", + "reqPutData", + "reqGetData", + "reqDelData", + "reqPutWAL", + "reqGetWAL", + "reqDelWAL", + "reqUpdateMeta", + ], + "requiresAuth": false, + "resTypes": [ + "resOpen", + "resGestalt", + "resSubscribeMeta", + "resPutMeta", + "resGetMeta", + "resDelMeta", + "resPutData", + "resGetData", + "resDelData", + "resPutWAL", + "resGetWAL", + "resDelWAL", + "updateMeta", + ], + "storeTypes": [ + "meta", + "data", + "wal", + ], + "wsEndpoints": [ + "/ws", + ], + }, + "tid": req.tid, + "type": "resGestalt", + "version": "FP-MSG-1.0", + }) + }) + + it("openConnection", async () => { + const req = buildReqOpen(sthis, { + tenantId: "tenant", + ledgerName: "ledger", + }, "open-test") + const r = await c.request(req, { waitFor: MsgIsResOpen }) + if (!MsgIsResOpen(r)) { + assert.fail("expected MsgError") + } + expect(r).toEqual({ + key: { + "ledgerName": "ledger", + "tenantId": "tenant", + }, + streamId: { + "req": "open-test", + "res": "res-open-test", + }, + tid: req.tid, + "type": "resOpen", + "version": "FP-MSG-1.0", + }) + }) + }) + } +}) \ No newline at end of file diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts new file mode 100644 index 00000000..d8e6e0ef --- /dev/null +++ b/src/cloud/http-connection.ts @@ -0,0 +1,109 @@ +import { Logger, Result, URI, exception2Result } from "@adviser/cement"; +import { SuperThis, ensureLogger } from "@fireproof/core"; +import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; +import { GestaltItem, selectRandom } from "./msg-request.js"; +import { MsgBase, MsgIsResOpen, ReqOpen, ResOpen, buildErrorMsg } from "./msg-types.js"; +import { MsgConnection, OnMsgFn, UnReg } from "./msger.js"; + +export class HttpConnection implements MsgConnection { + readonly sthis: SuperThis; + readonly logger: Logger; + readonly gestalt: GestaltItem; + readonly baseURIs: URI[]; + + readonly qsOpen: { + readonly req?: ReqOpen; + res?: ResOpen; + }; + + get conn(): ResOpen | undefined { + return this.qsOpen.res; + } + + readonly #onMsg = new Map(); + + constructor(sthis: SuperThis, reqOpen: ReqOpen | undefined, uris: URI[], gi: GestaltItem) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "HttpConnection"); + this.gestalt = gi; + this.baseURIs = uris; + this.qsOpen = { req: reqOpen }; + } + + async start(): Promise> { + if (this.qsOpen.req) { + const sOpen = await this.request(this.qsOpen.req, { waitFor: MsgIsResOpen }) + if (!MsgIsResOpen(sOpen)) { + return Result.Ok(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); + } + this.qsOpen.res = sOpen; + } + return Result.Ok(undefined); + } + + async close(): Promise> { + this.#onMsg.clear(); + return Result.Ok(undefined); + } + + toMsg(msg: WithErrorMsg): WithErrorMsg { + this.#onMsg.forEach((fn) => fn(msg)); + return msg; + } + + onMsg(fn: OnMsgFn): UnReg { + const key = this.sthis.nextId().str + this.#onMsg.set(key, fn); + return () => this.#onMsg.delete(key); + } + + async request(req: Q, _opts: RequestOpts): Promise> { + const headers = new Headers(); + headers.append("Content-Type", this.gestalt.mime); + headers.append("Accept", this.gestalt.mime); + const rReqBody = exception2Result(() => this.gestalt.ende.encode(req)); + if (rReqBody.isErr()) { + return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, + this.logger.Error().Err(rReqBody.Err()).Any("req", req).Msg("encode error").AsError() + )); + } + headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); + const url = selectRandom(this.baseURIs) + this.logger.Debug().Url(url).Any("body", req).Msg("request"); + const rRes = await exception2Result(() => fetch(url.toString(), { + method: "PUT", + headers, + body: rReqBody.Ok(), + })); + this.logger.Debug().Url(url).Any("body", rRes).Msg("response"); + if (rRes.isErr()) { + return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, + this.logger.Error().Err(rRes).Msg("fetch error").AsError() + )); + } + const res = rRes.Ok(); + if (!res.ok) { + return this.toMsg( + buildErrorMsg(this.sthis, this.logger, req, this.logger.Error() + .Url(url) + .Str("status", res.status.toString()) + .Str("statusText", res.statusText).Msg("HTTP Error").AsError(), + await res.text())); + } + const data = new Uint8Array(await res.arrayBuffer()); + const ret = await exception2Result(async () => this.gestalt.ende.decode(data) as S); + if (ret.isErr()) { + return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, + this.logger.Error().Err(ret.Err()).Msg("decode error").AsError(), + this.sthis.txt.decode(data) + )); + } + return this.toMsg(ret.Ok()) + } + + // toOnMessage(msg: WithErrorMsg): Result> { + // this.mec.msgFn?.(msg as unknown as MessageEvent); + // return Result.Ok(msg); + // } + +} diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts index cf44f4b2..13e88a23 100644 --- a/src/cloud/msg-processor.ts +++ b/src/cloud/msg-processor.ts @@ -62,16 +62,16 @@ export interface MsgProcessor { } export interface RequestOpts { - readonly waitType: string; + readonly waitFor: (msg: MsgBase) => boolean; readonly timeout?: number; // ms } -export interface Connection { - readonly ws: WebSocket; - readonly key: ConnectionKey; - request(msg: MsgBase, opts: RequestOpts): Promise>; - onMessage(msgFn: (msg: MsgBase) => void): () => void; - close(): Promise; -} +// export interface Connection { +// readonly ws: WebSocket; +// readonly key: ConnectionKey; +// request(msg: MsgBase, opts: RequestOpts): Promise>; +// onMessage(msgFn: (msg: MsgBase) => void): () => void; +// close(): Promise; +// } export abstract class MsgProcessorBase implements MsgProcessor { diff --git a/src/cloud/msg-request.ts b/src/cloud/msg-request.ts index 09009312..e87b2f85 100644 --- a/src/cloud/msg-request.ts +++ b/src/cloud/msg-request.ts @@ -1,10 +1,11 @@ import { Future, Logger, exception2Result, Result, CoerceURI, KeyedResolvOnce, URI } from "@adviser/cement"; -import { SuperThis, ensureLogger } from "@fireproof/core"; -import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { MsgBase, AuthType, Gestalt, defaultGestalt, ResGestalt, ReqGestalt, buildErrorMsg } from "./msg-types.js"; +import { SuperThis, } from "@fireproof/core"; +import { RequestOpts, } from "./msg-processor.js"; +import { MsgBase, AuthType, Gestalt, defaultGestalt, ResGestalt, ReqGestalt, MsgIsResGestalt, MsgIsError, } from "./msg-types.js"; import * as json from 'multiformats/codecs/json'; import * as cborg from '@fireproof/vendor/cborg'; +import { MsgConnection } from "./msger.js"; export interface EnDeCoder { encode(node: T): Uint8Array; @@ -15,14 +16,7 @@ export interface WaitForTid { readonly tid: string; readonly future: Future; // undefined match all - readonly type?: string; -} - -export interface Connection { - // readonly ws: WebSocket; - // readonly params: ConnectionKey; - request(req: Q, opts: RequestOpts): Promise>> - + readonly waitFor: (msg: MsgBase) => boolean; } export interface FetchGestaltParams { @@ -30,12 +24,12 @@ export interface FetchGestaltParams { readonly sthis: SuperThis; readonly gestaltURL: URI; readonly uniqServerId?: string; - readonly getConn: () => Promise; + readonly getConn: () => Promise; } export interface HttpConnectionParams { readonly gestaltURL: CoerceURI; - readonly fetchConnection?: Connection; + readonly fetchConnection?: MsgConnection; readonly ende?: EnDeCoder; readonly uniqServerId?: string; } @@ -44,7 +38,8 @@ export interface GestaltItem { readonly ende: EnDeCoder; readonly mime: string; readonly auth?: AuthType; - readonly params: Gestalt; + readonly hasPersistent?: boolean; + readonly gestalt: Gestalt; } export type RequestFN = (req: Q, opts: RequestOpts) => Promise> @@ -78,85 +73,26 @@ async function fetchGestalt(fgp: FetchGestaltParams): Promise { type: "reqGestalt", tid: fgp.sthis.nextId().str, version: serverId, - gestalt: defaultGestalt(fgp.uniqServerId || serverId, false), - }, { waitType: "resGestalt" }); - if (rGestalt.isErr()) { - throw rGestalt.Err(); + gestalt: defaultGestalt({ id: fgp.uniqServerId || serverId }), + }, { waitFor: MsgIsResGestalt }); + if (MsgIsError(rGestalt)) { + throw Error(rGestalt.message) } - const gestalt = rGestalt.Ok() as ResGestalt; - const ende = encoded(fgp.sthis.logger, gestalt.params.encodings[0]) + const gestalt = rGestalt.gestalt + const ende = encoded(fgp.sthis.logger, gestalt.encodings[0]) return { ende: ende.ende, mime: ende.mime, auth: gestalt.auth, - params: gestalt.params + gestalt: gestalt } }) } -function selectRandom(arr: T[]): T { +export function selectRandom(arr: T[]): T { return arr[Math.floor(Math.random() * arr.length)]; } -export class HttpConnection implements Connection { - readonly sthis: SuperThis; - readonly logger: Logger; - readonly gestaltItem: GestaltItem; - readonly mec: MsgErrorClose; - constructor(sthis: SuperThis, gi: GestaltItem, mec: MsgErrorClose = {}) { - this.sthis = sthis; - this.logger = ensureLogger(sthis, "HttpConnection"); - this.gestaltItem = gi; - this.mec = mec; - } - - async request(req: Q, _opts: RequestOpts): Promise>> { - const headers = new Headers(); - headers.append("Content-Type", this.gestaltItem.mime); - headers.append("Accept", this.gestaltItem.mime); - const rReqBody = exception2Result(() => this.gestaltItem.ende.encode(req)); - if (rReqBody.isErr()) { - return this.toOnMessage(buildErrorMsg(this.logger, req, - this.logger.Error().Err(rReqBody.Err()).Msg("encode error").AsError() - )); - } - headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); - const url = selectRandom(this.gestaltItem.params.httpEndpoints) - const rRes = await exception2Result(() => fetch(url, { - method: "PUT", - headers, - body: rReqBody.Ok(), - })); - if (rRes.isErr()) { - return this.toOnMessage(buildErrorMsg(this.logger, req, - this.logger.Error().Err(rRes.Ok()).Msg("fetch error").AsError() - )); - } - const res = rRes.Ok(); - if (!res.ok) { - return this.toOnMessage( - buildErrorMsg(this.logger, req, this.logger.Error() - .Url(url) - .Str("status", res.status.toString()) - .Str("statusText", res.statusText).Msg("HTTP Error").AsError())); - } - const data = new Uint8Array(await res.arrayBuffer()); - const ret = await exception2Result(async () => this.gestaltItem.ende.decode(data) as S); - if (ret.isErr()) { - return this.toOnMessage(buildErrorMsg(this.logger, req, - this.logger.Error().Err(ret.Err()).Msg("decode error").AsError() - )); - } - return this.toOnMessage(ret.Ok()) - } - - toOnMessage(msg: WithErrorMsg): Result> { - this.mec.msgFn?.(msg as unknown as MessageEvent); - return Result.Ok(msg); - } - -} - export interface MsgErrorClose { readonly msgFn: (msg: MessageEvent) => void; readonly errFn: (err: Event) => void; @@ -164,79 +100,6 @@ export interface MsgErrorClose { readonly openFn: () => void; } -export class WSAttachConnection implements Connection { - readonly ws: WebSocket; - // readonly key: ConnectionKey; - readonly sthis: SuperThis; - readonly logger: Logger; - - // readonly errFns = new Map void>(); - // readonly closeFns = new Map void>(); - // readonly msgFns = new Map void>(); - - readonly waitForTid: WSAttachable["waitForTid"]; - constructor(sthis: SuperThis, ws: WebSocket, waitForTid: WSAttachable["waitForTid"], mec: MsgErrorClose) { - this.ws = ws; - // this.key = key; - this.sthis = sthis; - // this.onClose = onClose; - this.logger = ensureLogger(sthis, "WSAttachConnection", { - this: true, - }); - this.waitForTid = waitForTid; - ws.onmessage = mec.msgFn - ws.onopen = mec.openFn; - ws.onerror = mec.errFn - ws.onclose = mec.closeFn - } - - async close(): Promise { - this.logger.Debug().Msg("close"); - this.ws.close(); - } - - async request(req: Q, opts: RequestOpts): Promise> { - opts = { - ...{ - timeout: 1000, - }, - ...opts, - }; - const future = new Future(); - this.waitForTid.set(req.tid, { - tid: req.tid, - future, - type: opts.waitType, - }); - const start = Date.now(); - const logger = ensureLogger(this.sthis, "ConnectionImpl.request") - .With() - .Str("tid", req.tid) - .Uint64("timeout", opts.timeout) - .Ref("start", () => new Date().getTime() - start) - .Any("req", req) - .Logger(); - this.ws.send(JSON.stringify(req)); - const clean = setTimeout(() => { - this.waitForTid.delete(req.tid); - future.reject(new Error("Timeout")); - }, opts.timeout); - // add timeout handling - logger.Debug().Msg("request-enter"); - return future - .asPromise() - .finally(() => clearTimeout(clean)) - .then((res) => { - logger.Debug().Any("res", res).Msg("request-ok"); - return Result.Ok(res as S); - }) - .catch((err) => { - logger.Error().Err(err).Msg("request-error"); - return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); - }); - } -} - export interface GestaltParams { diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 434d6388..8ef34507 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,4 +1,5 @@ import { CRDTEntry, Logger, SuperThis } from "@fireproof/core"; +import { GestaltItem } from "./msg-request.js"; export interface ConnId { readonly connId: string; @@ -30,6 +31,8 @@ export interface MsgBase { export interface ErrorMsg extends MsgBase { readonly type: "error"; readonly message: string; + readonly body?: string; + readonly stack?: string[]; } export function MsgIsError(rq: MsgBase): rq is ErrorMsg { return rq.type === "error"; @@ -41,6 +44,15 @@ export function MsgIsQSError(rq: ReqRes): rq is ReqRes & { readonly id: string }; + +export function defaultGestalt(gs: GestaltParam & { + hasPersitance?: boolean; +}): Gestalt { + const hasPersitance = gs.hasPersitance || false; + delete gs.hasPersitance; return { storeTypes: ["meta", "data", "wal"], - id: uniqServerId, + id: gs.id, httpEndpoints: ["/fp"], wsEndpoints: ["/ws"], encodings: ["JSON"], + protocolCapabilities: ["stream", "reqRes"], auth: [], requiresAuth: false, data: hasPersitance ? { @@ -131,6 +156,7 @@ export function defaultGestalt(uniqServerId: string, hasPersitance: boolean): Ge outband: true, }: undefined, reqTypes: [ + "reqOpen", "reqGestalt", // "reqSignedUrl", "reqSubscribeMeta", @@ -146,6 +172,7 @@ export function defaultGestalt(uniqServerId: string, hasPersitance: boolean): Ge "reqUpdateMeta", ], resTypes: [ + "resOpen", "resGestalt", // "resSignedUrl", "resSubscribeMeta", @@ -161,6 +188,7 @@ export function defaultGestalt(uniqServerId: string, hasPersitance: boolean): Ge "updateMeta", ], eventTypes: ["updateMeta"], + ...gs.gestalt } } @@ -177,13 +205,22 @@ export function MsgIsReqGestalt(msg: MsgBase): msg is ReqGestalt { return msg.type === "reqGestalt"; } +export function buildReqGestalt(sthis: NextId, gestalt: Gestalt): ReqGestalt { + return { + tid: sthis.nextId().str, + type: "reqGestalt", + version: VERSION, + gestalt + }; +} + /** * The ResGestalt message is used to respond with * the features of the Responder. */ export interface ResGestalt extends MsgBase { readonly type: "resGestalt"; - readonly params: Gestalt; + readonly gestalt: Gestalt; } export function buildResGestalt(req: ReqGestalt, gestalt: Gestalt): ResGestalt | ErrorMsg { @@ -191,7 +228,7 @@ export function buildResGestalt(req: ReqGestalt, gestalt: Gestalt): ResGestalt | tid: req.tid, type: "resGestalt", version: VERSION, - params: gestalt + gestalt }; } @@ -200,13 +237,104 @@ export function MsgIsResGestalt(msg: MsgBase): msg is ResGestalt { } +export interface ReqOpen extends MsgBase { + readonly type: "reqOpen"; + readonly key: ConnectionKey; + readonly streamId: { + readonly req: string; + }; +} -export interface ConnectionKey { - // readonly protocol: "ws" | "wss"; // ws or wss - readonly tenantId: string; - readonly name: string; +export function buildReqOpen(sthis: NextId, key: ConnectionKey, reqStreamId = sthis.nextId().str): ReqOpen { + return { + tid: sthis.nextId().str, + type: "reqOpen", + version: VERSION, + key, + streamId: { + req: reqStreamId + } + }; } +export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { + return msg.type === "reqOpen"; +} + +export interface ResOpen extends MsgBase { + readonly type: "resOpen"; + readonly key: ConnectionKey; + readonly streamId: { + readonly req: string; + readonly res: string; + }; +} + +export function buildResOpen(req: ReqOpen, resStreamId = 'res-'+req.streamId.req): ResOpen { + return { + ...req, + type: "resOpen", + streamId: { + ...req.streamId, + res: resStreamId + } + }; +} + +export function MsgIsResOpen(msg: MsgBase): msg is ResOpen { + return msg.type === "resOpen"; +} + + +// /* +// * This behavios somekind of strange if it comes to WebSocket +// * if the requesting Gestalt wants http it responds with http +// * if the requesting Gestalt wants WebSocket and the requested +// * is capable of WebSocket this response is sent via WebSocket +// */ +// export interface ResOpen extends MsgBase { +// readonly type: "resOpen"; +// readonly key: ConnectionKey; +// readonly connId: string; +// // reguester Gestalt +// readonly gestalt: Gestalt; +// } + +// export function buildReqOpen(sthis: NextId, key: ConnectionKey, gestalt: Gestalt): ReqOpen { +// return { +// tid: sthis.nextId().str, +// type: "reqOpen", +// version: VERSION, +// key, +// gestalt, +// }; +// } + +// export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { +// return msg.type === "reqOpen"; +// } + +// export function buildResOpen(req: ReqOpen, connId: string, gestalt: Gestalt): ResOpen { +// return { +// tid: req.tid, +// type: "resOpen", +// version: VERSION, +// key: req.key, +// connId, +// gestalt, +// }; +// } + +// export function MsgIsResOpen(msg: MsgBase): msg is ResOpen { +// return msg.type === "resOpen"; +// } + +// export interface ConnectionKey { +// // readonly protocol: "ws" | "wss"; // ws or wss +// readonly tenantId: string; +// readonly name: string; +// } + export interface SignedUrlParam extends ConnectionKey { readonly path?: string; readonly method: HttpMethods; @@ -232,8 +360,9 @@ export interface ReqSignedUrlParam { readonly auth?: AuthType; readonly params: { // readonly protocol?: "ws" | "wss"; // ws or wss - readonly tenantId: string; - readonly name: string; + // readonly tenantId: string; + // readonly name: string; + readonly connectionKey: ConnectionKey; readonly path?: string; readonly method: HttpMethods; readonly store: FPStoreTypes; @@ -288,12 +417,16 @@ export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSign }; } -export function buildErrorMsg(logger: Logger, base: Partial, error: Error): ErrorMsg { +export function buildErrorMsg(sthis: SuperThis, logger: Logger, base: Partial, error: Error, body?: string, stack?: string[]): ErrorMsg { + if (!stack && sthis.env.get("FP_STACK")) { + stack = error.stack?.split("\n"); + } const msg = { type: "error", tid: base.tid || "internal", message: error.message, version: VERSION, + body, stack } satisfies ErrorMsg; logger.Error().Any("msg", msg).Msg("error"); return msg; diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts new file mode 100644 index 00000000..b68a5d17 --- /dev/null +++ b/src/cloud/msger.ts @@ -0,0 +1,100 @@ +import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; +import { buildReqGestalt, defaultGestalt, GestaltParam, MsgBase, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; +import { SuperThis } from "@fireproof/core"; +import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; +import { HttpConnection } from "./http-connection.js"; +import { EnDeCoder, GestaltItem, selectRandom } from "./msg-request.js"; +import { WSConnection } from "./ws-connection.js"; + +// const headers = { +// "Content-Type": "application/json", +// "Accept": "application/json", +// }; + +export type OnMsgFn = (msg: WithErrorMsg) => void +export type UnReg = () => void + +export interface MsgConnection { + // readonly ws: WebSocket; + // readonly params: ConnectionKey; + conn?: ResOpen; + request(req: Q, opts: RequestOpts): Promise> + start(): Promise>; + close(): Promise>; + onMsg(msg: OnMsgFn): UnReg +} + +function jsonEnDe(sthis: SuperThis) { + return { + encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)), + decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)), + } satisfies EnDeCoder; +} + +export function defaultGestaltItem(sthis: SuperThis, igs: GestaltParam): GestaltItem { + return { + ende: igs.ende || jsonEnDe(sthis), + mime: igs.mime || "application/json", + gestalt: defaultGestalt(igs), + } satisfies GestaltItem; +} + +// eslint-disable-next-line @typescript-eslint/no-extraneous-class +export class Msger { + static async openHttp(sthis: SuperThis, reqOpen: ReqOpen|undefined, urls: URI[], gi: GestaltItem): Promise> { + return Result.Ok(new HttpConnection(sthis, reqOpen, urls, gi)) + } + static async openWS(sthis: SuperThis, qOpen: ReqOpen, url: URI, gs: GestaltItem): Promise> { + let ws: WebSocket; + const { encode } = jsonEnDe(sthis); + url = url.build().setParam("reqOpen", sthis.txt.decode(encode(qOpen))).URI(); + if (runtimeFn().isNodeIsh) { + const { WebSocket }= await import('ws'); + ws = new WebSocket(url.toString()) as unknown as WebSocket; + } else { + ws = new WebSocket(url.toString()); + } + return Result.Ok(new WSConnection(sthis, { + reqOpen: qOpen, + ws, + }, gs)) + } + static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, igs: GestaltParam): Promise> { + // initial exchange with JSON encoding + const jsGI = defaultGestaltItem(sthis, { ...igs, ende: jsonEnDe(sthis) }); + const url = URI.from(curl) + /* + * request Gestalt with Http + */ + const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI); + if (rHC.isErr()) { + return rHC; + } + const hc = rHC.Ok(); + const resGestalt = await hc.request(buildReqGestalt(sthis, jsGI.gestalt), { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(resGestalt)) { + return Result.Err(new Error("Invalid Gestalt")); + } + await hc.close(); + const gt = resGestalt.gestalt + const gi = defaultGestaltItem(sthis, igs); + if (gt.protocolCapabilities.includes("reqRes") && !gt.protocolCapabilities.includes("stream")) { + return Msger.openHttp(sthis, qOpen, gi.gestalt.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), gi); + } + return Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(gi.gestalt.wsEndpoints)).URI(), gi); + } + + private constructor() { + /* */ + } + + // readonly logger: Logger; + // readonly url: URI; + // readonly qs: ReqRes; + // constructor(logger: Logger, url: URI, qs: ReqRes) { + // this.logger = logger; + // this.url = url; + // this.qs = qs; + // } + +} \ No newline at end of file diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts new file mode 100644 index 00000000..53f9d975 --- /dev/null +++ b/src/cloud/ws-connection.ts @@ -0,0 +1,215 @@ + +// export class WSAttachConnection implements Connection { +// readonly ws: WebSocket; +// // readonly key: ConnectionKey; +// readonly sthis: SuperThis; +// readonly logger: Logger; + +// // readonly errFns = new Map void>(); +// // readonly closeFns = new Map void>(); +// // readonly msgFns = new Map void>(); + +// readonly waitForTid: WSAttachable["waitForTid"]; +// constructor(sthis: SuperThis, ws: WebSocket, waitForTid: WSAttachable["waitForTid"], mec: MsgErrorClose) { +// this.ws = ws; +// // this.key = key; +// this.sthis = sthis; +// // this.onClose = onClose; +// this.logger = ensureLogger(sthis, "WSAttachConnection", { +// this: true, +// }); +// this.waitForTid = waitForTid; +// ws.onmessage = mec.msgFn +// ws.onopen = mec.openFn; +// ws.onerror = mec.errFn +// ws.onclose = mec.closeFn +// } + +// async close(): Promise { +// this.logger.Debug().Msg("close"); +// this.ws.close(); +// } + +// async request(req: Q, opts: RequestOpts): Promise> { +// opts = { +// ...{ +// timeout: 1000, +// }, +// ...opts, +// }; +// const future = new Future(); +// this.waitForTid.set(req.tid, { +// tid: req.tid, +// future, +// type: opts.waitType, +// }); +// const start = Date.now(); +// const logger = ensureLogger(this.sthis, "ConnectionImpl.request") +// .With() +// .Str("tid", req.tid) +// .Uint64("timeout", opts.timeout) +// .Ref("start", () => new Date().getTime() - start) +// .Any("req", req) +// .Logger(); +// this.ws.send(JSON.stringify(req)); +// const clean = setTimeout(() => { +// this.waitForTid.delete(req.tid); +// future.reject(new Error("Timeout")); +// }, opts.timeout); +// // add timeout handling +// logger.Debug().Msg("request-enter"); +// return future +// .asPromise() +// .finally(() => clearTimeout(clean)) +// .then((res) => { +// logger.Debug().Any("res", res).Msg("request-ok"); +// return Result.Ok(res as S); +// }) +// .catch((err) => { +// logger.Error().Err(err).Msg("request-error"); +// return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); +// }); +// } +// } + + +import { exception2Result, Future, Logger, Result } from "@adviser/cement"; +import { SuperThis, ensureLogger } from "@fireproof/core"; +import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; +import { GestaltItem, WaitForTid } from "./msg-request.js"; +import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, ResOpen, MsgIsResOpen } from "./msg-types.js"; +import { MsgConnection, OnMsgFn, UnReg } from "./msger.js"; + +export interface WSReqOpen { + readonly reqOpen: ReqOpen; + readonly ws: WebSocket; // this WS is opened with a specific URL-Param +} + +interface WSQSOpen extends WSReqOpen { + resOpen?: ResOpen; +} + +export class WSConnection implements MsgConnection { + readonly sthis: SuperThis; + readonly logger: Logger; + readonly gestaltItem: GestaltItem; + // readonly baseURI: URI; + readonly wqs: WSQSOpen; + + readonly #onMsg = new Map(); + readonly #onClose = new Map(); + + readonly waitForTid = new Map(); + opened = false; + + get conn(): ResOpen|undefined { + return this.wqs.resOpen + } + + constructor(sthis: SuperThis, wsq: WSReqOpen, gi: GestaltItem) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "WSConnection"); + this.gestaltItem = gi; + // this.baseURI = uri; + this.wqs = { ...wsq }; + } + + async start(): Promise> { + const onOpenFuture = new Future(); + this.wqs.ws.onopen = () => { + onOpenFuture.resolve(); + this.opened = true; + } + this.wqs.ws.onerror = (err) => { + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, this.logger.Error().Err(err).Msg("WS Error").AsError())); + } + this.wqs.ws.onmessage = (evt) => { + if (!this.opened) { + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, this.logger.Error().Msg("Received message before onOpen").AsError())); + } + this.#wsOnMessage(evt); + } + this.wqs.ws.onclose = () => { + this.opened = false; + this.close().catch((err) => this.logger.Error().Err(err).Msg("close error")); + } + /* wait for onOpen */ + await onOpenFuture.asPromise() + const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }) + if (!MsgIsResOpen(resOpen)) { + return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); + } + this.wqs.resOpen = resOpen; + return Result.Ok(undefined); + } + + readonly #wsOnMessage = async (event: MessageEvent) => { + const rMsg = await exception2Result(() => this.gestaltItem.ende.decode(event.data) as MsgBase); + if (rMsg.isErr()) { + this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); + return; + } + const msg = rMsg.Ok(); + const waitFor = this.waitForTid.get(msg.tid); + this.#onMsg.forEach((cb) => cb(msg)); + if (waitFor) { + if (MsgIsError(msg)) { + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else if (waitFor.waitFor(msg)) { + // what for a specific type + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } else { + // wild-card + this.waitForTid.delete(msg.tid); + waitFor.future.resolve(msg); + } + } + } + + async close(): Promise> { + this.#onClose.forEach((fn) => fn()); + this.#onClose.clear(); + this.#onMsg.clear(); + this.wqs.ws.close(); + return Result.Ok(undefined); + } + + toMsg(msg: WithErrorMsg): WithErrorMsg { + this.#onMsg.forEach((fn) => fn(msg)); + return msg; + } + + async sendMsg(msg: MsgBase): Promise { + this.wqs.ws.send(this.gestaltItem.ende.encode(msg)); + } + + onMsg(fn: OnMsgFn): UnReg { + const key = this.sthis.nextId().str + this.#onMsg.set(key, fn); + return () => this.#onMsg.delete(key); + } + + onClose(fn: UnReg): UnReg { + const key = this.sthis.nextId().str + this.#onClose.set(key, fn); + return () => this.#onClose.delete(key); + } + + async request(req: Q, opts: RequestOpts): Promise> { + if (!this.opened) { + return buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Msg("Connection not open").AsError()); + } + const future = new Future(); + this.waitForTid.set(req.tid, { tid: req.tid, future, waitFor: opts.waitFor }); + await this.sendMsg(req); + return future.asPromise() + } + + // toOnMessage(msg: WithErrorMsg): Result> { + // this.mec.msgFn?.(msg as unknown as MessageEvent); + // return Result.Ok(msg); + // } + +} diff --git a/src/coerce-binary.ts b/src/coerce-binary.ts index 170168f2..a04a9de6 100644 --- a/src/coerce-binary.ts +++ b/src/coerce-binary.ts @@ -1,5 +1,16 @@ -export function to_uint8(input: ArrayBuffer | ArrayBufferView | Uint8Array): Uint8Array { - if (input instanceof ArrayBuffer) { +export async function top_uint8(input: string | ArrayBuffer | ArrayBufferView | Uint8Array | SharedArrayBuffer | Blob): Promise { + if (input instanceof Blob) { + return new Uint8Array(await input.arrayBuffer()); + } + return to_uint8(input); +} + +export function to_uint8(input: string | ArrayBuffer | ArrayBufferView | Uint8Array | SharedArrayBuffer): Uint8Array { + if (typeof input === "string") { + // eslint-disable-next-line no-restricted-globals + return new TextEncoder().encode(input); + } + if (input instanceof ArrayBuffer || input instanceof SharedArrayBuffer) { return new Uint8Array(input); } From 12570409a3d7629dbb973d59eaac6a3504d3a7a6 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 23 Dec 2024 12:40:03 +0100 Subject: [PATCH 31/83] chore: added coderabbit --- .coderabbit.yaml | 15 ++ package.json | 4 +- pnpm-lock.yaml | 12 +- src/cloud/connection.test.ts | 346 +++++++++++++++++++++-------------- src/cloud/http-connection.ts | 29 +-- src/cloud/msg-processor.ts | 7 +- src/cloud/msg-request.ts | 11 +- src/cloud/msg-types.ts | 140 ++++++-------- src/cloud/msger.ts | 59 ++++-- src/cloud/ws-connection.ts | 45 +++-- 10 files changed, 388 insertions(+), 280 deletions(-) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..4a839e76 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +language: "en-US" +#early_access: false +reviews: + profile: "chill" + request_changes_workflow: false + high_level_summary: true + poem: false + review_status: false + collapse_walkthrough: false + auto_review: + enabled: true + drafts: true +chat: + auto_reply: true diff --git a/package.json b/package.json index d8ca37ab..dffface1 100644 --- a/package.json +++ b/package.json @@ -98,10 +98,10 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.43" + "@adviser/cement": "^0.2.44" }, "dependencies": { - "@adviser/cement": "^0.2.43", + "@adviser/cement": "^0.2.44", "@aws-sdk/client-s3": "^3.705.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78b82366..b79c0d6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.43 - version: 0.2.43(typescript@5.7.2) + specifier: ^0.2.44 + version: 0.2.44(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.705.0 version: 3.705.0 @@ -216,8 +216,8 @@ importers: packages: - '@adviser/cement@0.2.43': - resolution: {integrity: sha512-jBxv0bbzHODe7KrCrknQgy6g0KV/vq92olbXNgI+O87hiThALTv0FKfBgxY7NrMoHmEM4+89s+hHCuoH+l7NSg==} + '@adviser/cement@0.2.44': + resolution: {integrity: sha512-IxmNkCSpST2FBeHqhk1RGxcb6pF8FZMSFbPpNUi0Drx3v219gNl5Q1gOQ2TWPqblTvMO942MqSE/QlgEppshgg==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -4074,7 +4074,7 @@ packages: snapshots: - '@adviser/cement@0.2.43(typescript@5.7.2)': + '@adviser/cement@0.2.44(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4986,7 +4986,7 @@ snapshots: '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.2.43(typescript@5.7.2) + '@adviser/cement': 0.2.44(typescript@5.7.2) '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index a53f5540..54f5710e 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -1,5 +1,5 @@ -import { ensureSuperThis, SuperThis } from "@fireproof/core"; -import { Result, URI } from "@adviser/cement"; +import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; +import { Logger, Result, URI } from "@adviser/cement"; import { buildErrorMsg, buildReqGestalt, @@ -12,125 +12,246 @@ import { MsgIsResGestalt, MsgIsResOpen, MsgBase, - ReqOpen + Connection, + defaultGestalt, + MsgerParams, } from "./msg-types.js"; import { serve, ServerType } from '@hono/node-server' import { createNodeWebSocket } from '@hono/node-ws' import { Hono } from 'hono' -import { defaultGestaltItem, MsgConnection, Msger } from "./msger.js"; +import { defaultMsgParams, MsgConnection, Msger, } from "./msger.js"; import { top_uint8 } from "../coerce-binary.js"; -function dispatch(sthis: SuperThis, msg: MsgBase, send: (msg: MsgBase) => void) { - switch (true) { - case MsgIsReqGestalt(msg): - return send(buildResGestalt(msg, defaultGestaltItem(sthis, { id: "server", hasPersistent: true }).gestalt)); - case MsgIsReqOpen(msg): - return send(buildResOpen(msg)); - default: - // c.status(501) - return send(buildErrorMsg(sthis, sthis.logger, msg, new Error("unexpected message"))); +class Dispatcher { + readonly sthis: SuperThis + readonly logger: Logger + readonly conns = new Map() + + constructor(sthis: SuperThis) { + this.sthis = sthis + this.logger = ensureLogger(sthis, "Dispatcher") } -} -async function applyStart(prC: Promise>): Promise> { - const rC = await prC - if (rC.isErr()) { - return rC + addConn(aConn: Connection): Result { + const key = [aConn.key.ledgerName, aConn.key.tenantId].join(":") + let conn = this.conns.get(key) + if (!conn) { + if (this.conns.size > 0) { + return Result.Err("connection") + } + conn = { ...aConn, resId: this.sthis.nextId().str } + this.conns.set(key, conn) + } + if (conn.reqId !== aConn.reqId) { + return Result.Err("unexpected reqId") + } + return Result.Ok(conn) } - const c = rC.Ok() - const r = await c.start() - if (r.isErr()) { - return Result.Ok(c) + + dispatch(msg: MsgBase, send: (msg: MsgBase) => void) { + switch (true) { + case MsgIsReqGestalt(msg): + return send(buildResGestalt(msg, { + ...defaultMsgParams(this.sthis, { + hasPersistent: true + }), + ...msg.gestalt, + id: "server", + })); + case MsgIsReqOpen(msg): { + if (!msg.conn) { + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); + } + /* DDoS protection */ + const rConn = this.addConn(msg.conn) + if (rConn.isErr()) { + return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); + } + return send(buildResOpen(this.sthis, msg, rConn.Ok().resId)); + } + default: + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); + } } - return rC } -describe("Connection", () => { - const sthis = ensureSuperThis(); - const gsi = defaultGestaltItem(sthis, { id: "test", hasPersistent: true }) - let server: ServerType - let port: number - beforeAll(async () => { +class HonoServer { + readonly sthis: SuperThis + server?: ServerType + readonly gsi: MsgerParams + readonly logger: Logger + constructor(sthis: SuperThis, gsi: MsgerParams) { + this.sthis = sthis + this.logger = ensureLogger(sthis, "HonoServer") + this.gsi = gsi + } + async start(port: number): Promise { const app = new Hono() const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }) + const dispatcher = new Dispatcher(this.sthis) // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) app.put('/fp', async (c) => { const msg = await c.req.json() - return dispatch(sthis, msg, (msg) => c.json(msg)) + return dispatcher.dispatch(msg, (msg) => c.json(msg)) }) - app.get("/ws", upgradeWebSocket((c) => { - return { + app.get("/ws", async (c, next) => { + const reqOpen = JSON.parse(URI.from(c.req.url).getParam("reqOpen", "")) + if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { + c.status(401) + return c.json(buildErrorMsg(this.sthis, this.sthis.logger, reqOpen, + this.logger.Error().Msg("expected reqOpen").AsError() + )) + } + dispatcher.addConn(reqOpen.conn) + return upgradeWebSocket((_c) => ({ onOpen: () => { // console.log('Connection opened', c.req.url) }, onError: (error) => { - console.error(`WebSocket error: ${error}`) + this.logger.Error().Err(error).Msg("WebSocket error") }, - async onMessage(event, ws) { + onMessage: async (event, ws) => { // console.log('onMsg event', event, event.data); - dispatch(sthis, gsi.ende.decode(await top_uint8(event.data)), (msg) => { - const str = gsi.ende.encode(msg) + dispatcher.dispatch(this.gsi.ende.decode(await top_uint8(event.data)), (msg) => { + const str = this.gsi.ende.encode(msg) ws.send(str) }) }, onClose: () => { // console.log('Connection closed') }, - } + }))(c, next) }) - ) - - port = 1024 + Math.floor(Math.random() * (65536 - 1024)) - server = await new Promise((resolve) => { + this.server = await new Promise((resolve) => { const server = serve({ fetch: app.fetch, port }, () => resolve(server)) injectWebSocket(server) return server }) + return this + } + async close() { + await new Promise((resolve) => this.server?.close(resolve)) + } +} + +async function applyStart(prC: Promise>): Promise> { + const rC = await prC + if (rC.isErr()) { + return rC + } + const c = rC.Ok() + const r = await c.start() + if (r.isErr()) { + return Result.Err(r.Err()) + } + return rC +} + +describe("Connection", () => { + const sthis = ensureSuperThis(); + const gsi = defaultMsgParams(sthis, { hasPersistent: true }) + let server: HonoServer + const port = 1024 + Math.floor(Math.random() * (65536 - 1024)) + beforeAll(async () => { + server = await (new HonoServer(sthis, gsi)).start(port) }) afterAll(async () => { - await new Promise((resolve) => server.close(resolve)) + await server.close() }) - const qOpen = { - tid: "WS-OPEN", - version: "FP-MSG-1.0", - type: "reqOpen", + const qOpen = buildReqOpen(sthis, { key: { ledgerName: "test", tenantId: "test", }, - streamId: { - req: "req-open-test", - } - } satisfies ReqOpen + reqId: "req-open-test", + }) + + const exGt = { + my: defaultGestalt({ id: "test" }), + remote: defaultGestalt({ id: "server" }), + } + + for (const style of [{ + name: "HTTP", + url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), + open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port - 1}/fp`)], { + ...gsi, + protocol: "http", + timeout: 100 + }, exGt) + }, { + name: "WS", + url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), + open: () => Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port - 1}/ws`), { + ...gsi, + protocol: "ws", + timeout: 100 + }, exGt) + }]) { + it(`${style.name} - conn refused`, async () => { + const rC = await applyStart(style.open()) + expect(rC.isErr()).toBeTruthy() + expect(rC.Err().message).toMatch(/ECONNREFUSED/) + }) + } + + for (const style of [{ + name: "HTTP", + url: () => URI.from(`http://4.7.1.1:${port - 1}/fp`), + open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://4.7.1.1:${port - 1}/fp`)], { + ...gsi, + protocol: "http", + timeout: 100 + }, exGt) + }, { + name: "WS", + url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), + open: () => Msger.openWS(sthis, qOpen, URI.from(`http://4.7.1.1:${port - 1}/ws`), { + ...gsi, + protocol: "ws", + timeout: 100 + }, exGt) + }]) { + it(`${style.name} - timeout`, async () => { + const rC = await applyStart(style.open()) + expect(rC.isErr()).toBeTruthy() + expect(rC.Err().message).toMatch(/Timeout/i) + }) + } for (const style of [{ name: "HTTP", url: () => URI.from(`http://localhost:${port}/fp`), - open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], gsi)) + open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], { + ...gsi, + protocol: "http", + }, exGt)) }, { name: "WS", url: () => URI.from(`http://localhost:${port}/ws`), - open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), gsi)) + open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), { + ...gsi, + protocol: "ws", + }, exGt)) }]) { describe(style.name, () => { - let c: MsgConnection beforeEach(async () => { const rC = await style.open() expect(rC.isOk()).toBeTruthy() c = rC.Ok() expect(c.conn).toEqual({ - "key": { - "ledgerName": "test", - "tenantId": "test", - }, - "streamId": { - "req": "req-open-test", - "res": "res-req-open-test", + conn: { + "key": { + "ledgerName": "test", + "tenantId": "test", + }, + "reqId": "req-open-test", + "resId": c.conn?.conn.resId, }, - "tid": "WS-OPEN", + "tid": qOpen.tid, "type": "resOpen", "version": "FP-MSG-1.0", }) @@ -157,93 +278,25 @@ describe("Connection", () => { }) }) it("gestalt url http", async () => { - const gsi = defaultGestaltItem(sthis, { id: "test" }) - const req = buildReqGestalt(sthis, gsi.gestalt) + const msgP = defaultMsgParams(sthis, { }) + const req = buildReqGestalt(sthis, defaultGestalt({ id: "test", ...msgP })) const r = await c.request(req, { waitFor: MsgIsResGestalt }) if (!MsgIsResGestalt(r)) { assert.fail("expected MsgError", JSON.stringify(r)) } - expect(r).toEqual({ - "gestalt": { - "auth": [], - "encodings": [ - "JSON", - ], - "eventTypes": [ - "updateMeta", - ], - "httpEndpoints": [ - "/fp", - ], - "id": "server", - "protocolCapabilities": [ - "stream", - "reqRes", - ], - "reqTypes": [ - "reqOpen", - "reqGestalt", - "reqSubscribeMeta", - "reqPutMeta", - "reqGetMeta", - "reqDelMeta", - "reqPutData", - "reqGetData", - "reqDelData", - "reqPutWAL", - "reqGetWAL", - "reqDelWAL", - "reqUpdateMeta", - ], - "requiresAuth": false, - "resTypes": [ - "resOpen", - "resGestalt", - "resSubscribeMeta", - "resPutMeta", - "resGetMeta", - "resDelMeta", - "resPutData", - "resGetData", - "resDelData", - "resPutWAL", - "resGetWAL", - "resDelWAL", - "updateMeta", - ], - "storeTypes": [ - "meta", - "data", - "wal", - ], - "wsEndpoints": [ - "/ws", - ], - }, - "tid": req.tid, - "type": "resGestalt", - "version": "FP-MSG-1.0", - }) + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote) }) it("openConnection", async () => { const req = buildReqOpen(sthis, { - tenantId: "tenant", - ledgerName: "ledger", - }, "open-test") + ...c.conn?.conn as Connection, + }) const r = await c.request(req, { waitFor: MsgIsResOpen }) if (!MsgIsResOpen(r)) { - assert.fail("expected MsgError") + assert.fail(JSON.stringify(r)) } expect(r).toEqual({ - key: { - "ledgerName": "ledger", - "tenantId": "tenant", - }, - streamId: { - "req": "open-test", - "res": "res-open-test", - }, + conn: c.conn?.conn, tid: req.tid, "type": "resOpen", "version": "FP-MSG-1.0", @@ -251,4 +304,23 @@ describe("Connection", () => { }) }) } -}) \ No newline at end of file +}) + +// describe("connection -- http", async () => { +// const sthis = ensureSuperThis(); +// const port = 1024 + Math.floor(Math.random() * (65536 - 1024)) +// const gsi = defaultGestaltItem(sthis, { id: "test", hasPersistent: true, protocol: "http" }) +// beforeAll(async () => { +// }) +// afterAll(async () => { +// }) +// it("open", async () => { +// Msger.open(sthis, URI.from(`http://localhost:${port}`), buildReqOpen(sthis, { +// key: { +// ledgerName: "test", +// tenantId: "test", +// }, +// reqId: "req-open-test", +// }), gsi) +// }) +// }) \ No newline at end of file diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index d8e6e0ef..283c0211 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -1,14 +1,16 @@ import { Logger, Result, URI, exception2Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { GestaltItem, selectRandom } from "./msg-request.js"; -import { MsgBase, MsgIsResOpen, ReqOpen, ResOpen, buildErrorMsg } from "./msg-types.js"; -import { MsgConnection, OnMsgFn, UnReg } from "./msger.js"; +import { selectRandom } from "./msg-request.js"; +import { MsgBase, MsgIsResOpen, ReqOpen, ResOpen, buildErrorMsg, MsgerParams } from "./msg-types.js"; +import { ExchangedGestalt, MsgConnection, OnMsgFn, timeout, UnReg } from "./msger.js"; export class HttpConnection implements MsgConnection { readonly sthis: SuperThis; readonly logger: Logger; - readonly gestalt: GestaltItem; + readonly msgParam: MsgerParams; + readonly exchangedGestalt: ExchangedGestalt; + readonly baseURIs: URI[]; readonly qsOpen: { @@ -22,19 +24,20 @@ export class HttpConnection implements MsgConnection { readonly #onMsg = new Map(); - constructor(sthis: SuperThis, reqOpen: ReqOpen | undefined, uris: URI[], gi: GestaltItem) { + constructor(sthis: SuperThis, reqOpen: ReqOpen | undefined, uris: URI[], msgP: MsgerParams, exGestalt: ExchangedGestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "HttpConnection"); - this.gestalt = gi; + this.msgParam = msgP; this.baseURIs = uris; this.qsOpen = { req: reqOpen }; + this.exchangedGestalt = exGestalt } async start(): Promise> { if (this.qsOpen.req) { const sOpen = await this.request(this.qsOpen.req, { waitFor: MsgIsResOpen }) if (!MsgIsResOpen(sOpen)) { - return Result.Ok(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); + return Result.Err(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); } this.qsOpen.res = sOpen; } @@ -59,9 +62,9 @@ export class HttpConnection implements MsgConnection { async request(req: Q, _opts: RequestOpts): Promise> { const headers = new Headers(); - headers.append("Content-Type", this.gestalt.mime); - headers.append("Accept", this.gestalt.mime); - const rReqBody = exception2Result(() => this.gestalt.ende.encode(req)); + headers.append("Content-Type", this.msgParam.mime); + headers.append("Accept", this.msgParam.mime); + const rReqBody = exception2Result(() => this.msgParam.ende.encode(req)); if (rReqBody.isErr()) { return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Err(rReqBody.Err()).Any("req", req).Msg("encode error").AsError() @@ -70,11 +73,11 @@ export class HttpConnection implements MsgConnection { headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); const url = selectRandom(this.baseURIs) this.logger.Debug().Url(url).Any("body", req).Msg("request"); - const rRes = await exception2Result(() => fetch(url.toString(), { + const rRes = await exception2Result(() => timeout(this.msgParam.timeout, fetch(url.toString(), { method: "PUT", headers, body: rReqBody.Ok(), - })); + }))); this.logger.Debug().Url(url).Any("body", rRes).Msg("response"); if (rRes.isErr()) { return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, @@ -91,7 +94,7 @@ export class HttpConnection implements MsgConnection { await res.text())); } const data = new Uint8Array(await res.arrayBuffer()); - const ret = await exception2Result(async () => this.gestalt.ende.decode(data) as S); + const ret = await exception2Result(async () => this.msgParam.ende.decode(data) as S); if (ret.isErr()) { return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Err(ret.Err()).Msg("decode error").AsError(), diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts index 13e88a23..34fb56c6 100644 --- a/src/cloud/msg-processor.ts +++ b/src/cloud/msg-processor.ts @@ -31,6 +31,7 @@ import { ResPutMeta, } from "./msg-types.js"; import { calculatePreSignedUrl } from "./pre-signed-url.js"; +import { SuperThis } from "@fireproof/core"; export type WithErrorMsg = T | ErrorMsg @@ -79,10 +80,12 @@ export abstract class MsgProcessorBase readonly logger: Logger; readonly serverId: string readonly ctx: O - constructor(logger: Logger, ctx: O, serverId: string) { + readonly sthis: SuperThis + constructor(sthis: SuperThis, logger: Logger, ctx: O, serverId: string) { this.serverId = serverId this.logger = logger this.ctx = ctx + this.sthis = sthis } async dispatch( @@ -91,7 +94,7 @@ export abstract class MsgProcessorBase ): Promise> { const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); if (rReqMsg.isErr()) { - const errMsg = buildErrorMsg(this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); + const errMsg = buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); return { req: errMsg as unknown as Q, res: errMsg, diff --git a/src/cloud/msg-request.ts b/src/cloud/msg-request.ts index e87b2f85..194629c4 100644 --- a/src/cloud/msg-request.ts +++ b/src/cloud/msg-request.ts @@ -34,12 +34,13 @@ export interface HttpConnectionParams { readonly uniqServerId?: string; } -export interface GestaltItem { +export interface MsgerParams { readonly ende: EnDeCoder; readonly mime: string; readonly auth?: AuthType; readonly hasPersistent?: boolean; - readonly gestalt: Gestalt; + readonly protocol: "http" | "ws"; + readonly timeout: number; // msec } export type RequestFN = (req: Q, opts: RequestOpts) => Promise> @@ -66,7 +67,7 @@ export function encoded(logger: Logger, g: "JSON" | "CBOR") { const getGestalts = new KeyedResolvOnce(); -async function fetchGestalt(fgp: FetchGestaltParams): Promise { +async function fetchGestalt(fgp: FetchGestaltParams): Promise { return getGestalts.get(fgp.gestaltURL.toString()).once(async () => { const conn = await fgp.getConn(); const rGestalt = await conn.request({ @@ -128,10 +129,10 @@ export interface Attachable { } export class WSAttachable implements Attachable { - readonly gestalt: GestaltItem + readonly gestalt: MsgerParams readonly sthis: SuperThis readonly waitForTid = new Map(); - constructor(sthis: SuperThis, gestalt: GestaltItem) { + constructor(sthis: SuperThis, gestalt: MsgerParams) { this.gestalt = gestalt this.sthis = sthis } diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 8ef34507..05269fa6 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,12 +1,12 @@ import { CRDTEntry, Logger, SuperThis } from "@fireproof/core"; -import { GestaltItem } from "./msg-request.js"; +import { EnDeCoder } from "./msg-request.js"; -export interface ConnId { - readonly connId: string; -} +export const VERSION = "FP-MSG-1.0"; +// export interface ConnId { +// readonly connId: string; +// } // type AddConnId = Omit & ConnId & { readonly type: N }; - interface NextId { readonly nextId: SuperThis["nextId"]; } @@ -22,21 +22,40 @@ export interface UCanAuth { }; } +export interface ConnectionKey { + readonly tenantId: string; + readonly ledgerName: string; +} + +export interface Connection { + readonly key: ConnectionKey; + readonly reqId: string; + readonly resId: string; +} + +export interface Connected { + readonly conn: Connection; +} + export interface MsgBase { readonly tid: string; readonly type: string; readonly version: string; readonly auth?: AuthType; + readonly conn?: Connection; } + export interface ErrorMsg extends MsgBase { readonly type: "error"; readonly message: string; readonly body?: string; readonly stack?: string[]; } + export function MsgIsError(rq: MsgBase): rq is ErrorMsg { return rq.type === "error"; } + export function MsgIsQSError(rq: ReqRes): rq is ReqRes { return rq.res.type === "error" || rq.req.type === "error"; } @@ -44,10 +63,7 @@ export function MsgIsQSError(rq: ReqRes): rq is ReqRes & { readonly id: string }; +export type GestaltParam = Partial & { readonly id: string }; export function defaultGestalt(gs: GestaltParam & { hasPersitance?: boolean; + protocol?: "http" | "ws"; }): Gestalt { const hasPersitance = gs.hasPersitance || false; delete gs.hasPersitance; @@ -138,9 +164,9 @@ export function defaultGestalt(gs: GestaltParam & { storeTypes: ["meta", "data", "wal"], id: gs.id, httpEndpoints: ["/fp"], - wsEndpoints: ["/ws"], + wsEndpoints: gs.protocol === 'ws' ? ["/ws"] : [], encodings: ["JSON"], - protocolCapabilities: ["stream", "reqRes"], + protocolCapabilities: gs.protocol === 'ws' ? ["stream"] : ["reqRes"], auth: [], requiresAuth: false, data: hasPersitance ? { @@ -236,23 +262,23 @@ export function MsgIsResGestalt(msg: MsgBase): msg is ResGestalt { return msg.type === "resGestalt"; } +export interface ReqOpenConnection { + readonly key: ConnectionKey; + readonly reqId?: string; +} export interface ReqOpen extends MsgBase { readonly type: "reqOpen"; - readonly key: ConnectionKey; - readonly streamId: { - readonly req: string; - }; } -export function buildReqOpen(sthis: NextId, key: ConnectionKey, reqStreamId = sthis.nextId().str): ReqOpen { +export function buildReqOpen(sthis: NextId, conn: ReqOpenConnection): ReqOpen { return { tid: sthis.nextId().str, type: "reqOpen", version: VERSION, - key, - streamId: { - req: reqStreamId + conn: { + ...conn as Connection, + reqId: conn.reqId || sthis.nextId().str } }; } @@ -263,20 +289,19 @@ export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { export interface ResOpen extends MsgBase { readonly type: "resOpen"; - readonly key: ConnectionKey; - readonly streamId: { - readonly req: string; - readonly res: string; - }; + readonly conn: Connection; } -export function buildResOpen(req: ReqOpen, resStreamId = 'res-'+req.streamId.req): ResOpen { +export function buildResOpen(sthis: NextId, req: ReqOpen, resStreamId?: string): ResOpen { + if (!(req.conn && req.conn.reqId)) { + throw new Error("req.conn.reqId is required"); + } return { ...req, type: "resOpen", - streamId: { - ...req.streamId, - res: resStreamId + conn: { + ...req.conn as Connection, + resId: resStreamId || sthis.nextId().str } }; } @@ -285,56 +310,6 @@ export function MsgIsResOpen(msg: MsgBase): msg is ResOpen { return msg.type === "resOpen"; } - -// /* -// * This behavios somekind of strange if it comes to WebSocket -// * if the requesting Gestalt wants http it responds with http -// * if the requesting Gestalt wants WebSocket and the requested -// * is capable of WebSocket this response is sent via WebSocket -// */ -// export interface ResOpen extends MsgBase { -// readonly type: "resOpen"; -// readonly key: ConnectionKey; -// readonly connId: string; -// // reguester Gestalt -// readonly gestalt: Gestalt; -// } - -// export function buildReqOpen(sthis: NextId, key: ConnectionKey, gestalt: Gestalt): ReqOpen { -// return { -// tid: sthis.nextId().str, -// type: "reqOpen", -// version: VERSION, -// key, -// gestalt, -// }; -// } - -// export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { -// return msg.type === "reqOpen"; -// } - -// export function buildResOpen(req: ReqOpen, connId: string, gestalt: Gestalt): ResOpen { -// return { -// tid: req.tid, -// type: "resOpen", -// version: VERSION, -// key: req.key, -// connId, -// gestalt, -// }; -// } - -// export function MsgIsResOpen(msg: MsgBase): msg is ResOpen { -// return msg.type === "resOpen"; -// } - -// export interface ConnectionKey { -// // readonly protocol: "ws" | "wss"; // ws or wss -// readonly tenantId: string; -// readonly name: string; -// } - export interface SignedUrlParam extends ConnectionKey { readonly path?: string; readonly method: HttpMethods; @@ -372,7 +347,6 @@ export interface ReqSignedUrlParam { }; } -const VERSION = "FP-MSG-1.0"; /* Signed URL */ @@ -474,15 +448,15 @@ export function buildReqSubscriptMeta(sthis: NextId, ck: ConnectionKey, subscrib export interface ResSubscribeMeta extends MsgBase { readonly type: "resSubscribeMeta"; readonly subscriberId: string; - readonly connId: string; + readonly conn: Connection; readonly key: ConnectionKey; } -export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: ConnId): ResSubscribeMeta { +export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: Connection): ResSubscribeMeta { return { tid: req.tid, type: "resSubscribeMeta", - connId: ctx.connId, + conn: ctx, subscriberId: req.subscriberId, key: req.key, version: VERSION, diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index b68a5d17..fb6d87ac 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -1,9 +1,9 @@ import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; -import { buildReqGestalt, defaultGestalt, GestaltParam, MsgBase, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; +import { buildReqGestalt, defaultGestalt, Gestalt, GestaltParam, MsgBase, MsgerParams, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; import { HttpConnection } from "./http-connection.js"; -import { EnDeCoder, GestaltItem, selectRandom } from "./msg-request.js"; +import { EnDeCoder, selectRandom } from "./msg-request.js"; import { WSConnection } from "./ws-connection.js"; // const headers = { @@ -11,13 +11,31 @@ import { WSConnection } from "./ws-connection.js"; // "Accept": "application/json", // }; +export function timeout(ms: number, promise: Promise): Promise { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + reject(new Error(`TIMEOUT after ${ms}ms`)) + }, ms) + promise + .then(resolve) + .catch(reject) + .finally(() => clearTimeout(timer)) + }) + } + export type OnMsgFn = (msg: WithErrorMsg) => void export type UnReg = () => void +export interface ExchangedGestalt { + readonly my: Gestalt; + readonly remote: Gestalt; +} + export interface MsgConnection { // readonly ws: WebSocket; // readonly params: ConnectionKey; conn?: ResOpen; + readonly exchangedGestalt: ExchangedGestalt; request(req: Q, opts: RequestOpts): Promise> start(): Promise>; close(): Promise>; @@ -31,20 +49,26 @@ function jsonEnDe(sthis: SuperThis) { } satisfies EnDeCoder; } -export function defaultGestaltItem(sthis: SuperThis, igs: GestaltParam): GestaltItem { +export function defaultMsgParams(sthis: SuperThis, igs: Partial): MsgerParams { return { ende: igs.ende || jsonEnDe(sthis), mime: igs.mime || "application/json", - gestalt: defaultGestalt(igs), - } satisfies GestaltItem; + protocol: igs.protocol || "http", + timeout: igs.timeout || 3000, + } satisfies MsgerParams; } +export interface OpenParams { + readonly timeout: number; +} + + // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Msger { - static async openHttp(sthis: SuperThis, reqOpen: ReqOpen|undefined, urls: URI[], gi: GestaltItem): Promise> { - return Result.Ok(new HttpConnection(sthis, reqOpen, urls, gi)) + static async openHttp(sthis: SuperThis, reqOpen: ReqOpen|undefined, urls: URI[], msgP: MsgerParams, exGestalt: ExchangedGestalt): Promise> { + return Result.Ok(new HttpConnection(sthis, reqOpen, urls, msgP, exGestalt)); } - static async openWS(sthis: SuperThis, qOpen: ReqOpen, url: URI, gs: GestaltItem): Promise> { + static async openWS(sthis: SuperThis, qOpen: ReqOpen, url: URI, msgP: MsgerParams, exGestalt: ExchangedGestalt): Promise> { let ws: WebSocket; const { encode } = jsonEnDe(sthis); url = url.build().setParam("reqOpen", sthis.txt.decode(encode(qOpen))).URI(); @@ -57,31 +81,32 @@ export class Msger { return Result.Ok(new WSConnection(sthis, { reqOpen: qOpen, ws, - }, gs)) + }, msgP, exGestalt)) } static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, igs: GestaltParam): Promise> { // initial exchange with JSON encoding - const jsGI = defaultGestaltItem(sthis, { ...igs, ende: jsonEnDe(sthis) }); + const jsGI = defaultMsgParams(sthis, { ...igs, ende: jsonEnDe(sthis) }); const url = URI.from(curl) + const gs = defaultGestalt({id: "FP-Universal-Client"}); /* * request Gestalt with Http */ - const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI); + const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI, { my: gs, remote: gs }); if (rHC.isErr()) { return rHC; } const hc = rHC.Ok(); - const resGestalt = await hc.request(buildReqGestalt(sthis, jsGI.gestalt), { waitFor: MsgIsResGestalt }); + const resGestalt = await hc.request(buildReqGestalt(sthis, gs), { waitFor: MsgIsResGestalt }); if (!MsgIsResGestalt(resGestalt)) { return Result.Err(new Error("Invalid Gestalt")); } await hc.close(); - const gt = resGestalt.gestalt - const gi = defaultGestaltItem(sthis, igs); - if (gt.protocolCapabilities.includes("reqRes") && !gt.protocolCapabilities.includes("stream")) { - return Msger.openHttp(sthis, qOpen, gi.gestalt.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), gi); + const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt; + const msgP = defaultMsgParams(sthis, igs); + if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) { + return Msger.openHttp(sthis, qOpen, exGt.remote.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), msgP, exGt); } - return Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(gi.gestalt.wsEndpoints)).URI(), gi); + return Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt); } private constructor() { diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index 53f9d975..e5483dca 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -76,9 +76,9 @@ import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { GestaltItem, WaitForTid } from "./msg-request.js"; -import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, ResOpen, MsgIsResOpen } from "./msg-types.js"; -import { MsgConnection, OnMsgFn, UnReg } from "./msger.js"; +import { WaitForTid } from "./msg-request.js"; +import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, ResOpen, MsgIsResOpen, MsgerParams } from "./msg-types.js"; +import { ExchangedGestalt, MsgConnection, OnMsgFn, UnReg } from "./msger.js"; export interface WSReqOpen { readonly reqOpen: ReqOpen; @@ -92,7 +92,8 @@ interface WSQSOpen extends WSReqOpen { export class WSConnection implements MsgConnection { readonly sthis: SuperThis; readonly logger: Logger; - readonly gestaltItem: GestaltItem; + readonly msgP: MsgerParams; + readonly exchangedGestalt: ExchangedGestalt; // readonly baseURI: URI; readonly wqs: WSQSOpen; @@ -106,22 +107,29 @@ export class WSConnection implements MsgConnection { return this.wqs.resOpen } - constructor(sthis: SuperThis, wsq: WSReqOpen, gi: GestaltItem) { + constructor(sthis: SuperThis, wsq: WSReqOpen, msgP: MsgerParams, exGestalt: ExchangedGestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "WSConnection"); - this.gestaltItem = gi; - // this.baseURI = uri; + this.msgP = msgP; + this.exchangedGestalt = exGestalt; this.wqs = { ...wsq }; } async start(): Promise> { - const onOpenFuture = new Future(); + const onOpenFuture: Future> = new Future>(); + const timer = setTimeout(() => { + const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError() + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, err)); + onOpenFuture.resolve(Result.Err(err)); + }, this.msgP.timeout); this.wqs.ws.onopen = () => { - onOpenFuture.resolve(); + onOpenFuture.resolve(Result.Ok(undefined)); this.opened = true; } - this.wqs.ws.onerror = (err) => { - this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, this.logger.Error().Err(err).Msg("WS Error").AsError())); + this.wqs.ws.onerror = (ierr) => { + const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError() + onOpenFuture.resolve(Result.Err(err)); + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal", conn: this.conn } as MsgBase, err)); } this.wqs.ws.onmessage = (evt) => { if (!this.opened) { @@ -131,10 +139,17 @@ export class WSConnection implements MsgConnection { } this.wqs.ws.onclose = () => { this.opened = false; - this.close().catch((err) => this.logger.Error().Err(err).Msg("close error")); + this.close().catch((ierr) => { + const err = this.logger.Error().Err(ierr).Msg("close error").AsError() + onOpenFuture.resolve(Result.Err(err)); + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, err)); + }); } /* wait for onOpen */ - await onOpenFuture.asPromise() + const rOpen = await onOpenFuture.asPromise().finally(() => clearTimeout(timer)); + if (rOpen.isErr()) { + return rOpen; + } const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }) if (!MsgIsResOpen(resOpen)) { return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); @@ -144,7 +159,7 @@ export class WSConnection implements MsgConnection { } readonly #wsOnMessage = async (event: MessageEvent) => { - const rMsg = await exception2Result(() => this.gestaltItem.ende.decode(event.data) as MsgBase); + const rMsg = await exception2Result(() => this.msgP.ende.decode(event.data) as MsgBase); if (rMsg.isErr()) { this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); return; @@ -182,7 +197,7 @@ export class WSConnection implements MsgConnection { } async sendMsg(msg: MsgBase): Promise { - this.wqs.ws.send(this.gestaltItem.ende.encode(msg)); + this.wqs.ws.send(this.msgP.ende.encode(msg)); } onMsg(fn: OnMsgFn): UnReg { From 4cecd0ec7909cccc5c336aafdd446543d6d3f726 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 23 Dec 2024 15:40:46 +0100 Subject: [PATCH 32/83] wip --- src/cloud/connection.test.ts | 356 +++++++++++++++++------------------ src/cloud/msg-request.ts | 9 - src/cloud/msger.ts | 22 ++- 3 files changed, 196 insertions(+), 191 deletions(-) diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 54f5710e..47b5d466 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -15,21 +15,26 @@ import { Connection, defaultGestalt, MsgerParams, + Gestalt, + ReqOpen, } from "./msg-types.js"; import { serve, ServerType } from '@hono/node-server' import { createNodeWebSocket } from '@hono/node-ws' import { Hono } from 'hono' -import { defaultMsgParams, MsgConnection, Msger, } from "./msger.js"; +import { applyStart, defaultMsgParams, MsgConnection, Msger, } from "./msger.js"; import { top_uint8 } from "../coerce-binary.js"; +import exp from "constants"; class Dispatcher { readonly sthis: SuperThis readonly logger: Logger readonly conns = new Map() + readonly gestalt: Gestalt - constructor(sthis: SuperThis) { + constructor(sthis: SuperThis, gestalt: Gestalt) { this.sthis = sthis this.logger = ensureLogger(sthis, "Dispatcher") + this.gestalt = gestalt } addConn(aConn: Connection): Result { @@ -51,13 +56,7 @@ class Dispatcher { dispatch(msg: MsgBase, send: (msg: MsgBase) => void) { switch (true) { case MsgIsReqGestalt(msg): - return send(buildResGestalt(msg, { - ...defaultMsgParams(this.sthis, { - hasPersistent: true - }), - ...msg.gestalt, - id: "server", - })); + return send(buildResGestalt(msg, this.gestalt)); case MsgIsReqOpen(msg): { if (!msg.conn) { return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); @@ -78,19 +77,21 @@ class Dispatcher { class HonoServer { readonly sthis: SuperThis server?: ServerType - readonly gsi: MsgerParams + readonly msgP: MsgerParams + readonly gestalt: Gestalt readonly logger: Logger - constructor(sthis: SuperThis, gsi: MsgerParams) { + constructor(sthis: SuperThis, msgP: MsgerParams, gestalt: Gestalt) { this.sthis = sthis this.logger = ensureLogger(sthis, "HonoServer") - this.gsi = gsi + this.msgP = msgP + this.gestalt = gestalt } async start(port: number): Promise { const app = new Hono() const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }) - const dispatcher = new Dispatcher(this.sthis) // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) + const dispatcher = new Dispatcher(this.sthis, this.gestalt) app.put('/fp', async (c) => { const msg = await c.req.json() return dispatcher.dispatch(msg, (msg) => c.json(msg)) @@ -103,6 +104,7 @@ class HonoServer { this.logger.Error().Msg("expected reqOpen").AsError() )) } + const dispatcher = new Dispatcher(this.sthis, this.gestalt) dispatcher.addConn(reqOpen.conn) return upgradeWebSocket((_c) => ({ onOpen: () => { @@ -113,8 +115,8 @@ class HonoServer { }, onMessage: async (event, ws) => { // console.log('onMsg event', event, event.data); - dispatcher.dispatch(this.gsi.ende.decode(await top_uint8(event.data)), (msg) => { - const str = this.gsi.ende.encode(msg) + dispatcher.dispatch(this.msgP.ende.decode(await top_uint8(event.data)), (msg) => { + const str = this.msgP.ende.encode(msg) ws.send(str) }) }, @@ -135,31 +137,78 @@ class HonoServer { } } -async function applyStart(prC: Promise>): Promise> { - const rC = await prC - if (rC.isErr()) { - return rC + +function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt({ id: "HTTP-server", hasPersistent: true, protocol: "http" }) + const exGt = { my, remote } + return { + name: "HTTP", + remoteGestalt: remote, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/fp`), + open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], { + ...msgP, + protocol: "http", + timeout: 1000 + }, exGt)) + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), + open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port - 1}/fp`)], { + ...msgP, + protocol: "http", + timeout: 1000 + }, exGt) + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port}/fp`), + open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://4.7.1.1:${port}/fp`)], { + ...msgP, + protocol: "http", + timeout: 500 + }, exGt) + } } - const c = rC.Ok() - const r = await c.start() - if (r.isErr()) { - return Result.Err(r.Err()) +} + +function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt({ id: "WS-server", hasPersistent: true, protocol: "ws" }) + const exGt = { my, remote } + return { + name: "WS", + remoteGestalt: remote, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/ws`), + open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), { + ...msgP, + protocol: "ws", + timeout: 1000 + }, exGt)) + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), + open: () => Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port - 1}/ws`), { + ...msgP, + protocol: "ws", + timeout: 1000 + }, exGt) + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), + open: () => Msger.openWS(sthis, qOpen, URI.from(`http://4.7.1.1:${port - 1}/ws`), { + ...msgP, + protocol: "ws", + timeout: 500 + }, exGt) + } } - return rC } + describe("Connection", () => { const sthis = ensureSuperThis(); - const gsi = defaultMsgParams(sthis, { hasPersistent: true }) - let server: HonoServer + const msgP = defaultMsgParams(sthis, { hasPersistent: true }) const port = 1024 + Math.floor(Math.random() * (65536 - 1024)) - beforeAll(async () => { - server = await (new HonoServer(sthis, gsi)).start(port) - }) - afterAll(async () => { - await server.close() - }) - const qOpen = buildReqOpen(sthis, { key: { ledgerName: "test", @@ -167,160 +216,111 @@ describe("Connection", () => { }, reqId: "req-open-test", }) + const my = defaultGestalt({ id: "test" }) + for (const style of [httpStyle(sthis, port, msgP, qOpen, my)/*, wsStyle(sthis, port, msgP, qOpen, my)*/]) { + describe(style.name, () => { + let server: HonoServer + beforeAll(async () => { + server = await (new HonoServer(sthis, msgP, style.remoteGestalt)).start(port) + }) + afterAll(async () => { + await server.close() + }) + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()) + expect(rC.isErr()).toBeTruthy() + expect(rC.Err().message).toMatch(/ECONNREFUSED/) + }) - const exGt = { - my: defaultGestalt({ id: "test" }), - remote: defaultGestalt({ id: "server" }), - } - - for (const style of [{ - name: "HTTP", - url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), - open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port - 1}/fp`)], { - ...gsi, - protocol: "http", - timeout: 100 - }, exGt) - }, { - name: "WS", - url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), - open: () => Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port - 1}/ws`), { - ...gsi, - protocol: "ws", - timeout: 100 - }, exGt) - }]) { - it(`${style.name} - conn refused`, async () => { - const rC = await applyStart(style.open()) - expect(rC.isErr()).toBeTruthy() - expect(rC.Err().message).toMatch(/ECONNREFUSED/) - }) - } - - for (const style of [{ - name: "HTTP", - url: () => URI.from(`http://4.7.1.1:${port - 1}/fp`), - open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://4.7.1.1:${port - 1}/fp`)], { - ...gsi, - protocol: "http", - timeout: 100 - }, exGt) - }, { - name: "WS", - url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), - open: () => Msger.openWS(sthis, qOpen, URI.from(`http://4.7.1.1:${port - 1}/ws`), { - ...gsi, - protocol: "ws", - timeout: 100 - }, exGt) - }]) { - it(`${style.name} - timeout`, async () => { - const rC = await applyStart(style.open()) - expect(rC.isErr()).toBeTruthy() - expect(rC.Err().message).toMatch(/Timeout/i) - }) - } + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()) + expect(rC.isErr()).toBeTruthy() + expect(rC.Err().message).toMatch(/Timeout/i) + }) - for (const style of [{ - name: "HTTP", - url: () => URI.from(`http://localhost:${port}/fp`), - open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], { - ...gsi, - protocol: "http", - }, exGt)) - }, { - name: "WS", - url: () => URI.from(`http://localhost:${port}/ws`), - open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), { - ...gsi, - protocol: "ws", - }, exGt)) - }]) { - describe(style.name, () => { - let c: MsgConnection - beforeEach(async () => { - const rC = await style.open() - expect(rC.isOk()).toBeTruthy() - c = rC.Ok() - expect(c.conn).toEqual({ - conn: { - "key": { - "ledgerName": "test", - "tenantId": "test", + describe(`connection`, () => { + let c: MsgConnection + beforeEach(async () => { + const rC = await style.ok.open() + expect(rC.isOk()).toBeTruthy() + c = rC.Ok() + expect(c.conn).toEqual({ + conn: { + "key": { + "ledgerName": "test", + "tenantId": "test", + }, + "reqId": "req-open-test", + "resId": c.conn?.conn.resId, }, - "reqId": "req-open-test", - "resId": c.conn?.conn.resId, - }, - "tid": qOpen.tid, - "type": "resOpen", - "version": "FP-MSG-1.0", + "tid": qOpen.tid, + "type": "resOpen", + "version": "FP-MSG-1.0", + }) + }) + afterEach(async () => { + await c.close() }) - }) - afterEach(async () => { - await c.close() - }) - it("kaputt url http", async () => { - const r = await c.request({ - tid: "test", - type: "kaputt", - version: "FP-MSG-1.0", - }, { waitFor: () => true }) - if (!MsgIsError(r)) { - assert.fail("expected MsgError") - return - } - expect(r).toEqual({ - "message": "unexpected message", - "tid": "test", - "type": "error", - "version": "FP-MSG-1.0", + it("kaputt url http", async () => { + const r = await c.request({ + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, { waitFor: () => true }) + if (!MsgIsError(r)) { + assert.fail("expected MsgError") + return + } + expect(r).toEqual({ + "message": "unexpected message", + "tid": "test", + "type": "error", + "version": "FP-MSG-1.0", + }) + }) + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}) + const req = buildReqGestalt(sthis, defaultGestalt({ id: "test", ...msgP })) + const r = await c.request(req, { waitFor: MsgIsResGestalt }) + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)) + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote) }) - }) - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, { }) - const req = buildReqGestalt(sthis, defaultGestalt({ id: "test", ...msgP })) - const r = await c.request(req, { waitFor: MsgIsResGestalt }) - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)) - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote) - }) - it("openConnection", async () => { - const req = buildReqOpen(sthis, { - ...c.conn?.conn as Connection, + it("openConnection", async () => { + const req = buildReqOpen(sthis, { + ...c.conn?.conn as Connection, + }) + const r = await c.request(req, { waitFor: MsgIsResOpen }) + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)) + } + expect(r).toEqual({ + conn: c.conn?.conn, + tid: req.tid, + "type": "resOpen", + "version": "FP-MSG-1.0", + }) }) - const r = await c.request(req, { waitFor: MsgIsResOpen }) - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)) - } - expect(r).toEqual({ - conn: c.conn?.conn, - tid: req.tid, - "type": "resOpen", - "version": "FP-MSG-1.0", + + it("open", async () => { + const qOpen = buildReqOpen(sthis, { + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + }) + const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}`), qOpen, msgP) + expect(rC.isOk()).toBeTruthy() + const c = rC.Ok() + expect(c.conn).toEqual({}) + expect(c.exchangedGestalt).toEqual({}) + }) }) }) } -}) - -// describe("connection -- http", async () => { -// const sthis = ensureSuperThis(); -// const port = 1024 + Math.floor(Math.random() * (65536 - 1024)) -// const gsi = defaultGestaltItem(sthis, { id: "test", hasPersistent: true, protocol: "http" }) -// beforeAll(async () => { -// }) -// afterAll(async () => { -// }) -// it("open", async () => { -// Msger.open(sthis, URI.from(`http://localhost:${port}`), buildReqOpen(sthis, { -// key: { -// ledgerName: "test", -// tenantId: "test", -// }, -// reqId: "req-open-test", -// }), gsi) -// }) -// }) \ No newline at end of file +}) \ No newline at end of file diff --git a/src/cloud/msg-request.ts b/src/cloud/msg-request.ts index 194629c4..e481325c 100644 --- a/src/cloud/msg-request.ts +++ b/src/cloud/msg-request.ts @@ -34,15 +34,6 @@ export interface HttpConnectionParams { readonly uniqServerId?: string; } -export interface MsgerParams { - readonly ende: EnDeCoder; - readonly mime: string; - readonly auth?: AuthType; - readonly hasPersistent?: boolean; - readonly protocol: "http" | "ws"; - readonly timeout: number; // msec -} - export type RequestFN = (req: Q, opts: RequestOpts) => Promise> const serverId = "FP-Universal-Client" diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index fb6d87ac..411c914b 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -1,5 +1,5 @@ import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; -import { buildReqGestalt, defaultGestalt, Gestalt, GestaltParam, MsgBase, MsgerParams, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; +import { buildReqGestalt, defaultGestalt, Gestalt, MsgBase, MsgerParams, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; import { HttpConnection } from "./http-connection.js"; @@ -62,6 +62,20 @@ export interface OpenParams { readonly timeout: number; } +export async function applyStart(prC: Promise>): Promise> { + const rC = await prC + if (rC.isErr()) { + return rC + } + const c = rC.Ok() + const r = await c.start() + if (r.isErr()) { + return Result.Err(r.Err()) + } + return rC +} + + // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Msger { @@ -83,7 +97,7 @@ export class Msger { ws, }, msgP, exGestalt)) } - static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, igs: GestaltParam): Promise> { + static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, igs: MsgerParams): Promise> { // initial exchange with JSON encoding const jsGI = defaultMsgParams(sthis, { ...igs, ende: jsonEnDe(sthis) }); const url = URI.from(curl) @@ -104,9 +118,9 @@ export class Msger { const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt; const msgP = defaultMsgParams(sthis, igs); if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) { - return Msger.openHttp(sthis, qOpen, exGt.remote.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), msgP, exGt); + return applyStart(Msger.openHttp(sthis, qOpen, exGt.remote.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), msgP, exGt)); } - return Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt); + return applyStart(Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt)); } private constructor() { From 503f352a3907237a6629689447cf50f6f2e34098 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 23 Dec 2024 16:33:54 +0100 Subject: [PATCH 33/83] chore: Msger with connection tests --- src/cloud/cloud.test.ts | 2 +- src/cloud/connection.test.ts | 57 ++++++++++++++++++--------- src/cloud/msg-types.ts | 24 +++++------- src/cloud/msger.ts | 8 ++-- src/cloud/ws-connection.ts | 75 ------------------------------------ 5 files changed, 52 insertions(+), 114 deletions(-) diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 995be4c5..80bdd2ca 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -8,7 +8,7 @@ import * as toml from "smol-toml"; import { bs, CRDTEntry, Database, ensureSuperThis, fireproof, isNotFoundError, rt } from "@fireproof/core"; import { AwsClient } from "aws4fetch"; import { smokeDB } from "../../tests/helper.js"; -import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.ts-off"; +// import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.ts-off"; import { calculatePreSignedUrl } from "./pre-signed-url.js"; import { newWebSocket } from "./new-websocket.js"; diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 47b5d466..5a3ef1b1 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -23,7 +23,8 @@ import { createNodeWebSocket } from '@hono/node-ws' import { Hono } from 'hono' import { applyStart, defaultMsgParams, MsgConnection, Msger, } from "./msger.js"; import { top_uint8 } from "../coerce-binary.js"; -import exp from "constants"; +import { HttpConnection } from "./http-connection.js"; +import { WSConnection } from "./ws-connection.js"; class Dispatcher { readonly sthis: SuperThis @@ -139,11 +140,12 @@ class HonoServer { function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt({ id: "HTTP-server", hasPersistent: true, protocol: "http" }) + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "http" }), { id: "HTTP-server" }) const exGt = { my, remote } return { name: "HTTP", remoteGestalt: remote, + cInstance: HttpConnection, ok: { url: () => URI.from(`http://127.0.0.1:${port}/fp`), open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], { @@ -172,11 +174,12 @@ function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: Req } function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt({ id: "WS-server", hasPersistent: true, protocol: "ws" }) + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "ws" }), { id: "WS-server" }) const exGt = { my, remote } return { name: "WS", remoteGestalt: remote, + cInstance: WSConnection, ok: { url: () => URI.from(`http://127.0.0.1:${port}/ws`), open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), { @@ -216,8 +219,8 @@ describe("Connection", () => { }, reqId: "req-open-test", }) - const my = defaultGestalt({ id: "test" }) - for (const style of [httpStyle(sthis, port, msgP, qOpen, my)/*, wsStyle(sthis, port, msgP, qOpen, my)*/]) { + const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }) + for (const style of [httpStyle(sthis, port, msgP, qOpen, my), wsStyle(sthis, port, msgP, qOpen, my)]) { describe(style.name, () => { let server: HonoServer beforeAll(async () => { @@ -281,7 +284,7 @@ describe("Connection", () => { }) it("gestalt url http", async () => { const msgP = defaultMsgParams(sthis, {}) - const req = buildReqGestalt(sthis, defaultGestalt({ id: "test", ...msgP })) + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })) const r = await c.request(req, { waitFor: MsgIsResGestalt }) if (!MsgIsResGestalt(r)) { assert.fail("expected MsgError", JSON.stringify(r)) @@ -304,22 +307,38 @@ describe("Connection", () => { "version": "FP-MSG-1.0", }) }) + }) - it("open", async () => { - const qOpen = buildReqOpen(sthis, { - key: { - ledgerName: "test", - tenantId: "test", + it("open", async () => { + const qOpen = buildReqOpen(sthis, { + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + }) + const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP) + expect(rC.isOk()).toBeTruthy() + const c = rC.Ok() + expect(c.conn).toEqual({ + "conn": { + "key": { + "ledgerName": "test", + "tenantId": "test", }, - reqId: "req-open-test", - }) - const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}`), qOpen, msgP) - expect(rC.isOk()).toBeTruthy() - const c = rC.Ok() - expect(c.conn).toEqual({}) - expect(c.exchangedGestalt).toEqual({}) - + "reqId": "req-open-test", + "resId": c.conn?.conn.resId, + }, + "tid": c.conn?.tid, + "type": "resOpen", + "version": "FP-MSG-1.0", + }) + expect(c).toBeInstanceOf(style.cInstance) + expect(c.exchangedGestalt).toEqual({ + my, remote: style.remoteGestalt }) + await c.close() + }) }) } diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 05269fa6..25e2f2d5 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -152,32 +152,26 @@ export interface MsgerParams { } // force the server id -export type GestaltParam = Partial & { readonly id: string }; - -export function defaultGestalt(gs: GestaltParam & { - hasPersitance?: boolean; - protocol?: "http" | "ws"; -}): Gestalt { - const hasPersitance = gs.hasPersitance || false; - delete gs.hasPersitance; +export type GestaltParam = Partial & { readonly id: string }; + +export function defaultGestalt(msgP: MsgerParams, gestalt: GestaltParam): Gestalt { return { storeTypes: ["meta", "data", "wal"], - id: gs.id, httpEndpoints: ["/fp"], - wsEndpoints: gs.protocol === 'ws' ? ["/ws"] : [], + wsEndpoints: msgP.protocol === 'ws' ? ["/ws"] : [], encodings: ["JSON"], - protocolCapabilities: gs.protocol === 'ws' ? ["stream"] : ["reqRes"], + protocolCapabilities: msgP.protocol === 'ws' ? ["stream"] : ["reqRes"], auth: [], requiresAuth: false, - data: hasPersitance ? { + data: msgP.hasPersistent ? { inband: true, outband: true, }: undefined, - meta: hasPersitance ? { + meta: msgP.hasPersistent ? { inband: true, outband: true, }: undefined, - wal: hasPersitance ? { + wal: msgP.hasPersistent ? { inband: true, outband: true, }: undefined, @@ -214,7 +208,7 @@ export function defaultGestalt(gs: GestaltParam & { "updateMeta", ], eventTypes: ["updateMeta"], - ...gs.gestalt + ...gestalt } } diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 411c914b..f86aee94 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -97,11 +97,11 @@ export class Msger { ws, }, msgP, exGestalt)) } - static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, igs: MsgerParams): Promise> { + static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, imsgP: MsgerParams): Promise> { // initial exchange with JSON encoding - const jsGI = defaultMsgParams(sthis, { ...igs, ende: jsonEnDe(sthis) }); + const jsGI = defaultMsgParams(sthis, { ...imsgP, ende: jsonEnDe(sthis) }); const url = URI.from(curl) - const gs = defaultGestalt({id: "FP-Universal-Client"}); + const gs = defaultGestalt(imsgP, {id: "FP-Universal-Client"}); /* * request Gestalt with Http */ @@ -116,7 +116,7 @@ export class Msger { } await hc.close(); const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt; - const msgP = defaultMsgParams(sthis, igs); + const msgP = defaultMsgParams(sthis, imsgP); if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) { return applyStart(Msger.openHttp(sthis, qOpen, exGt.remote.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), msgP, exGt)); } diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index e5483dca..b43e75e8 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -1,78 +1,3 @@ - -// export class WSAttachConnection implements Connection { -// readonly ws: WebSocket; -// // readonly key: ConnectionKey; -// readonly sthis: SuperThis; -// readonly logger: Logger; - -// // readonly errFns = new Map void>(); -// // readonly closeFns = new Map void>(); -// // readonly msgFns = new Map void>(); - -// readonly waitForTid: WSAttachable["waitForTid"]; -// constructor(sthis: SuperThis, ws: WebSocket, waitForTid: WSAttachable["waitForTid"], mec: MsgErrorClose) { -// this.ws = ws; -// // this.key = key; -// this.sthis = sthis; -// // this.onClose = onClose; -// this.logger = ensureLogger(sthis, "WSAttachConnection", { -// this: true, -// }); -// this.waitForTid = waitForTid; -// ws.onmessage = mec.msgFn -// ws.onopen = mec.openFn; -// ws.onerror = mec.errFn -// ws.onclose = mec.closeFn -// } - -// async close(): Promise { -// this.logger.Debug().Msg("close"); -// this.ws.close(); -// } - -// async request(req: Q, opts: RequestOpts): Promise> { -// opts = { -// ...{ -// timeout: 1000, -// }, -// ...opts, -// }; -// const future = new Future(); -// this.waitForTid.set(req.tid, { -// tid: req.tid, -// future, -// type: opts.waitType, -// }); -// const start = Date.now(); -// const logger = ensureLogger(this.sthis, "ConnectionImpl.request") -// .With() -// .Str("tid", req.tid) -// .Uint64("timeout", opts.timeout) -// .Ref("start", () => new Date().getTime() - start) -// .Any("req", req) -// .Logger(); -// this.ws.send(JSON.stringify(req)); -// const clean = setTimeout(() => { -// this.waitForTid.delete(req.tid); -// future.reject(new Error("Timeout")); -// }, opts.timeout); -// // add timeout handling -// logger.Debug().Msg("request-enter"); -// return future -// .asPromise() -// .finally(() => clearTimeout(clean)) -// .then((res) => { -// logger.Debug().Any("res", res).Msg("request-ok"); -// return Result.Ok(res as S); -// }) -// .catch((err) => { -// logger.Error().Err(err).Msg("request-error"); -// return Result.Ok(buildErrorMsg(this.logger, req, err) as MsgBase as S); -// }); -// } -// } - - import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; From 60c1a2fd2b3370a0d086e75061a9c577386f0028 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 23 Dec 2024 23:30:44 +0100 Subject: [PATCH 34/83] chore: hono is our server platform --- src/cloud/backend/cf-hono-server.ts | 26 + src/cloud/backend/env.d.ts | 1 + src/cloud/backend/server.ts | 787 ++++++++++++++-------------- src/cloud/backend/wrangler.toml | 19 +- src/cloud/cloud.test.ts | 12 +- src/cloud/connection.test.ts | 628 +++++++++++----------- src/cloud/hono-server.ts | 104 ++++ src/cloud/http-connection.ts | 86 ++- src/cloud/msg-dispatch.ts | 61 +++ src/cloud/msg-processor.ts | 80 +-- src/cloud/msg-request.ts | 411 +++++++-------- src/cloud/msg-types.ts | 107 ++-- src/cloud/msger.ts | 238 +++++---- src/cloud/node-hono-server.ts | 41 ++ src/cloud/ws-connection.ts | 64 ++- src/coerce-binary.ts | 4 +- 16 files changed, 1500 insertions(+), 1169 deletions(-) create mode 100644 src/cloud/backend/cf-hono-server.ts create mode 100644 src/cloud/hono-server.ts create mode 100644 src/cloud/msg-dispatch.ts create mode 100644 src/cloud/node-hono-server.ts diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts new file mode 100644 index 00000000..c2f3e39e --- /dev/null +++ b/src/cloud/backend/cf-hono-server.ts @@ -0,0 +1,26 @@ +import { HttpHeader } from "@adviser/cement"; +import { Hono } from "hono"; +import { UpgradeWebSocket } from "hono/ws"; +import { HonoServerImpl, CORS } from "../hono-server.js"; + +export class CFHonoServer implements HonoServerImpl { + upgradeWebSocket!: UpgradeWebSocket; + + readonly headers: HttpHeader; + constructor(headers?: HttpHeader) { + this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + // console.log("CFHonoServer", this.headers.AsHeaderInit()) + } + + async start(_app: Hono): Promise { + const { upgradeWebSocket } = await import("hono/cloudflare-workers"); + this.upgradeWebSocket = upgradeWebSocket; + } + + async serve(_app: Hono, _port?: number): Promise { + return {} as T; + } + async close(): Promise { + return; + } +} diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index fd73ba15..4130c727 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -23,6 +23,7 @@ export interface Env { FP_DEBUG: string; FP_STACK: string; FP_FORMAT: string; + FP_PROTOCOL: string; TEST_DATE?: string; MAX_IDLE_TIME?: string; diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index a3ef1a64..62aab8a1 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,425 +1,410 @@ // / -import type { Env } from "./env.js"; -import { JSONFormatter, Logger, LoggerImpl, URI, YAMLFormatter } from "@adviser/cement"; -import { - buildErrorMsg, - buildResDelMeta, - buildResGetMeta, - buildResPutMeta, - buildResSignedUrl, - buildResSubscriptMeta, - buildUpdateMetaEvent, - ErrorMsg, - MsgBase, - MsgIsQSError, - MsgIsReqPutMeta, - MsgIsResPutMeta, - MsgIsResSubscribeMeta, - ReqDelMeta, - ReqGetMeta, - ReqPutMeta, - ReqSignedUrl, - ReqSubscribeMeta, - ResDelMeta, - ResGetMeta, - ResPutMeta, - ResSignedUrl, - ResSubscribeMeta, - UpdateMetaEvent, -} from "../msg-types.js"; +import { ResolveOnce } from "@adviser/cement"; +import { defaultGestalt } from "../msg-types.js"; // import { Hono } from "hono"; -import { CRDTEntry, NotFoundError } from "@fireproof/core"; -// import { DurableObject } from "cloudflare:workers"; +import { ensureSuperThis } from "@fireproof/core"; import { DurableObject } from "cloudflare:workers"; -import { calculatePreSignedUrl } from "../pre-signed-url.js"; -import { CtxBase, MsgProcessorBase, ReqOptResCtx, ReqResCtx, WithErrorMsg } from "../msg-processor.js"; - -const CORS = { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "GET,POST,OPTIONS,PUT,DELETE", - "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours -}; +import { HonoServer } from "../hono-server.js"; +import { Hono } from "hono"; +import { defaultMsgParams } from "../msger.js"; +import { Env } from "./env.js"; +import { CFHonoServer } from "./cf-hono-server.js"; + +// function json(data: T, status = 200) { +// return Response.json(data, { status, headers: CORS }); +// } -function json(data: T, status = 200) { - return Response.json(data, { status, headers: CORS }); -} +// function ensureLogger(env: Env, module = "Fireproof"): Logger { +// const logger = new LoggerImpl() +// .With() +// .Module(module) +// .SetDebug(env.FP_DEBUG) +// .SetExposeStack(!!env.FP_STACK || false); +// switch (env.FP_FORMAT) { +// case "jsonice": +// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); +// break; +// case "yaml": +// logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); +// break; +// case "json": +// default: +// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); +// break; +// } +// return logger.Logger(); +// } -function ensureLogger(env: Env, module = "Fireproof"): Logger { - const logger = new LoggerImpl() - .With() - .Module(module) - .SetDebug(env.FP_DEBUG) - .SetExposeStack(!!env.FP_STACK || false); - switch (env.FP_FORMAT) { - case "jsonice": - logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); - break; - case "yaml": - logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); - break; - case "json": - default: - logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); - break; - } - return logger.Logger(); -} +// interface MsgStats { +// readonly msgSeq: number; +// } -interface MsgStats { - readonly msgSeq: number; -} +// interface FPMetaGroup { +// readonly group: ResSubscribeMeta; +// readonly connId: string; +// readonly qs: { +// readonly q: Record; +// readonly s: Record; +// }; +// readonly lastUsed: Date; +// readonly lastMeta: ReqPutMeta; +// } -interface FPMetaGroup { - readonly group: ResSubscribeMeta; - readonly connId: string; - readonly qs: { - readonly q: Record; - readonly s: Record; - }; - readonly lastUsed: Date; - readonly lastMeta: ReqPutMeta; -} +// // interface NextId { +// // nextId: SuperThis["nextId"]; +// // } +// // class NextIdImpl implements NextId { +// // nextId(bytes = 6): { str: string; bin: Uint8Array } { +// // const buf = new Uint8Array(bytes); +// // const bin = crypto.getRandomValues(buf); +// // return { +// // str: base58btc.encode(bin), +// // bin, +// // }; +// // } +// // } + +// // const sthis = new NextIdImpl(); + +export class FPMetaGroups extends DurableObject {} + +// export class FPMetaGroups extends DurableObject { +// // readonly sessions: Map = new Map(); +// // readonly lastMetaByTendant = new Map[]>(); + +// readonly logger: Logger; + +// constructor(ctx: DurableObjectState, env: Env) { +// super(ctx, env); +// this.logger = ensureLogger(env, "FPMetaGroups"); +// // this.ctx.getWebSockets().forEach((webSocket) => { +// // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; +// // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { +// // this.sessions.set(webSocket, fpMetaGroup); +// // } +// // }); +// } + +// async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { +// if (typeof msg !== "string") { +// this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); +// return; +// } -// interface NextId { -// nextId: SuperThis["nextId"]; -// } -// class NextIdImpl implements NextId { -// nextId(bytes = 6): { str: string; bin: Uint8Array } { -// const buf = new Uint8Array(bytes); -// const bin = crypto.getRandomValues(buf); -// return { -// str: base58btc.encode(bin), -// bin, -// }; +// return CFMsgProcessor.dispatch( +// () => JSON.parse(msg.toString()), +// { env: this.env }, +// async (req: MsgBase, ictx: CFCtxBase) => { +// if (req.auth) { +// // do ucan magic +// } +// let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; +// group = { +// ...group, +// qs: { +// ...group.qs, +// q: { +// ...group.qs.q, +// [req.type]: { +// msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, +// }, +// }, +// }, +// connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), +// lastUsed: new Date(), +// } satisfies FPMetaGroup; +// ws.serializeAttachment(group); +// const ctx = { ...ictx, group } satisfies CFCtxWithGroup; +// return { req, ctx }; +// } +// ).then((qs) => { +// let group = { +// ...qs.ctx.group, +// qs: { +// ...qs.ctx.group.qs, +// s: { +// ...qs.ctx.group.qs.s, +// [qs.req.type]: { +// msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, +// }, +// }, +// }, +// } satisfies FPMetaGroup; +// switch (true) { +// case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): +// { +// group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; +// ws.serializeAttachment(group); +// // console.log("putMeta group", group); +// (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( +// buildUpdateMetaEvent(qs, { +// connId: qs.res.connId, +// subscriberId: "later-overriden", +// }) +// ); +// this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); +// } +// break; +// case MsgIsResSubscribeMeta(qs): +// { +// group = { ...group, group: qs.res } satisfies FPMetaGroup; +// // console.log("subscribeMeta group", group); +// ws.serializeAttachment(group); +// this.updateMeta({ +// connId: qs.res.connId, +// subscriberId: "later-overriden", +// tid: qs.res.tid, +// type: "updateMeta", +// key: qs.res.key, +// metaId: "later-overriden", +// metas: [], +// version: qs.res.version, +// }); +// } +// break; +// } +// // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); +// ws.send(JSON.stringify(qs.res)); +// }); +// } + +// async fetch(req: Request): Promise { +// const path = URI.from(req.url).pathname; +// switch (path) { +// case "/fp": { +// const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); +// return json(rq.res, MsgIsQSError(rq) ? 422 : 200); +// } +// case "/ws": { +// const upgradeHeader = req.headers.get("Upgrade"); +// if (!upgradeHeader || upgradeHeader !== "websocket") { +// return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); +// } +// const { 0: fromClient, 1: toClient } = new WebSocketPair(); +// this.ctx.acceptWebSocket(toClient); +// // this.logger.Debug().Msg("fetch"); +// return new Response(null, { +// status: 101, +// webSocket: fromClient, +// }); +// } +// default: { +// const logger = ensureLogger(this.env); +// return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); +// } +// } +// } + +// webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { +// try { +// ws.close(code, reason); +// // eslint-disable-next-line @typescript-eslint/no-unused-vars +// } catch (e) { +// // ignore +// } finally { +// this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); +// } +// } + +// updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { +// const wsSocks = ctx.dobj.getWebSockets(); +// const groupWs = wsSocks.map((ws) => ({ +// ws, +// group: ws.deserializeAttachment() as FPMetaGroup, +// })); +// const joinedMeta = groupWs.reduce((acc, { group }) => { +// if (group && group.lastMeta) { +// acc.push(...group.lastMeta.metas); +// } +// return acc +// }, [] as CRDTEntry[]) +// const now = new Date() +// const joinedQS = { +// req: { ...qs.req, metas: joinedMeta }, +// res: qs.res, // } +// return acc; +// }, [] as CRDTEntry[]); +// if (joinedMeta.length === 0) { +// return []; +// } +// const now = new Date(); +// const joinedUp = { +// ...up, +// metas: joinedMeta, +// }; +// groupWs.forEach(({ ws, group }) => { +// // console.log("group->", group); +// // group = { +// // ...group, +// // msgSeq: (group ? group.msgSeq : 0) + 1, +// // } +// group = { +// ...group, +// qs: { +// ...group.qs, +// s: { +// ...group.qs.s, +// [up.type]: { +// msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, +// }, +// }, +// }, +// lastUsed: now, +// } satisfies FPMetaGroup; +// ws.serializeAttachment(group); +// const toSend = { +// ...joinedUp, +// subscriberId: group.group.subscriberId, +// connId: group.group.connId, +// }; +// this.logger.Debug().Any("event", toSend).Msg("updateMeta"); +// ws.send( +// // this is not the best way to do this +// JSON.stringify(toSend) +// ); +// }); +// return joinedMeta; +// } // } -// const sthis = new NextIdImpl(); - -export class FPMetaGroups extends DurableObject { - // readonly sessions: Map = new Map(); - // readonly lastMetaByTendant = new Map[]>(); - - readonly logger: Logger; - - constructor(ctx: DurableObjectState, env: Env) { - super(ctx, env); - this.logger = ensureLogger(env, "FPMetaGroups"); - // this.ctx.getWebSockets().forEach((webSocket) => { - // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; - // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { - // this.sessions.set(webSocket, fpMetaGroup); - // } - // }); - } - - async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { - if (typeof msg !== "string") { - this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); - return; - } - - return CFMsgProcessor.dispatch( - () => JSON.parse(msg.toString()), - { env: this.env }, - async (req: MsgBase, ictx: CFCtxBase) => { - if (req.auth) { - // do ucan magic - } - let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; - group = { - ...group, - qs: { - ...group.qs, - q: { - ...group.qs.q, - [req.type]: { - msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, - }, - }, - }, - connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), - lastUsed: new Date(), - } satisfies FPMetaGroup; - ws.serializeAttachment(group); - const ctx = { ...ictx, group } satisfies CFCtxWithGroup; - return { req, ctx }; - } - ).then((qs) => { - let group = { - ...qs.ctx.group, - qs: { - ...qs.ctx.group.qs, - s: { - ...qs.ctx.group.qs.s, - [qs.req.type]: { - msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, - }, - }, - }, - } satisfies FPMetaGroup; - switch (true) { - case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): - { - group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; - ws.serializeAttachment(group); - // console.log("putMeta group", group); - (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( - buildUpdateMetaEvent(qs, { - connId: qs.res.connId, - subscriberId: "later-overriden", - }) - ); - this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); - } - break; - case MsgIsResSubscribeMeta(qs): - { - group = { ...group, group: qs.res } satisfies FPMetaGroup; - // console.log("subscribeMeta group", group); - ws.serializeAttachment(group); - this.updateMeta({ - connId: qs.res.connId, - subscriberId: "later-overriden", - tid: qs.res.tid, - type: "updateMeta", - key: qs.res.key, - metaId: "later-overriden", - metas: [], - version: qs.res.version, - }); - } - break; - } - // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); - ws.send(JSON.stringify(qs.res)); - }); - } - - async fetch(req: Request): Promise { - const path = URI.from(req.url).pathname; - switch (path) { - case "/fp": { - const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); - return json(rq.res, MsgIsQSError(rq) ? 422 : 200); - } - case "/ws": { - const upgradeHeader = req.headers.get("Upgrade"); - if (!upgradeHeader || upgradeHeader !== "websocket") { - return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); - } - const { 0: fromClient, 1: toClient } = new WebSocketPair(); - this.ctx.acceptWebSocket(toClient); - // this.logger.Debug().Msg("fetch"); - return new Response(null, { - status: 101, - webSocket: fromClient, - }); - } - default: { - const logger = ensureLogger(this.env); - return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); - } - } - } - - webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { - try { - ws.close(code, reason); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - } catch (e) { - // ignore - } finally { - this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); - } - } - - updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { - const wsSocks = ctx.dobj.getWebSockets(); - const groupWs = wsSocks.map((ws) => ({ - ws, - group: ws.deserializeAttachment() as FPMetaGroup, - })); - const joinedMeta = groupWs.reduce((acc, { group }) => { - if (group && group.lastMeta) { - acc.push(...group.lastMeta.metas); - } - return acc - }, [] as CRDTEntry[]) - const now = new Date() - const joinedQS = { - req: { ...qs.req, metas: joinedMeta }, - res: qs.res, - } - return acc; - }, [] as CRDTEntry[]); - if (joinedMeta.length === 0) { - return []; - } - const now = new Date(); - const joinedUp = { - ...up, - metas: joinedMeta, - }; - groupWs.forEach(({ ws, group }) => { - // console.log("group->", group); - // group = { - // ...group, - // msgSeq: (group ? group.msgSeq : 0) + 1, - // } - group = { - ...group, - qs: { - ...group.qs, - s: { - ...group.qs.s, - [up.type]: { - msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, - }, - }, - }, - lastUsed: now, - } satisfies FPMetaGroup; - ws.serializeAttachment(group); - const toSend = { - ...joinedUp, - subscriberId: group.group.subscriberId, - connId: group.group.connId, - }; - this.logger.Debug().Any("event", toSend).Msg("updateMeta"); - ws.send( - // this is not the best way to do this - JSON.stringify(toSend) - ); - }); - return joinedMeta; - } -} - -// const app = new Hono<{ Bindings: Env }>(); - - -interface CFCtxBaseParam { - readonly env: Env; - readonly module?: string; -} +// // const app = new Hono<{ Bindings: Env }>(); -interface CFCtxBase extends CtxBase { - readonly env: Env; -} - -type CFCtxWithGroup = CFCtxBase & { readonly group: FPMetaGroup }; - -const serverId = "Cloudflare-Fireproof"; - -class CFMsgProcessor extends MsgProcessorBase { - - static dispatch( - decodeFn: () => Promise, - ctx: CFCtxBaseParam, - reqFn?: (msg: Q, ctx: CFCtxBase) => Promise> - ): Promise, CFCtxWithGroup>> { - return new CFMsgProcessor({ - env: ctx.env, - logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor"), - }).dispatch(decodeFn, reqFn); - } - - constructor(cfp: CFCtxBase) { - super(cfp.logger, cfp, "CFMsgProcessor") - } - - async dispatch( - decodeFn: () => Promise, - reqFn: (msg: Q, ctx: CFCtxBase) => Promise> = async (req) => ({ req }) - ): Promise, CFCtxWithGroup>> { - return super.dispatch(decodeFn, async (msg: Q, ctx: CFCtxBase) => { - const { req, res, ctx: optCtx } = await reqFn(msg, ctx) - return { req, res, ctx: optCtx || ctx} - }) - } - - - - async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { - // delete meta does nothing in this implementation - // if you delete meta basically you are deleting the whole ledger - return buildResDelMeta(req, { - params: req.params, - status: "unsupported", - connId: ctx.group.connId, - }); - } - - async getMeta(req: ReqGetMeta, ctx: CFCtxWithGroup): Promise { - const rSignedUrl = await calculatePreSignedUrl( - { - tid: req.tid, - type: "reqSignedUrl", - version: req.version, - params: { ...req.params, method: "GET" }, - }, - ctx.env - ); - if (rSignedUrl.isErr()) { - return buildErrorMsg(this.logger, req, rSignedUrl.Err()); - } - return buildResGetMeta(req, { - signedGetUrl: rSignedUrl.Ok().toString(), - status: "found", - metas: [], - connId: "", - }); - } - - async putMeta(req: ReqPutMeta, ctx: CFCtxWithGroup): Promise { - const rSignedUrl = await calculatePreSignedUrl( - { - tid: req.tid, - type: "reqSignedUrl", - version: req.version, - params: { ...req.params, method: "PUT" }, - }, - ctx.env - ); - if (rSignedUrl.isErr()) { - return buildErrorMsg(this.logger, req, rSignedUrl.Err()); - } - // roughly time ordered - return buildResPutMeta(req, { - // metaId should be a hash of metas. - metaId: new Date().getTime().toString(), - metas: req.metas, - signedPutUrl: rSignedUrl.Ok().toString(), - connId: ctx.group.connId, - }); - } +// interface CFCtxBaseParam { +// readonly env: Env; +// readonly module?: string; +// } - async signedUrl(req: Q, ctx: CFCtxBase): Promise { - const rSignedUrl = await calculatePreSignedUrl(req, ctx.env); - if (rSignedUrl.isErr()) { - return buildErrorMsg(this.logger, req, rSignedUrl.Err()); - } - const resSignedUrl = buildResSignedUrl(req, rSignedUrl.Ok().toString()); - return resSignedUrl; - } +// interface CFCtxBase extends CtxBase { +// readonly env: Env; +// } +// type CFCtxWithGroup = CFCtxBase & { readonly group: FPMetaGroup }; + +// const serverId = "Cloudflare-Fireproof"; + +// class CFMsgProcessor extends MsgProcessorBase { + +// static dispatch( +// decodeFn: () => Promise, +// ctx: CFCtxBaseParam, +// reqFn?: (msg: Q, ctx: CFCtxBase) => Promise> +// ): Promise, CFCtxWithGroup>> { +// return new CFMsgProcessor({ +// env: ctx.env, +// logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor"), +// }).dispatch(decodeFn, reqFn); +// } + +// constructor(cfp: CFCtxBase) { +// super(cfp.logger, cfp, "CFMsgProcessor") +// } + +// async dispatch( +// decodeFn: () => Promise, +// reqFn: (msg: Q, ctx: CFCtxBase) => Promise> = async (req) => ({ req }) +// ): Promise, CFCtxWithGroup>> { +// return super.dispatch(decodeFn, async (msg: Q, ctx: CFCtxBase) => { +// const { req, res, ctx: optCtx } = await reqFn(msg, ctx) +// return { req, res, ctx: optCtx || ctx} +// }) +// } + +// async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { +// // delete meta does nothing in this implementation +// // if you delete meta basically you are deleting the whole ledger +// return buildResDelMeta(req, { +// params: req.params, +// status: "unsupported", +// connId: ctx.group.connId, +// }); +// } + +// async getMeta(req: ReqGetMeta, ctx: CFCtxWithGroup): Promise { +// const rSignedUrl = await calculatePreSignedUrl( +// { +// tid: req.tid, +// type: "reqSignedUrl", +// version: req.version, +// params: { ...req.params, method: "GET" }, +// }, +// ctx.env +// ); +// if (rSignedUrl.isErr()) { +// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); +// } +// return buildResGetMeta(req, { +// signedGetUrl: rSignedUrl.Ok().toString(), +// status: "found", +// metas: [], +// connId: "", +// }); +// } + +// async putMeta(req: ReqPutMeta, ctx: CFCtxWithGroup): Promise { +// const rSignedUrl = await calculatePreSignedUrl( +// { +// tid: req.tid, +// type: "reqSignedUrl", +// version: req.version, +// params: { ...req.params, method: "PUT" }, +// }, +// ctx.env +// ); +// if (rSignedUrl.isErr()) { +// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); +// } +// // roughly time ordered +// return buildResPutMeta(req, { +// // metaId should be a hash of metas. +// metaId: new Date().getTime().toString(), +// metas: req.metas, +// signedPutUrl: rSignedUrl.Ok().toString(), +// connId: ctx.group.connId, +// }); +// } + +// async signedUrl(req: Q, ctx: CFCtxBase): Promise { +// const rSignedUrl = await calculatePreSignedUrl(req, ctx.env); +// if (rSignedUrl.isErr()) { +// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); +// } +// const resSignedUrl = buildResSignedUrl(req, rSignedUrl.Ok().toString()); +// return resSignedUrl; +// } + +// async subscribeMeta(req: ReqSubscribeMeta, ctx: CFCtxWithGroup): Promise { +// // console.log("subscribeMeta", req) +// return buildResSubscriptMeta(req, ctx.group); +// } +// } - async subscribeMeta(req: ReqSubscribeMeta, ctx: CFCtxWithGroup): Promise { - // console.log("subscribeMeta", req) - return buildResSubscriptMeta(req, ctx.group); - } -} +const app = new Hono(); +const once = new ResolveOnce(); export default { + fetch: async (req, env, ctx): Promise => { + await once.once(() => { + const sthis = ensureSuperThis(); + const msgP = defaultMsgParams(sthis, { + hasPersistent: true, + protocol: env.FP_PROTOCOL === "ws" ? "ws" : "http", + }); + const gs = defaultGestalt(msgP, { + id: env.FP_PROTOCOL ? (env.FP_PROTOCOL === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", + }); + const honoServer = new HonoServer(sthis, msgP, gs, new CFHonoServer()); + return honoServer.start(app); + }); + return app.fetch(req, env, ctx); + }, +} satisfies ExportedHandler; +/* async fetch(req, env, _ctx): Promise { - - - const id = env.FP_META_GROUPS.idFromName("fireproof"); const stub = env.FP_META_GROUPS.get(id); // eslint-disable-next-line @typescript-eslint/no-explicit-any return stub.fetch(req as any) as unknown as Promise; }, } satisfies ExportedHandler; +*/ diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 9f108778..45a9bfb7 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -18,16 +18,31 @@ new_classes = ["FPMetaGroups"] enabled = true head_sampling_rate = 1 -[env.test.vars] +[env.test-reqRes.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" FP_DEBUG = "FPMetaGroups" +FP_PROTOCOL = "http" + +[env.test-stream.vars] +VERSION = "FP-MSG-1.0" +STORAGE_URL = "http://localhost:9000/testbucket" +ACCESS_KEY_ID = "minioadmin" +SECRET_ACCESS_KEY = "minioadmin" +FP_DEBUG = "FPMetaGroups" +FP_PROTOCOL = "ws" + #FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" -[env.test.durable_objects] +[env.test-reqRes.durable_objects] +bindings = [ + { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, +] + +[env.test-stream.durable_objects] bindings = [ { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, ] diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts index 80bdd2ca..90eda9c0 100644 --- a/src/cloud/cloud.test.ts +++ b/src/cloud/cloud.test.ts @@ -147,14 +147,12 @@ describe("CloudBackendTest", () => { expect(await res.json()).toEqual(await testResSignedUrl(env)); }); - it("reqOpen without websocket", async () => { - const conn = await msgOpen(cfURL, { } - }); - - it("reqOpen with websocket", async () => { - }); - + // it("reqOpen without websocket", async () => { + // const conn = await msgOpen(cfURL, { } + // }); + // it("reqOpen with websocket", async () => { + // }); it("use websockets SignedUrl", async () => { await Promise.all( diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 5a3ef1b1..b8130808 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -1,345 +1,323 @@ -import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; -import { Logger, Result, URI } from "@adviser/cement"; +import { ensureSuperThis, SuperThis } from "@fireproof/core"; +import { Future, URI } from "@adviser/cement"; import { - buildErrorMsg, - buildReqGestalt, - buildReqOpen, - buildResGestalt, - buildResOpen, - MsgIsError, - MsgIsReqOpen, - MsgIsReqGestalt, - MsgIsResGestalt, - MsgIsResOpen, - MsgBase, - Connection, - defaultGestalt, - MsgerParams, - Gestalt, - ReqOpen, + buildReqGestalt, + buildReqOpen, + MsgIsError, + MsgIsResGestalt, + MsgIsResOpen, + Connection, + defaultGestalt, + MsgerParams, + Gestalt, + ReqOpen, } from "./msg-types.js"; -import { serve, ServerType } from '@hono/node-server' -import { createNodeWebSocket } from '@hono/node-ws' -import { Hono } from 'hono' -import { applyStart, defaultMsgParams, MsgConnection, Msger, } from "./msger.js"; -import { top_uint8 } from "../coerce-binary.js"; +import { applyStart, defaultMsgParams, MsgConnection, Msger } from "./msger.js"; import { HttpConnection } from "./http-connection.js"; import { WSConnection } from "./ws-connection.js"; +import { HonoServer } from "./hono-server.js"; +import { Hono } from "hono"; +import { NodeHonoServer } from "./node-hono-server.js"; +import { $ } from "zx"; -class Dispatcher { - readonly sthis: SuperThis - readonly logger: Logger - readonly conns = new Map() - readonly gestalt: Gestalt - - constructor(sthis: SuperThis, gestalt: Gestalt) { - this.sthis = sthis - this.logger = ensureLogger(sthis, "Dispatcher") - this.gestalt = gestalt - } - - addConn(aConn: Connection): Result { - const key = [aConn.key.ledgerName, aConn.key.tenantId].join(":") - let conn = this.conns.get(key) - if (!conn) { - if (this.conns.size > 0) { - return Result.Err("connection") - } - conn = { ...aConn, resId: this.sthis.nextId().str } - this.conns.set(key, conn) - } - if (conn.reqId !== aConn.reqId) { - return Result.Err("unexpected reqId") - } - return Result.Ok(conn) - } - - dispatch(msg: MsgBase, send: (msg: MsgBase) => void) { - switch (true) { - case MsgIsReqGestalt(msg): - return send(buildResGestalt(msg, this.gestalt)); - case MsgIsReqOpen(msg): { - if (!msg.conn) { - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); - } - /* DDoS protection */ - const rConn = this.addConn(msg.conn) - if (rConn.isErr()) { - return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); - } - return send(buildResOpen(this.sthis, msg, rConn.Ok().resId)); - } - default: - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); - } - } +function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "http" }), { + id: "HTTP-server", + }); + const exGt = { my, remote }; + return { + name: "HTTP", + remoteGestalt: remote, + cInstance: HttpConnection, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/fp`), + open: () => + applyStart( + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://localhost:${port}/fp`)], + { + ...msgP, + protocol: "http", + timeout: 1000, + }, + exGt + ) + ), + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), + open: () => + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://localhost:${port - 1}/fp`)], + { + ...msgP, + protocol: "http", + timeout: 1000, + }, + exGt + ), + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port}/fp`), + open: () => + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://4.7.1.1:${port}/fp`)], + { + ...msgP, + protocol: "http", + timeout: 500, + }, + exGt + ), + }, + }; } -class HonoServer { - readonly sthis: SuperThis - server?: ServerType - readonly msgP: MsgerParams - readonly gestalt: Gestalt - readonly logger: Logger - constructor(sthis: SuperThis, msgP: MsgerParams, gestalt: Gestalt) { - this.sthis = sthis - this.logger = ensureLogger(sthis, "HonoServer") - this.msgP = msgP - this.gestalt = gestalt - } - async start(port: number): Promise { - const app = new Hono() - const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }) - // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) - // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) - const dispatcher = new Dispatcher(this.sthis, this.gestalt) - app.put('/fp', async (c) => { - const msg = await c.req.json() - return dispatcher.dispatch(msg, (msg) => c.json(msg)) - }) - app.get("/ws", async (c, next) => { - const reqOpen = JSON.parse(URI.from(c.req.url).getParam("reqOpen", "")) - if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { - c.status(401) - return c.json(buildErrorMsg(this.sthis, this.sthis.logger, reqOpen, - this.logger.Error().Msg("expected reqOpen").AsError() - )) - } - const dispatcher = new Dispatcher(this.sthis, this.gestalt) - dispatcher.addConn(reqOpen.conn) - return upgradeWebSocket((_c) => ({ - onOpen: () => { - // console.log('Connection opened', c.req.url) - }, - onError: (error) => { - this.logger.Error().Err(error).Msg("WebSocket error") - }, - onMessage: async (event, ws) => { - // console.log('onMsg event', event, event.data); - dispatcher.dispatch(this.msgP.ende.decode(await top_uint8(event.data)), (msg) => { - const str = this.msgP.ende.encode(msg) - ws.send(str) - }) - }, - onClose: () => { - // console.log('Connection closed') - }, - }))(c, next) - }) - this.server = await new Promise((resolve) => { - const server = serve({ fetch: app.fetch, port }, () => resolve(server)) - injectWebSocket(server) - return server - }) - return this - } - async close() { - await new Promise((resolve) => this.server?.close(resolve)) - } +function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "ws" }), { id: "WS-server" }); + const exGt = { my, remote }; + return { + name: "WS", + remoteGestalt: remote, + cInstance: WSConnection, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/ws`), + open: () => + applyStart( + Msger.openWS( + sthis, + qOpen, + URI.from(`http://localhost:${port}/ws`), + { + ...msgP, + protocol: "ws", + timeout: 1000, + }, + exGt + ) + ), + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), + open: () => + Msger.openWS( + sthis, + qOpen, + URI.from(`http://localhost:${port - 1}/ws`), + { + ...msgP, + protocol: "ws", + timeout: 1000, + }, + exGt + ), + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), + open: () => + Msger.openWS( + sthis, + qOpen, + URI.from(`http://4.7.1.1:${port - 1}/ws`), + { + ...msgP, + protocol: "ws", + timeout: 500, + }, + exGt + ), + }, + }; } - -function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "http" }), { id: "HTTP-server" }) - const exGt = { my, remote } - return { - name: "HTTP", - remoteGestalt: remote, - cInstance: HttpConnection, - ok: { - url: () => URI.from(`http://127.0.0.1:${port}/fp`), - open: () => applyStart(Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port}/fp`)], { - ...msgP, - protocol: "http", - timeout: 1000 - }, exGt)) - }, - connRefused: { - url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), - open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://localhost:${port - 1}/fp`)], { - ...msgP, - protocol: "http", - timeout: 1000 - }, exGt) - }, - timeout: { - url: () => URI.from(`http://4.7.1.1:${port}/fp`), - open: () => Msger.openHttp(sthis, qOpen, [URI.from(`http://4.7.1.1:${port}/fp`)], { - ...msgP, - protocol: "http", - timeout: 500 - }, exGt) +const sthis = ensureSuperThis(); +const msgP = defaultMsgParams(sthis, { hasPersistent: true }); +for (const honoServer of [ + { + name: "NodeHonoServer", + factory: async (remoteGestalt: Gestalt, _port: number) => + new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer()), + }, + { + name: "CFHonoServer", + factory: async (remoteGestalt: Gestalt, port: number) => { + const tomlFile = "src/cloud/backend/wrangler.toml"; + $.verbose = !!process.env.FP_DEBUG; + const runningWrangler = $` + wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]} --no-show-interactive-dev-session & + waitPid=$! + echo "PID:$waitPid" + wait $waitPid`; + const waitReady = new Future(); + let pid: number | undefined; + runningWrangler.stdout.on("data", (chunk) => { + // console.log(">>", chunk.toString()) + const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; + if (mightPid) { + pid = +mightPid; } - } -} - -function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "ws" }), { id: "WS-server" }) - const exGt = { my, remote } - return { - name: "WS", - remoteGestalt: remote, - cInstance: WSConnection, - ok: { - url: () => URI.from(`http://127.0.0.1:${port}/ws`), - open: () => applyStart(Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port}/ws`), { - ...msgP, - protocol: "ws", - timeout: 1000 - }, exGt)) + if (chunk.includes("Ready on http")) { + waitReady.resolve(true); + } + }); + runningWrangler.stderr.on("data", (chunk) => { + // eslint-disable-next-line no-console + console.error("!!", chunk.toString()); + }); + await waitReady.asPromise(); + const hs = { + start: async () => { + return hs; }, - connRefused: { - url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), - open: () => Msger.openWS(sthis, qOpen, URI.from(`http://localhost:${port - 1}/ws`), { - ...msgP, - protocol: "ws", - timeout: 1000 - }, exGt) + close: async () => { + if (pid) process.kill(pid); }, - timeout: { - url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), - open: () => Msger.openWS(sthis, qOpen, URI.from(`http://4.7.1.1:${port - 1}/ws`), { - ...msgP, - protocol: "ws", - timeout: 500 - }, exGt) - } - } -} - - -describe("Connection", () => { - const sthis = ensureSuperThis(); - const msgP = defaultMsgParams(sthis, { hasPersistent: true }) - const port = 1024 + Math.floor(Math.random() * (65536 - 1024)) + } as unknown as HonoServer; + return hs; + }, + }, +]) { + describe(`${honoServer.name} - Connection`, () => { + const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { - key: { - ledgerName: "test", - tenantId: "test", - }, - reqId: "req-open-test", - }) - const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }) + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + }); + const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); for (const style of [httpStyle(sthis, port, msgP, qOpen, my), wsStyle(sthis, port, msgP, qOpen, my)]) { - describe(style.name, () => { - let server: HonoServer - beforeAll(async () => { - server = await (new HonoServer(sthis, msgP, style.remoteGestalt)).start(port) - }) - afterAll(async () => { - await server.close() - }) - it(`conn refused`, async () => { - const rC = await applyStart(style.connRefused.open()) - expect(rC.isErr()).toBeTruthy() - expect(rC.Err().message).toMatch(/ECONNREFUSED/) - }) - - it(`timeout`, async () => { - const rC = await applyStart(style.timeout.open()) - expect(rC.isErr()).toBeTruthy() - expect(rC.Err().message).toMatch(/Timeout/i) - }) + describe(style.name, () => { + let server: HonoServer; + beforeAll(async () => { + const app = new Hono(); + server = await (await honoServer.factory(style.remoteGestalt, port)).start(app, port); + }); + afterAll(async () => { + await server.close(); + }); + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/ECONNREFUSED/); + }); - describe(`connection`, () => { - let c: MsgConnection - beforeEach(async () => { - const rC = await style.ok.open() - expect(rC.isOk()).toBeTruthy() - c = rC.Ok() - expect(c.conn).toEqual({ - conn: { - "key": { - "ledgerName": "test", - "tenantId": "test", - }, - "reqId": "req-open-test", - "resId": c.conn?.conn.resId, - }, - "tid": qOpen.tid, - "type": "resOpen", - "version": "FP-MSG-1.0", - }) - }) - afterEach(async () => { - await c.close() - }) + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/Timeout/i); + }); - it("kaputt url http", async () => { - const r = await c.request({ - tid: "test", - type: "kaputt", - version: "FP-MSG-1.0", - }, { waitFor: () => true }) - if (!MsgIsError(r)) { - assert.fail("expected MsgError") - return - } - expect(r).toEqual({ - "message": "unexpected message", - "tid": "test", - "type": "error", - "version": "FP-MSG-1.0", - }) - }) - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, {}) - const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })) - const r = await c.request(req, { waitFor: MsgIsResGestalt }) - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)) - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote) - }) + describe(`connection`, () => { + let c: MsgConnection; + beforeEach(async () => { + const rC = await style.ok.open(); + expect(rC.isOk()).toBeTruthy(); + c = rC.Ok(); + expect(c.conn).toEqual({ + conn: { + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + resId: c.conn?.conn.resId, + }, + tid: qOpen.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); + }); + afterEach(async () => { + await c.close(); + }); - it("openConnection", async () => { - const req = buildReqOpen(sthis, { - ...c.conn?.conn as Connection, - }) - const r = await c.request(req, { waitFor: MsgIsResOpen }) - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)) - } - expect(r).toEqual({ - conn: c.conn?.conn, - tid: req.tid, - "type": "resOpen", - "version": "FP-MSG-1.0", - }) - }) - }) + it("kaputt url http", async () => { + const r = await c.request( + { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + { waitFor: () => true } + ); + if (!MsgIsError(r)) { + assert.fail("expected MsgError"); + return; + } + expect(r).toEqual({ + message: "unexpected message", + tid: "test", + type: "error", + version: "FP-MSG-1.0", + }); + }); + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}); + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); + const r = await c.request(req, { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)); + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); + }); - it("open", async () => { - const qOpen = buildReqOpen(sthis, { - key: { - ledgerName: "test", - tenantId: "test", - }, - reqId: "req-open-test", - }) - const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP) - expect(rC.isOk()).toBeTruthy() - const c = rC.Ok() - expect(c.conn).toEqual({ - "conn": { - "key": { - "ledgerName": "test", - "tenantId": "test", - }, - "reqId": "req-open-test", - "resId": c.conn?.conn.resId, - }, - "tid": c.conn?.tid, - "type": "resOpen", - "version": "FP-MSG-1.0", - }) - expect(c).toBeInstanceOf(style.cInstance) - expect(c.exchangedGestalt).toEqual({ - my, remote: style.remoteGestalt - }) - await c.close() + it("openConnection", async () => { + const req = buildReqOpen(sthis, { + ...(c.conn?.conn as Connection), + }); + const r = await c.request(req, { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)); + } + expect(r).toEqual({ + conn: c.conn?.conn, + tid: req.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); + }); + }); - }) - }) + it("open", async () => { + const qOpen = buildReqOpen(sthis, { + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + }); + const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); + expect(rC.isOk()).toBeTruthy(); + const c = rC.Ok(); + expect(c.conn).toEqual({ + conn: { + key: { + ledgerName: "test", + tenantId: "test", + }, + reqId: "req-open-test", + resId: c.conn?.conn.resId, + }, + tid: c.conn?.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); + expect(c).toBeInstanceOf(style.cInstance); + expect(c.exchangedGestalt).toEqual({ + my, + remote: style.remoteGestalt, + }); + await c.close(); + }); + }); } -}) \ No newline at end of file + }); +} diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts new file mode 100644 index 00000000..e989535f --- /dev/null +++ b/src/cloud/hono-server.ts @@ -0,0 +1,104 @@ +import { exception2Result, HttpHeader, runtimeFn, URI } from "@adviser/cement"; +import { ensureLogger, Logger, SuperThis } from "@fireproof/core"; +import { Hono } from "hono"; +import { top_uint8 } from "../coerce-binary.js"; +import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg } from "./msg-types.js"; +import { MsgDispatcher } from "./msg-dispatch.js"; +import { UpgradeWebSocket } from "hono/ws"; + +export interface HonoServerImpl { + start(app: Hono): Promise; + serve(app: Hono, port?: number): Promise; + close(): Promise; + upgradeWebSocket: UpgradeWebSocket; + readonly headers: HttpHeader; +} + +export const CORS = HttpHeader.from({ + // "Accept": "application/json", + "Content-Type": "application/json", + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET,POST,OPTIONS,PUT,DELETE", + "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours +}); + +export class HonoServer { + readonly sthis: SuperThis; + readonly msgP: MsgerParams; + readonly gestalt: Gestalt; + readonly logger: Logger; + readonly impl: HonoServerImpl; + constructor(sthis: SuperThis, msgP: MsgerParams, gestalt: Gestalt, impl: HonoServerImpl) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "HonoServer"); + this.msgP = msgP; + this.gestalt = gestalt; + this.impl = impl; + } + async start(app: Hono, port?: number): Promise { + await this.impl.start(app); + // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) + // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) + const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); + app.put("/fp", async (c) => { + const rMsg = await exception2Result(() => c.req.json()); + if (rMsg.isErr()) { + c.status(500); + return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rMsg.Err())); + } + this.impl.headers.Items().forEach((i) => { + c.res.headers.append(i[0], i[1][0]); + }); + return dispatcher.dispatch(rMsg.Ok(), (msg) => c.json(msg)); + }); + app.get("/ws", async (c, next) => { + this.impl.headers.AsHeaders().forEach((v, k) => c.res.headers.set(k, v)); + const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); + if (rReqOpen.isErr()) { + c.status(500); + return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rReqOpen.Err())); + } + const reqOpen = rReqOpen.Ok(); + if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { + c.status(401); + return c.json( + buildErrorMsg(this.sthis, this.sthis.logger, reqOpen, this.logger.Error().Msg("expected reqOpen").AsError()) + ); + } + const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); + dispatcher.addConn(reqOpen.conn); + return this.impl.upgradeWebSocket((_c) => ({ + onOpen: () => { + // console.log('Connection opened', c.req.url) + }, + onError: (error) => { + this.logger.Error().Err(error).Msg("WebSocket error"); + }, + onMessage: async (event, ws) => { + // console.log('onMsg event', event, event.data); + dispatcher.dispatch(this.msgP.ende.decode(await top_uint8(event.data)), (msg) => { + const str = this.msgP.ende.encode(msg); + ws.send(str); + }); + }, + onClose: () => { + // console.log('Connection closed') + }, + }))(c, next); + }); + await this.impl.serve(app, port); + return this; + } + async close() { + return this.impl.close(); + } +} + +export async function honoServer(_sthis: SuperThis, _msgP: MsgerParams, _gestalt: Gestalt) { + const rt = runtimeFn(); + if (rt.isNodeIsh) { + // const { NodeHonoServer } = await import("./node-hono-server.js"); + // return new HonoServer(sthis, msgP, gestalt, new NodeHonoServer()); + } + throw new Error("Not implemented"); +} diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index 283c0211..f3d05f7c 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -1,9 +1,8 @@ import { Logger, Result, URI, exception2Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { selectRandom } from "./msg-request.js"; import { MsgBase, MsgIsResOpen, ReqOpen, ResOpen, buildErrorMsg, MsgerParams } from "./msg-types.js"; -import { ExchangedGestalt, MsgConnection, OnMsgFn, timeout, UnReg } from "./msger.js"; +import { ExchangedGestalt, MsgConnection, OnMsgFn, selectRandom, timeout, UnReg } from "./msger.js"; export class HttpConnection implements MsgConnection { readonly sthis: SuperThis; @@ -24,18 +23,24 @@ export class HttpConnection implements MsgConnection { readonly #onMsg = new Map(); - constructor(sthis: SuperThis, reqOpen: ReqOpen | undefined, uris: URI[], msgP: MsgerParams, exGestalt: ExchangedGestalt) { + constructor( + sthis: SuperThis, + reqOpen: ReqOpen | undefined, + uris: URI[], + msgP: MsgerParams, + exGestalt: ExchangedGestalt + ) { this.sthis = sthis; this.logger = ensureLogger(sthis, "HttpConnection"); this.msgParam = msgP; this.baseURIs = uris; this.qsOpen = { req: reqOpen }; - this.exchangedGestalt = exGestalt + this.exchangedGestalt = exGestalt; } async start(): Promise> { if (this.qsOpen.req) { - const sOpen = await this.request(this.qsOpen.req, { waitFor: MsgIsResOpen }) + const sOpen = await this.request(this.qsOpen.req, { waitFor: MsgIsResOpen }); if (!MsgIsResOpen(sOpen)) { return Result.Err(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); } @@ -55,7 +60,7 @@ export class HttpConnection implements MsgConnection { } onMsg(fn: OnMsgFn): UnReg { - const key = this.sthis.nextId().str + const key = this.sthis.nextId().str; this.#onMsg.set(key, fn); return () => this.#onMsg.delete(key); } @@ -66,47 +71,70 @@ export class HttpConnection implements MsgConnection { headers.append("Accept", this.msgParam.mime); const rReqBody = exception2Result(() => this.msgParam.ende.encode(req)); if (rReqBody.isErr()) { - return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, - this.logger.Error().Err(rReqBody.Err()).Any("req", req).Msg("encode error").AsError() - )); + return this.toMsg( + buildErrorMsg( + this.sthis, + this.logger, + req, + this.logger.Error().Err(rReqBody.Err()).Any("req", req).Msg("encode error").AsError() + ) + ); } headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); - const url = selectRandom(this.baseURIs) + const url = selectRandom(this.baseURIs); this.logger.Debug().Url(url).Any("body", req).Msg("request"); - const rRes = await exception2Result(() => timeout(this.msgParam.timeout, fetch(url.toString(), { - method: "PUT", - headers, - body: rReqBody.Ok(), - }))); + const rRes = await exception2Result(() => + timeout( + this.msgParam.timeout, + fetch(url.toString(), { + method: "PUT", + headers, + body: rReqBody.Ok(), + }) + ) + ); this.logger.Debug().Url(url).Any("body", rRes).Msg("response"); if (rRes.isErr()) { - return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, - this.logger.Error().Err(rRes).Msg("fetch error").AsError() - )); + return this.toMsg( + buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Err(rRes).Msg("fetch error").AsError()) + ); } const res = rRes.Ok(); if (!res.ok) { return this.toMsg( - buildErrorMsg(this.sthis, this.logger, req, this.logger.Error() - .Url(url) - .Str("status", res.status.toString()) - .Str("statusText", res.statusText).Msg("HTTP Error").AsError(), - await res.text())); + buildErrorMsg( + this.sthis, + this.logger, + req, + this.logger + .Error() + .Url(url) + .Str("status", res.status.toString()) + .Str("statusText", res.statusText) + .Msg("HTTP Error") + .AsError(), + await res.text() + ) + ); } const data = new Uint8Array(await res.arrayBuffer()); const ret = await exception2Result(async () => this.msgParam.ende.decode(data) as S); if (ret.isErr()) { - return this.toMsg(buildErrorMsg(this.sthis, this.logger, req, - this.logger.Error().Err(ret.Err()).Msg("decode error").AsError(), - this.sthis.txt.decode(data) - )); + return this.toMsg( + buildErrorMsg( + this.sthis, + this.logger, + req, + this.logger.Error().Err(ret.Err()).Msg("decode error").AsError(), + this.sthis.txt.decode(data) + ) + ); } - return this.toMsg(ret.Ok()) + return this.toMsg(ret.Ok()); } // toOnMessage(msg: WithErrorMsg): Result> { // this.mec.msgFn?.(msg as unknown as MessageEvent); // return Result.Ok(msg); // } - } diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts new file mode 100644 index 00000000..77df873b --- /dev/null +++ b/src/cloud/msg-dispatch.ts @@ -0,0 +1,61 @@ +import { HttpHeader, Logger, Result } from "@adviser/cement"; +import { SuperThis, ensureLogger } from "@fireproof/core"; +import { + Gestalt, + MsgBase, + MsgIsReqGestalt, + buildResGestalt, + MsgIsReqOpen, + buildErrorMsg, + buildResOpen, + Connection, +} from "./msg-types.js"; + +export class MsgDispatcher { + readonly sthis: SuperThis; + readonly logger: Logger; + readonly conns = new Map(); + readonly gestalt: Gestalt; + + constructor(sthis: SuperThis, gestalt: Gestalt) { + this.sthis = sthis; + this.logger = ensureLogger(sthis, "Dispatcher"); + this.gestalt = gestalt; + } + + addConn(aConn: Connection): Result { + const key = [aConn.key.ledgerName, aConn.key.tenantId].join(":"); + let conn = this.conns.get(key); + if (!conn) { + if (this.conns.size > 0) { + return Result.Err("connection"); + } + conn = { ...aConn, resId: this.sthis.nextId().str }; + this.conns.set(key, conn); + } + if (conn.reqId !== aConn.reqId) { + return Result.Err("unexpected reqId"); + } + return Result.Ok(conn); + } + + dispatch(msg: MsgBase, send: (msg: MsgBase) => void) { + switch (true) { + case MsgIsReqGestalt(msg): + return send(buildResGestalt(msg, this.gestalt)); + case MsgIsReqOpen(msg): { + if (!msg.conn) { + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); + } + /* DDoS protection */ + const rConn = this.addConn(msg.conn); + if (rConn.isErr()) { + return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); + } + return send(buildResOpen(this.sthis, msg, rConn.Ok().resId)); + } + default: + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); + } + } +} diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts index 34fb56c6..31ef9814 100644 --- a/src/cloud/msg-processor.ts +++ b/src/cloud/msg-processor.ts @@ -33,13 +33,12 @@ import { import { calculatePreSignedUrl } from "./pre-signed-url.js"; import { SuperThis } from "@fireproof/core"; -export type WithErrorMsg = T | ErrorMsg +export type WithErrorMsg = T | ErrorMsg; export interface CtxBase { readonly logger: Logger; } - export interface ReqOptResCtx extends ReqOptRes { readonly ctx?: C; } @@ -48,7 +47,6 @@ export interface ReqResCtx { dispatch( decodeFn: () => Promise @@ -74,18 +72,16 @@ export interface RequestOpts { // close(): Promise; // } - export abstract class MsgProcessorBase implements MsgProcessor { - readonly logger: Logger; - readonly serverId: string - readonly ctx: O - readonly sthis: SuperThis + readonly serverId: string; + readonly ctx: O; + readonly sthis: SuperThis; constructor(sthis: SuperThis, logger: Logger, ctx: O, serverId: string) { - this.serverId = serverId - this.logger = logger - this.ctx = ctx - this.sthis = sthis + this.serverId = serverId; + this.logger = logger; + this.ctx = ctx; + this.sthis = sthis; } async dispatch( @@ -98,11 +94,11 @@ export abstract class MsgProcessorBase return { req: errMsg as unknown as Q, res: errMsg, - ctx: this.ctx + ctx: this.ctx, }; } const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, this.ctx); - const ctx = { ...(optCtx || this.ctx) } + const ctx = { ...(optCtx || this.ctx) }; switch (true) { case MsgIsReqGestalt(req): return { @@ -115,13 +111,17 @@ export abstract class MsgProcessorBase case MsgIsReqGetWAL(req): return { req, - res: (await this.signedUrl({ - ...req, params: { - ...req.params, - method: "GET", - store: getStoreFromType(req).store - } - }, ctx)) as S | ErrorMsg, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "GET", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, ctx, }; @@ -136,13 +136,17 @@ export abstract class MsgProcessorBase } return { req, - res: (await this.signedUrl({ - ...req, params: { - ...req.params, - method: "PUT", - store: getStoreFromType(req).store - } - }, ctx)) as S | ErrorMsg, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "PUT", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, ctx, }; @@ -150,17 +154,20 @@ export abstract class MsgProcessorBase case MsgIsReqDelWAL(req): return { req, - res: (await this.signedUrl({ - ...req, params: { - ...req.params, - method: "DELETE", - store: getStoreFromType(req).store - } - }, ctx)) as S | ErrorMsg, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "DELETE", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, ctx, }; - // case MsgIsReqSignedUrl(req): // return { // req, @@ -252,5 +259,4 @@ export abstract class MsgProcessorBase connId: ctx.group.connId, }); } - } diff --git a/src/cloud/msg-request.ts b/src/cloud/msg-request.ts index e481325c..51facafe 100644 --- a/src/cloud/msg-request.ts +++ b/src/cloud/msg-request.ts @@ -1,211 +1,207 @@ -import { Future, Logger, exception2Result, Result, CoerceURI, KeyedResolvOnce, URI } from "@adviser/cement"; -import { SuperThis, } from "@fireproof/core"; -import { RequestOpts, } from "./msg-processor.js"; -import { MsgBase, AuthType, Gestalt, defaultGestalt, ResGestalt, ReqGestalt, MsgIsResGestalt, MsgIsError, } from "./msg-types.js"; - -import * as json from 'multiformats/codecs/json'; -import * as cborg from '@fireproof/vendor/cborg'; -import { MsgConnection } from "./msger.js"; - -export interface EnDeCoder { - encode(node: T): Uint8Array; - decode(data: Uint8Array): T; -} - -export interface WaitForTid { - readonly tid: string; - readonly future: Future; - // undefined match all - readonly waitFor: (msg: MsgBase) => boolean; -} - -export interface FetchGestaltParams { - readonly auth?: AuthType; - readonly sthis: SuperThis; - readonly gestaltURL: URI; - readonly uniqServerId?: string; - readonly getConn: () => Promise; -} - -export interface HttpConnectionParams { - readonly gestaltURL: CoerceURI; - readonly fetchConnection?: MsgConnection; - readonly ende?: EnDeCoder; - readonly uniqServerId?: string; -} - -export type RequestFN = (req: Q, opts: RequestOpts) => Promise> - -const serverId = "FP-Universal-Client" - -export function encoded(logger: Logger, g: "JSON" | "CBOR") { - let ende: EnDeCoder - let mime: string - switch (g) { - case "JSON": - ende = json - mime = "application/json" - break; - case "CBOR": - ende = cborg - mime = "application/cbor" - break; - default: - throw logger.Error().Str("typ", g).Msg(`Unknown encoding: ${g}`).AsError() - } - return { ende, mime } -} - -const getGestalts = new KeyedResolvOnce(); - -async function fetchGestalt(fgp: FetchGestaltParams): Promise { - return getGestalts.get(fgp.gestaltURL.toString()).once(async () => { - const conn = await fgp.getConn(); - const rGestalt = await conn.request({ - type: "reqGestalt", - tid: fgp.sthis.nextId().str, - version: serverId, - gestalt: defaultGestalt({ id: fgp.uniqServerId || serverId }), - }, { waitFor: MsgIsResGestalt }); - if (MsgIsError(rGestalt)) { - throw Error(rGestalt.message) - } - const gestalt = rGestalt.gestalt - const ende = encoded(fgp.sthis.logger, gestalt.encodings[0]) - return { - ende: ende.ende, - mime: ende.mime, - auth: gestalt.auth, - gestalt: gestalt - } - }) -} - -export function selectRandom(arr: T[]): T { - return arr[Math.floor(Math.random() * arr.length)]; -} - -export interface MsgErrorClose { - readonly msgFn: (msg: MessageEvent) => void; - readonly errFn: (err: Event) => void; - readonly closeFn: () => void; - readonly openFn: () => void; -} - - - -export interface GestaltParams { - readonly auth?: AuthType; - readonly sthis: SuperThis; - readonly gestaltURL: URI; - readonly uniqServerId?: string; -} - -const keyedHttpConnection = new KeyedResolvOnce(); -function httpFactory(sthis: SuperThis, uniqServerId: string, auth?: AuthType): (() => Promise) { - return () => keyedHttpConnection.get(uniqServerId || serverId).once(async () => { - return new HttpConnection(sthis, { - ende: json, - mime: "application/json", - auth: auth, - params: defaultGestalt(uniqServerId || serverId, false), - }) - }) -} - -const keyedWSConnection = new KeyedResolvOnce(); - -export interface Attachable { - attach(t: T): Promise -} - -export class WSAttachable implements Attachable { - readonly gestalt: MsgerParams - readonly sthis: SuperThis - readonly waitForTid = new Map(); - constructor(sthis: SuperThis, gestalt: MsgerParams) { - this.gestalt = gestalt - this.sthis = sthis - } - attach(t: WebSocket): Promise { - return keyedWSConnection.get(this.gestalt.params.id).once(async () => { - const c = new WSAttachConnection(this.sthis, t, this.waitForTid, { - openFn: () => this.open(t), - errFn: (err) => this.error(t, err), - msgFn: (msg) => this.msg(t, msg), - closeFn: () => this.close(t) - }) - return c - }) - } - - open(ws: WebSocket) { - this.sthis.logger.Info().Msg("open") - } - - error(ws: WebSocket, err: Event) { - this.sthis.logger.Error().Msg("error") - - } - msg(ws: WebSocket, msg: MessageEvent) { - this.sthis.logger.Info().Any("msg", msg).Msg("msg") - ws.onmessage = async (event) => { - const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); - if (rMsg.isErr()) { - this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); - return; - } - const msg = rMsg.Ok(); - const waitFor = this.waitForTid.get(msg.tid); - if (waitFor) { - if (MsgIsError(msg)) { - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } else if (waitFor.type) { - // what for a specific type - if (waitFor.type === msg.type) { - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } else { - this.msgCallbacks.forEach((cb) => cb(msg)); - } - } else { - // wild-card - this.msgCallbacks.forEach((cb) => cb(msg)); - this.waitForTid.delete(msg.tid); - waitFor.future.resolve(msg); - } - } else { - this.msgCallbacks.forEach((cb) => cb(msg)); - } - }; - } - - close(ws: WebSocket) { - this.sthis.logger.Info().Msg("close") - } - - // this.params = params; - -} - -export async function getAttachable(p: FetchGestaltParams): Promise> { - const g = await fetchGestalt({ - gestaltURL: p.gestaltURL, - sthis: p.sthis, - getConn: httpFactory(p.sthis, p.uniqServerId || serverId, p.auth), - }) - if (g.params.wsEndpoints.length > 0) { - return new WSAttachable(p.sthis, g) as Attachable - } - return { - attach: async () => new HttpConnection(p.sthis, g) - } -} +// import { Future, Logger, exception2Result, Result, CoerceURI, KeyedResolvOnce, URI } from "@adviser/cement"; +// import { SuperThis, } from "@fireproof/core"; +// import { RequestOpts, } from "./msg-processor.js"; +// import { MsgBase, AuthType, Gestalt, defaultGestalt, ResGestalt, ReqGestalt, MsgIsResGestalt, MsgIsError, } from "./msg-types.js"; + +// import * as json from 'multiformats/codecs/json'; +// import * as cborg from '@fireproof/vendor/cborg'; +// import { MsgConnection } from "./msger.js"; + +// export interface EnDeCoder { +// encode(node: T): Uint8Array; +// decode(data: Uint8Array): T; +// } + +// export interface WaitForTid { +// readonly tid: string; +// readonly future: Future; +// // undefined match all +// readonly waitFor: (msg: MsgBase) => boolean; +// } + +// export interface FetchGestaltParams { +// readonly auth?: AuthType; +// readonly sthis: SuperThis; +// readonly gestaltURL: URI; +// readonly uniqServerId?: string; +// readonly getConn: () => Promise; +// } + +// export interface HttpConnectionParams { +// readonly gestaltURL: CoerceURI; +// readonly fetchConnection?: MsgConnection; +// readonly ende?: EnDeCoder; +// readonly uniqServerId?: string; +// } + +// export type RequestFN = (req: Q, opts: RequestOpts) => Promise> + +// const serverId = "FP-Universal-Client" + +// export function encoded(logger: Logger, g: "JSON" | "CBOR") { +// let ende: EnDeCoder +// let mime: string +// switch (g) { +// case "JSON": +// ende = json +// mime = "application/json" +// break; +// case "CBOR": +// ende = cborg +// mime = "application/cbor" +// break; +// default: +// throw logger.Error().Str("typ", g).Msg(`Unknown encoding: ${g}`).AsError() +// } +// return { ende, mime } +// } + +// const getGestalts = new KeyedResolvOnce(); + +// async function fetchGestalt(fgp: FetchGestaltParams): Promise { +// return getGestalts.get(fgp.gestaltURL.toString()).once(async () => { +// const conn = await fgp.getConn(); +// const rGestalt = await conn.request({ +// type: "reqGestalt", +// tid: fgp.sthis.nextId().str, +// version: serverId, +// gestalt: defaultGestalt({ id: fgp.uniqServerId || serverId }), +// }, { waitFor: MsgIsResGestalt }); +// if (MsgIsError(rGestalt)) { +// throw Error(rGestalt.message) +// } +// const gestalt = rGestalt.gestalt +// const ende = encoded(fgp.sthis.logger, gestalt.encodings[0]) +// return { +// ende: ende.ende, +// mime: ende.mime, +// auth: gestalt.auth, +// gestalt: gestalt +// } +// }) +// } + +// export function selectRandom(arr: T[]): T { +// return arr[Math.floor(Math.random() * arr.length)]; +// } + +// export interface MsgErrorClose { +// readonly msgFn: (msg: MessageEvent) => void; +// readonly errFn: (err: Event) => void; +// readonly closeFn: () => void; +// readonly openFn: () => void; +// } + +// export interface GestaltParams { +// readonly auth?: AuthType; +// readonly sthis: SuperThis; +// readonly gestaltURL: URI; +// readonly uniqServerId?: string; +// } + +// const keyedHttpConnection = new KeyedResolvOnce(); +// function httpFactory(sthis: SuperThis, uniqServerId: string, auth?: AuthType): (() => Promise) { +// return () => keyedHttpConnection.get(uniqServerId || serverId).once(async () => { +// return new HttpConnection(sthis, { +// ende: json, +// mime: "application/json", +// auth: auth, +// params: defaultGestalt(uniqServerId || serverId, false), +// }) +// }) +// } +// const keyedWSConnection = new KeyedResolvOnce(); +// export interface Attachable { +// attach(t: T): Promise +// } + +// export class WSAttachable implements Attachable { +// readonly gestalt: MsgerParams +// readonly sthis: SuperThis +// readonly waitForTid = new Map(); +// constructor(sthis: SuperThis, gestalt: MsgerParams) { +// this.gestalt = gestalt +// this.sthis = sthis +// } +// attach(t: WebSocket): Promise { +// return keyedWSConnection.get(this.gestalt.params.id).once(async () => { +// const c = new WSAttachConnection(this.sthis, t, this.waitForTid, { +// openFn: () => this.open(t), +// errFn: (err) => this.error(t, err), +// msgFn: (msg) => this.msg(t, msg), +// closeFn: () => this.close(t) +// }) +// return c +// }) +// } + +// open(ws: WebSocket) { +// this.sthis.logger.Info().Msg("open") +// } + +// error(ws: WebSocket, err: Event) { +// this.sthis.logger.Error().Msg("error") + +// } +// msg(ws: WebSocket, msg: MessageEvent) { +// this.sthis.logger.Info().Any("msg", msg).Msg("msg") +// ws.onmessage = async (event) => { +// const rMsg = await exception2Result(() => JSON.parse(event.data) as MsgBase); +// if (rMsg.isErr()) { +// this.logger.Error().Err(rMsg).Any(event.data).Msg("Invalid message"); +// return; +// } +// const msg = rMsg.Ok(); +// const waitFor = this.waitForTid.get(msg.tid); +// if (waitFor) { +// if (MsgIsError(msg)) { +// this.msgCallbacks.forEach((cb) => cb(msg)); +// this.waitForTid.delete(msg.tid); +// waitFor.future.resolve(msg); +// } else if (waitFor.type) { +// // what for a specific type +// if (waitFor.type === msg.type) { +// this.msgCallbacks.forEach((cb) => cb(msg)); +// this.waitForTid.delete(msg.tid); +// waitFor.future.resolve(msg); +// } else { +// this.msgCallbacks.forEach((cb) => cb(msg)); +// } +// } else { +// // wild-card +// this.msgCallbacks.forEach((cb) => cb(msg)); +// this.waitForTid.delete(msg.tid); +// waitFor.future.resolve(msg); +// } +// } else { +// this.msgCallbacks.forEach((cb) => cb(msg)); +// } +// }; +// } + +// close(ws: WebSocket) { +// this.sthis.logger.Info().Msg("close") +// } + +// // this.params = params; + +// } + +// export async function getAttachable(p: FetchGestaltParams): Promise> { +// const g = await fetchGestalt({ +// gestaltURL: p.gestaltURL, +// sthis: p.sthis, +// getConn: httpFactory(p.sthis, p.uniqServerId || serverId, p.auth), +// }) +// if (g.params.wsEndpoints.length > 0) { +// return new WSAttachable(p.sthis, g) as Attachable +// } +// return { +// attach: async () => new HttpConnection(p.sthis, g) +// } +// } // export class ConnectionImpl implements Connection { // readonly sthis: SuperThis; @@ -213,13 +209,10 @@ export async function getAttachable(p: FetchGestaltParams): Promise(req: Q, opts: RequestOpts): Promise> { // } - // } // export class ConnectionImpl implements Connection { diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 25e2f2d5..84ed96ac 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,8 +1,20 @@ +import { Future } from "@adviser/cement"; import { CRDTEntry, Logger, SuperThis } from "@fireproof/core"; -import { EnDeCoder } from "./msg-request.js"; export const VERSION = "FP-MSG-1.0"; +export interface EnDeCoder { + encode(node: T): Uint8Array; + decode(data: Uint8Array): T; +} + +export interface WaitForTid { + readonly tid: string; + readonly future: Future; + // undefined match all + readonly waitFor: (msg: MsgBase) => boolean; +} + // export interface ConnId { // readonly connId: string; // } @@ -63,11 +75,9 @@ export function MsgIsQSError(rq: ReqRes): rq is ReqRes = { +const reqToRes: Record = { reqGetData: { store: "data", resType: "resGetData" }, reqPutData: { store: "data", resType: "resPutData" }, reqDelData: { store: "data", resType: "resDelData" }, reqGetWAL: { store: "wal", resType: "resGetWAL" }, reqPutWAL: { store: "wal", resType: "resPutWAL" }, reqDelWAL: { store: "wal", resType: "resDelWAL" }, -} +}; export function getStoreFromType(req: MsgBase): StoreAndType { - return reqToRes[req.type] || (() => { throw new Error(`unknown req.type=${req.type}`) })(); + return ( + reqToRes[req.type] || + (() => { + throw new Error(`unknown req.type=${req.type}`); + })() + ); } export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { @@ -385,7 +405,14 @@ export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSign }; } -export function buildErrorMsg(sthis: SuperThis, logger: Logger, base: Partial, error: Error, body?: string, stack?: string[]): ErrorMsg { +export function buildErrorMsg( + sthis: SuperThis, + logger: Logger, + base: Partial, + error: Error, + body?: string, + stack?: string[] +): ErrorMsg { if (!stack && sthis.env.get("FP_STACK")) { stack = error.stack?.split("\n"); } @@ -394,7 +421,8 @@ export function buildErrorMsg(sthis: SuperThis, logger: Logger, base: Partial { readonly type: "reqPutWAL"; readonly payload: Uint8Array; // transfered via JSON base64 @@ -749,4 +776,4 @@ export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { export interface ResDelWAL extends Omit { readonly type: "resDelWAL"; -} \ No newline at end of file +} diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index f86aee94..7317fc8b 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -1,9 +1,20 @@ import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; -import { buildReqGestalt, defaultGestalt, Gestalt, MsgBase, MsgerParams, MsgIsResGestalt, ReqGestalt, ReqOpen, ResGestalt, ResOpen } from "./msg-types.js"; +import { + buildReqGestalt, + defaultGestalt, + EnDeCoder, + Gestalt, + MsgBase, + MsgerParams, + MsgIsResGestalt, + ReqGestalt, + ReqOpen, + ResGestalt, + ResOpen, +} from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; import { HttpConnection } from "./http-connection.js"; -import { EnDeCoder, selectRandom } from "./msg-request.js"; import { WSConnection } from "./ws-connection.js"; // const headers = { @@ -11,24 +22,28 @@ import { WSConnection } from "./ws-connection.js"; // "Accept": "application/json", // }; +export function selectRandom(arr: T[]): T { + return arr[Math.floor(Math.random() * arr.length)]; +} + export function timeout(ms: number, promise: Promise): Promise { - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - reject(new Error(`TIMEOUT after ${ms}ms`)) - }, ms) - promise - .then(resolve) - .catch(reject) - .finally(() => clearTimeout(timer)) - }) - } + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + reject(new Error(`TIMEOUT after ${ms}ms`)); + }, ms); + promise + .then(resolve) + .catch(reject) + .finally(() => clearTimeout(timer)); + }); +} -export type OnMsgFn = (msg: WithErrorMsg) => void -export type UnReg = () => void +export type OnMsgFn = (msg: WithErrorMsg) => void; +export type UnReg = () => void; export interface ExchangedGestalt { - readonly my: Gestalt; - readonly remote: Gestalt; + readonly my: Gestalt; + readonly remote: Gestalt; } export interface MsgConnection { @@ -36,104 +51,141 @@ export interface MsgConnection { // readonly params: ConnectionKey; conn?: ResOpen; readonly exchangedGestalt: ExchangedGestalt; - request(req: Q, opts: RequestOpts): Promise> + request(req: Q, opts: RequestOpts): Promise>; start(): Promise>; close(): Promise>; - onMsg(msg: OnMsgFn): UnReg + onMsg(msg: OnMsgFn): UnReg; } function jsonEnDe(sthis: SuperThis) { - return { - encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)), - decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)), - } satisfies EnDeCoder; + return { + encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)), + decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)), + } satisfies EnDeCoder; } export function defaultMsgParams(sthis: SuperThis, igs: Partial): MsgerParams { - return { - ende: igs.ende || jsonEnDe(sthis), - mime: igs.mime || "application/json", - protocol: igs.protocol || "http", - timeout: igs.timeout || 3000, - } satisfies MsgerParams; + return { + ende: jsonEnDe(sthis), + mime: "application/json", + protocol: "http", + timeout: 3000, + ...igs, + } satisfies MsgerParams; } export interface OpenParams { - readonly timeout: number; + readonly timeout: number; } export async function applyStart(prC: Promise>): Promise> { - const rC = await prC - if (rC.isErr()) { - return rC - } - const c = rC.Ok() - const r = await c.start() - if (r.isErr()) { - return Result.Err(r.Err()) - } - return rC + const rC = await prC; + if (rC.isErr()) { + return rC; + } + const c = rC.Ok(); + const r = await c.start(); + if (r.isErr()) { + return Result.Err(r.Err()); + } + return rC; } - - // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Msger { - static async openHttp(sthis: SuperThis, reqOpen: ReqOpen|undefined, urls: URI[], msgP: MsgerParams, exGestalt: ExchangedGestalt): Promise> { - return Result.Ok(new HttpConnection(sthis, reqOpen, urls, msgP, exGestalt)); + static async openHttp( + sthis: SuperThis, + reqOpen: ReqOpen | undefined, + urls: URI[], + msgP: MsgerParams, + exGestalt: ExchangedGestalt + ): Promise> { + return Result.Ok(new HttpConnection(sthis, reqOpen, urls, msgP, exGestalt)); + } + static async openWS( + sthis: SuperThis, + qOpen: ReqOpen, + url: URI, + msgP: MsgerParams, + exGestalt: ExchangedGestalt + ): Promise> { + let ws: WebSocket; + const { encode } = jsonEnDe(sthis); + url = url + .build() + .setParam("reqOpen", sthis.txt.decode(encode(qOpen))) + .URI(); + if (runtimeFn().isNodeIsh) { + const { WebSocket } = await import("ws"); + ws = new WebSocket(url.toString()) as unknown as WebSocket; + } else { + ws = new WebSocket(url.toString()); } - static async openWS(sthis: SuperThis, qOpen: ReqOpen, url: URI, msgP: MsgerParams, exGestalt: ExchangedGestalt): Promise> { - let ws: WebSocket; - const { encode } = jsonEnDe(sthis); - url = url.build().setParam("reqOpen", sthis.txt.decode(encode(qOpen))).URI(); - if (runtimeFn().isNodeIsh) { - const { WebSocket }= await import('ws'); - ws = new WebSocket(url.toString()) as unknown as WebSocket; - } else { - ws = new WebSocket(url.toString()); - } - return Result.Ok(new WSConnection(sthis, { - reqOpen: qOpen, - ws, - }, msgP, exGestalt)) + return Result.Ok( + new WSConnection( + sthis, + { + reqOpen: qOpen, + ws, + }, + msgP, + exGestalt + ) + ); + } + static async open( + sthis: SuperThis, + curl: CoerceURI, + qOpen: ReqOpen, + imsgP: MsgerParams + ): Promise> { + // initial exchange with JSON encoding + const jsGI = defaultMsgParams(sthis, { ...imsgP, ende: jsonEnDe(sthis) }); + const url = URI.from(curl); + const gs = defaultGestalt(imsgP, { id: "FP-Universal-Client" }); + /* + * request Gestalt with Http + */ + const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI, { my: gs, remote: gs }); + if (rHC.isErr()) { + return rHC; } - static async open(sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, imsgP: MsgerParams): Promise> { - // initial exchange with JSON encoding - const jsGI = defaultMsgParams(sthis, { ...imsgP, ende: jsonEnDe(sthis) }); - const url = URI.from(curl) - const gs = defaultGestalt(imsgP, {id: "FP-Universal-Client"}); - /* - * request Gestalt with Http - */ - const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI, { my: gs, remote: gs }); - if (rHC.isErr()) { - return rHC; - } - const hc = rHC.Ok(); - const resGestalt = await hc.request(buildReqGestalt(sthis, gs), { waitFor: MsgIsResGestalt }); - if (!MsgIsResGestalt(resGestalt)) { - return Result.Err(new Error("Invalid Gestalt")); - } - await hc.close(); - const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt; - const msgP = defaultMsgParams(sthis, imsgP); - if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) { - return applyStart(Msger.openHttp(sthis, qOpen, exGt.remote.httpEndpoints.map(i => BuildURI.from(url).resolve(i).URI()), msgP, exGt)); - } - return applyStart(Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt)); + const hc = rHC.Ok(); + const resGestalt = await hc.request(buildReqGestalt(sthis, gs), { + waitFor: MsgIsResGestalt, + }); + if (!MsgIsResGestalt(resGestalt)) { + return Result.Err(new Error("Invalid Gestalt")); } - - private constructor() { - /* */ + await hc.close(); + const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt; + const msgP = defaultMsgParams(sthis, imsgP); + if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) { + return applyStart( + Msger.openHttp( + sthis, + qOpen, + exGt.remote.httpEndpoints.map((i) => BuildURI.from(url).resolve(i).URI()), + msgP, + exGt + ) + ); } + return applyStart( + Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt) + ); + } - // readonly logger: Logger; - // readonly url: URI; - // readonly qs: ReqRes; - // constructor(logger: Logger, url: URI, qs: ReqRes) { - // this.logger = logger; - // this.url = url; - // this.qs = qs; - // } + private constructor() { + /* */ + } -} \ No newline at end of file + // readonly logger: Logger; + // readonly url: URI; + // readonly qs: ReqRes; + // constructor(logger: Logger, url: URI, qs: ReqRes) { + // this.logger = logger; + // this.url = url; + // this.qs = qs; + // } +} diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts new file mode 100644 index 00000000..b60f8fe1 --- /dev/null +++ b/src/cloud/node-hono-server.ts @@ -0,0 +1,41 @@ +import { UpgradeWebSocket } from "hono/ws"; +import { CORS, HonoServerImpl } from "./hono-server.js"; +import { HttpHeader } from "@adviser/cement"; +import { Hono } from "hono"; + +interface ServerType { + close(fn: () => void): void; +} + +type serveFn = (options: unknown, listeningListener?: ((info: unknown) => void) | undefined) => ServerType; + +export class NodeHonoServer implements HonoServerImpl { + upgradeWebSocket!: UpgradeWebSocket; + _injectWebSocket!: (t: unknown) => void; + _serve!: serveFn; + _server!: ServerType; + + readonly headers: HttpHeader; + constructor(headers?: HttpHeader) { + this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + } + + async start(app: Hono): Promise { + const { createNodeWebSocket } = await import("@hono/node-ws"); + const { serve } = await import("@hono/node-server"); + this._serve = serve as serveFn; + const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }); + this.upgradeWebSocket = upgradeWebSocket; + this._injectWebSocket = injectWebSocket as (t: unknown) => void; + } + + async serve(app: Hono, port: number): Promise { + await new Promise((resolve) => { + this._server = this._serve({ fetch: app.fetch, port }, () => resolve()); + }); + this._injectWebSocket(this._server); + } + async close(): Promise { + return new Promise((res) => this._server.close(() => res())); + } +} diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index b43e75e8..13159eb3 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -1,8 +1,16 @@ import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { WaitForTid } from "./msg-request.js"; -import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, ResOpen, MsgIsResOpen, MsgerParams } from "./msg-types.js"; +import { + MsgBase, + MsgIsError, + buildErrorMsg, + ReqOpen, + ResOpen, + MsgIsResOpen, + MsgerParams, + WaitForTid, +} from "./msg-types.js"; import { ExchangedGestalt, MsgConnection, OnMsgFn, UnReg } from "./msger.js"; export interface WSReqOpen { @@ -28,8 +36,8 @@ export class WSConnection implements MsgConnection { readonly waitForTid = new Map(); opened = false; - get conn(): ResOpen|undefined { - return this.wqs.resOpen + get conn(): ResOpen | undefined { + return this.wqs.resOpen; } constructor(sthis: SuperThis, wsq: WSReqOpen, msgP: MsgerParams, exGestalt: ExchangedGestalt) { @@ -43,39 +51,46 @@ export class WSConnection implements MsgConnection { async start(): Promise> { const onOpenFuture: Future> = new Future>(); const timer = setTimeout(() => { - const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError() + const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError(); this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, err)); onOpenFuture.resolve(Result.Err(err)); }, this.msgP.timeout); this.wqs.ws.onopen = () => { - onOpenFuture.resolve(Result.Ok(undefined)); - this.opened = true; - } + onOpenFuture.resolve(Result.Ok(undefined)); + this.opened = true; + }; this.wqs.ws.onerror = (ierr) => { - const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError() - onOpenFuture.resolve(Result.Err(err)); - this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal", conn: this.conn } as MsgBase, err)); - } + const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError(); + onOpenFuture.resolve(Result.Err(err)); + this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal", conn: this.conn } as MsgBase, err)); + }; this.wqs.ws.onmessage = (evt) => { - if (!this.opened) { - this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, this.logger.Error().Msg("Received message before onOpen").AsError())); - } - this.#wsOnMessage(evt); - } + if (!this.opened) { + this.toMsg( + buildErrorMsg( + this.sthis, + this.logger, + { tid: "internal" } as MsgBase, + this.logger.Error().Msg("Received message before onOpen").AsError() + ) + ); + } + this.#wsOnMessage(evt); + }; this.wqs.ws.onclose = () => { this.opened = false; this.close().catch((ierr) => { - const err = this.logger.Error().Err(ierr).Msg("close error").AsError() + const err = this.logger.Error().Err(ierr).Msg("close error").AsError(); onOpenFuture.resolve(Result.Err(err)); this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, err)); }); - } + }; /* wait for onOpen */ const rOpen = await onOpenFuture.asPromise().finally(() => clearTimeout(timer)); if (rOpen.isErr()) { return rOpen; } - const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }) + const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }); if (!MsgIsResOpen(resOpen)) { return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); } @@ -106,7 +121,7 @@ export class WSConnection implements MsgConnection { waitFor.future.resolve(msg); } } - } + }; async close(): Promise> { this.#onClose.forEach((fn) => fn()); @@ -126,13 +141,13 @@ export class WSConnection implements MsgConnection { } onMsg(fn: OnMsgFn): UnReg { - const key = this.sthis.nextId().str + const key = this.sthis.nextId().str; this.#onMsg.set(key, fn); return () => this.#onMsg.delete(key); } onClose(fn: UnReg): UnReg { - const key = this.sthis.nextId().str + const key = this.sthis.nextId().str; this.#onClose.set(key, fn); return () => this.#onClose.delete(key); } @@ -144,12 +159,11 @@ export class WSConnection implements MsgConnection { const future = new Future(); this.waitForTid.set(req.tid, { tid: req.tid, future, waitFor: opts.waitFor }); await this.sendMsg(req); - return future.asPromise() + return future.asPromise(); } // toOnMessage(msg: WithErrorMsg): Result> { // this.mec.msgFn?.(msg as unknown as MessageEvent); // return Result.Ok(msg); // } - } diff --git a/src/coerce-binary.ts b/src/coerce-binary.ts index a04a9de6..5a4169b2 100644 --- a/src/coerce-binary.ts +++ b/src/coerce-binary.ts @@ -1,4 +1,6 @@ -export async function top_uint8(input: string | ArrayBuffer | ArrayBufferView | Uint8Array | SharedArrayBuffer | Blob): Promise { +export async function top_uint8( + input: string | ArrayBuffer | ArrayBufferView | Uint8Array | SharedArrayBuffer | Blob +): Promise { if (input instanceof Blob) { return new Uint8Array(await input.arrayBuffer()); } From b0838d9826d15ed67bcb8d575724a73d50c85b94 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Wed, 25 Dec 2024 15:10:13 +0100 Subject: [PATCH 35/83] chore: Get/Put/Delete.Data/WAL --- package.json | 4 +- pnpm-lock.yaml | 12 +- src/cloud/backend/cf-hono-server.ts | 70 ++- src/cloud/backend/env.d.ts | 3 + ...p-meta-groups.ts => fp-meta-groups.ts-off} | 0 src/cloud/backend/server.ts | 458 +++++++++-------- src/cloud/backend/wrangler.toml | 15 +- src/cloud/connection.test.ts | 198 +++++-- src/cloud/hono-server.ts | 96 ++-- src/cloud/http-connection.ts | 44 +- src/cloud/msg-dispatch.ts | 68 ++- ...{msg-processor.ts => msg-processor.ts-off} | 3 +- src/cloud/msg-type-meta.ts | 262 ++++++++++ src/cloud/msg-types-data.ts | 127 +++++ src/cloud/msg-types-wal.ts | 123 +++++ src/cloud/msg-types.ts | 485 ++++-------------- src/cloud/msger.ts | 8 +- src/cloud/node-hono-server.ts | 35 +- src/cloud/pre-signed-url.ts | 84 ++- src/cloud/ws-connection.ts | 34 +- 20 files changed, 1340 insertions(+), 789 deletions(-) rename src/cloud/backend/{fp-meta-groups.ts => fp-meta-groups.ts-off} (100%) rename src/cloud/{msg-processor.ts => msg-processor.ts-off} (98%) create mode 100644 src/cloud/msg-type-meta.ts create mode 100644 src/cloud/msg-types-data.ts create mode 100644 src/cloud/msg-types-wal.ts diff --git a/package.json b/package.json index dffface1..29a7c0a0 100644 --- a/package.json +++ b/package.json @@ -98,10 +98,10 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.44" + "@adviser/cement": "^0.2.45" }, "dependencies": { - "@adviser/cement": "^0.2.44", + "@adviser/cement": "^0.2.45", "@aws-sdk/client-s3": "^3.705.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b79c0d6e..90d28d46 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.44 - version: 0.2.44(typescript@5.7.2) + specifier: ^0.2.45 + version: 0.2.45(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.705.0 version: 3.705.0 @@ -216,8 +216,8 @@ importers: packages: - '@adviser/cement@0.2.44': - resolution: {integrity: sha512-IxmNkCSpST2FBeHqhk1RGxcb6pF8FZMSFbPpNUi0Drx3v219gNl5Q1gOQ2TWPqblTvMO942MqSE/QlgEppshgg==} + '@adviser/cement@0.2.45': + resolution: {integrity: sha512-322C+IWgUhjomzTKohy86maLoOASUf5ZrIAs01dfZF2NLey/6GlUi3vehR4MpDXo/8lceuvemVCw/wd7kmWOtg==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -4074,7 +4074,7 @@ packages: snapshots: - '@adviser/cement@0.2.44(typescript@5.7.2)': + '@adviser/cement@0.2.45(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4986,7 +4986,7 @@ snapshots: '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.2.44(typescript@5.7.2) + '@adviser/cement': 0.2.45(typescript@5.7.2) '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index c2f3e39e..af3c7a86 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -1,20 +1,70 @@ -import { HttpHeader } from "@adviser/cement"; -import { Hono } from "hono"; -import { UpgradeWebSocket } from "hono/ws"; -import { HonoServerImpl, CORS } from "../hono-server.js"; +import { HttpHeader, Logger, Result, URI } from "@adviser/cement"; +import { Context, Hono } from "hono"; +import { HonoServerImpl, CORS, ConnMiddleware } from "../hono-server.js"; +import { WSEvents } from "hono/ws"; +import { buildErrorMsg, EnDeCoder } from "../msg-types.js"; +import { ensureLogger, SuperThis } from "@fireproof/core"; +import { Env } from "./env.js"; +import { RequestInfo as CFRequestInfo } from "@cloudflare/workers-types"; +import { calculatePreSignedUrl, PreSignedConnMsg } from "../pre-signed-url.js"; export class CFHonoServer implements HonoServerImpl { - upgradeWebSocket!: UpgradeWebSocket; + // _upgradeWebSocket?: UpgradeWebSocket readonly headers: HttpHeader; - constructor(headers?: HttpHeader) { - this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); - // console.log("CFHonoServer", this.headers.AsHeaderInit()) + readonly sthis: SuperThis; + readonly logger: Logger; + readonly ende: EnDeCoder; + readonly env: Env; + constructor(sthis: SuperThis, ende: EnDeCoder, env: Env, headers?: HttpHeader) { + this.headers = HttpHeader.from(headers).Merge(CORS); + this.sthis = sthis; + this.logger = ensureLogger(sthis, "CFHonoServer"); + this.ende = ende; + this.env = env; + } + + // getDurableObject(conn: Connection) { + // const id = env.FP_META_GROUPS.idFromName("fireproof"); + // const stub = env.FP_META_GROUPS.get(id); + // } + calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { + return calculatePreSignedUrl(p, { + storageUrl: URI.from(this.env.STORAGE_URL), + aws: { + accessKeyId: this.env.ACCESS_KEY_ID, + secretAccessKey: this.env.SECRET_ACCESS_KEY, + region: this.env.REGION, + }, + }); + } + + upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { + // if (!this._upgradeWebSocket) { + // throw new Error("upgradeWebSocket not implemented"); + // } + return async (conn, c, _next) => { + const upgradeHeader = c.req.header("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response( + this.ende.encode( + buildErrorMsg(this.sthis, this.logger, {}, new Error("Durable Object expected Upgrade: websocket")) + ), + { status: 426 } + ); + } + const env = c.env as Env; + const id = env.FP_META_GROUPS.idFromName([conn.key.tenant, conn.key.ledger].join(":")); + const dObj = env.FP_META_GROUPS.get(id); + c.env.WS_EVENTS = createEvents(c); + return dObj.fetch(c.req.raw as unknown as CFRequestInfo) as unknown as Promise; + // this._upgradeWebSocket!(createEvents)(c, next); + }; } async start(_app: Hono): Promise { - const { upgradeWebSocket } = await import("hono/cloudflare-workers"); - this.upgradeWebSocket = upgradeWebSocket; + // const { upgradeWebSocket } = await import("hono/cloudflare-workers"); + // this._upgradeWebSocket = upgradeWebSocket; } async serve(_app: Hono, _port?: number): Promise { diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index 4130c727..73c55d17 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -3,6 +3,7 @@ import type { DurableObjectNamespace } from "@cloudflare/workers-types"; import { FPMetaGroups } from "./fp-meta-groups.js"; +import { WSEvents } from "hono/ws"; export interface Env { // bucket: R2Bucket; @@ -28,6 +29,8 @@ export interface Env { MAX_IDLE_TIME?: string; FP_META_GROUPS: DurableObjectNamespace; + + WS_EVENTS: WSEvents; } // declare module "cloudflare:test" { diff --git a/src/cloud/backend/fp-meta-groups.ts b/src/cloud/backend/fp-meta-groups.ts-off similarity index 100% rename from src/cloud/backend/fp-meta-groups.ts rename to src/cloud/backend/fp-meta-groups.ts-off diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 62aab8a1..70435e03 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,5 +1,5 @@ // / -import { ResolveOnce } from "@adviser/cement"; +import { JSONFormatter, Logger, LoggerImpl, ResolveOnce, YAMLFormatter } from "@adviser/cement"; import { defaultGestalt } from "../msg-types.js"; // import { Hono } from "hono"; import { ensureSuperThis } from "@fireproof/core"; @@ -9,31 +9,32 @@ import { Hono } from "hono"; import { defaultMsgParams } from "../msger.js"; import { Env } from "./env.js"; import { CFHonoServer } from "./cf-hono-server.js"; +import { WSContext, WSEvents } from "hono/ws"; // function json(data: T, status = 200) { // return Response.json(data, { status, headers: CORS }); // } -// function ensureLogger(env: Env, module = "Fireproof"): Logger { -// const logger = new LoggerImpl() -// .With() -// .Module(module) -// .SetDebug(env.FP_DEBUG) -// .SetExposeStack(!!env.FP_STACK || false); -// switch (env.FP_FORMAT) { -// case "jsonice": -// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); -// break; -// case "yaml": -// logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); -// break; -// case "json": -// default: -// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); -// break; -// } -// return logger.Logger(); -// } +function ensureLogger(env: Env, module = "Fireproof"): Logger { + const logger = new LoggerImpl() + .With() + .Module(module) + .SetDebug(env.FP_DEBUG) + .SetExposeStack(!!env.FP_STACK || false); + switch (env.FP_FORMAT) { + case "jsonice": + logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); + break; + case "yaml": + logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); + break; + case "json": + default: + logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); + break; + } + return logger.Logger(); +} // interface MsgStats { // readonly msgSeq: number; @@ -66,207 +67,230 @@ import { CFHonoServer } from "./cf-hono-server.js"; // // const sthis = new NextIdImpl(); -export class FPMetaGroups extends DurableObject {} +export class FPMetaGroups extends DurableObject { + // readonly sessions: Map = new Map(); + // readonly lastMetaByTendant = new Map[]>(); -// export class FPMetaGroups extends DurableObject { -// // readonly sessions: Map = new Map(); -// // readonly lastMetaByTendant = new Map[]>(); + readonly logger: Logger; -// readonly logger: Logger; + readonly wsEvents: WSEvents = {}; -// constructor(ctx: DurableObjectState, env: Env) { -// super(ctx, env); -// this.logger = ensureLogger(env, "FPMetaGroups"); -// // this.ctx.getWebSockets().forEach((webSocket) => { -// // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; -// // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { -// // this.sessions.set(webSocket, fpMetaGroup); -// // } -// // }); -// } + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + this.logger = ensureLogger(env, "FPMetaGroups"); + // this.ctx.getWebSockets().forEach((webSocket) => { + // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; + // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { + // this.sessions.set(webSocket, fpMetaGroup); + // } + // }); + } -// async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { -// if (typeof msg !== "string") { -// this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); -// return; -// } + // injectWSEvents(wsEvents: WSEvents): void { + // Object.assign(this.wsEvents, wsEvents); + // } -// return CFMsgProcessor.dispatch( -// () => JSON.parse(msg.toString()), -// { env: this.env }, -// async (req: MsgBase, ictx: CFCtxBase) => { -// if (req.auth) { -// // do ucan magic -// } -// let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; -// group = { -// ...group, -// qs: { -// ...group.qs, -// q: { -// ...group.qs.q, -// [req.type]: { -// msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, -// }, -// }, -// }, -// connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), -// lastUsed: new Date(), -// } satisfies FPMetaGroup; -// ws.serializeAttachment(group); -// const ctx = { ...ictx, group } satisfies CFCtxWithGroup; -// return { req, ctx }; -// } -// ).then((qs) => { -// let group = { -// ...qs.ctx.group, -// qs: { -// ...qs.ctx.group.qs, -// s: { -// ...qs.ctx.group.qs.s, -// [qs.req.type]: { -// msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, -// }, -// }, -// }, -// } satisfies FPMetaGroup; -// switch (true) { -// case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): -// { -// group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; -// ws.serializeAttachment(group); -// // console.log("putMeta group", group); -// (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( -// buildUpdateMetaEvent(qs, { -// connId: qs.res.connId, -// subscriberId: "later-overriden", -// }) -// ); -// this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); -// } -// break; -// case MsgIsResSubscribeMeta(qs): -// { -// group = { ...group, group: qs.res } satisfies FPMetaGroup; -// // console.log("subscribeMeta group", group); -// ws.serializeAttachment(group); -// this.updateMeta({ -// connId: qs.res.connId, -// subscriberId: "later-overriden", -// tid: qs.res.tid, -// type: "updateMeta", -// key: qs.res.key, -// metaId: "later-overriden", -// metas: [], -// version: qs.res.version, -// }); -// } -// break; -// } -// // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); -// ws.send(JSON.stringify(qs.res)); -// }); -// } + webSocketError(_ws: WebSocket, error: unknown): void | Promise { + this.logger.Error().Any("error", error).Msg("webSocketError"); + this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); + } -// async fetch(req: Request): Promise { -// const path = URI.from(req.url).pathname; -// switch (path) { -// case "/fp": { -// const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); -// return json(rq.res, MsgIsQSError(rq) ? 422 : 200); -// } -// case "/ws": { -// const upgradeHeader = req.headers.get("Upgrade"); -// if (!upgradeHeader || upgradeHeader !== "websocket") { -// return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); -// } -// const { 0: fromClient, 1: toClient } = new WebSocketPair(); -// this.ctx.acceptWebSocket(toClient); -// // this.logger.Debug().Msg("fetch"); -// return new Response(null, { -// status: 101, -// webSocket: fromClient, -// }); -// } -// default: { -// const logger = ensureLogger(this.env); -// return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); -// } -// } -// } + async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { + this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); + // if (typeof msg !== "string") { + // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); + // return; + // } -// webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { -// try { -// ws.close(code, reason); -// // eslint-disable-next-line @typescript-eslint/no-unused-vars -// } catch (e) { -// // ignore -// } finally { -// this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); -// } -// } + // return CFMsgProcessor.dispatch( + // () => JSON.parse(msg.toString()), + // { env: this.env }, + // async (req: MsgBase, ictx: CFCtxBase) => { + // if (req.auth) { + // // do ucan magic + // } + // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; + // group = { + // ...group, + // qs: { + // ...group.qs, + // q: { + // ...group.qs.q, + // [req.type]: { + // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, + // }, + // }, + // }, + // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), + // lastUsed: new Date(), + // } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; + // return { req, ctx }; + // } + // ).then((qs) => { + // let group = { + // ...qs.ctx.group, + // qs: { + // ...qs.ctx.group.qs, + // s: { + // ...qs.ctx.group.qs.s, + // [qs.req.type]: { + // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, + // }, + // }, + // }, + // } satisfies FPMetaGroup; + // switch (true) { + // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): + // { + // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // // console.log("putMeta group", group); + // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( + // buildUpdateMetaEvent(qs, { + // connId: qs.res.connId, + // subscriberId: "later-overriden", + // }) + // ); + // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); + // } + // break; + // case MsgIsResSubscribeMeta(qs): + // { + // group = { ...group, group: qs.res } satisfies FPMetaGroup; + // // console.log("subscribeMeta group", group); + // ws.serializeAttachment(group); + // this.updateMeta({ + // connId: qs.res.connId, + // subscriberId: "later-overriden", + // tid: qs.res.tid, + // type: "updateMeta", + // key: qs.res.key, + // metaId: "later-overriden", + // metas: [], + // version: qs.res.version, + // }); + // } + // break; + // } + // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); + // ws.send(JSON.stringify(qs.res)); + // }); + } -// updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { -// const wsSocks = ctx.dobj.getWebSockets(); -// const groupWs = wsSocks.map((ws) => ({ -// ws, -// group: ws.deserializeAttachment() as FPMetaGroup, -// })); -// const joinedMeta = groupWs.reduce((acc, { group }) => { -// if (group && group.lastMeta) { -// acc.push(...group.lastMeta.metas); -// } -// return acc -// }, [] as CRDTEntry[]) -// const now = new Date() -// const joinedQS = { -// req: { ...qs.req, metas: joinedMeta }, -// res: qs.res, -// } -// return acc; -// }, [] as CRDTEntry[]); -// if (joinedMeta.length === 0) { -// return []; -// } -// const now = new Date(); -// const joinedUp = { -// ...up, -// metas: joinedMeta, -// }; -// groupWs.forEach(({ ws, group }) => { -// // console.log("group->", group); -// // group = { -// // ...group, -// // msgSeq: (group ? group.msgSeq : 0) + 1, -// // } -// group = { -// ...group, -// qs: { -// ...group.qs, -// s: { -// ...group.qs.s, -// [up.type]: { -// msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, -// }, -// }, -// }, -// lastUsed: now, -// } satisfies FPMetaGroup; -// ws.serializeAttachment(group); -// const toSend = { -// ...joinedUp, -// subscriberId: group.group.subscriberId, -// connId: group.group.connId, -// }; -// this.logger.Debug().Any("event", toSend).Msg("updateMeta"); -// ws.send( -// // this is not the best way to do this -// JSON.stringify(toSend) -// ); -// }); -// return joinedMeta; -// } -// } + async fetch(_req: Request): Promise { + const { 0: fromClient, 1: toClient } = new WebSocketPair(); + this.ctx.acceptWebSocket(toClient); + // this.logger.Debug().Msg("fetch"); + this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); + return new Response(null, { + status: 101, + webSocket: fromClient, + }); + + // const path = URI.from(req.url).pathname; + // switch (path) { + // case "/fp": { + // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); + // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); + // } + // case "/ws": { + // const upgradeHeader = req.headers.get("Upgrade"); + // if (!upgradeHeader || upgradeHeader !== "websocket") { + // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); + // } + // const { 0: fromClient, 1: toClient } = new WebSocketPair(); + // this.ctx.acceptWebSocket(toClient); + // // this.logger.Debug().Msg("fetch"); + // return new Response(null, { + // status: 101, + // webSocket: fromClient, + // }); + // } + // default: { + // const logger = ensureLogger(this.env); + // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); + // } + // } + // return new Response("Not implemented", { status: 501 }); + } + + webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { + try { + // if (typeof this.env.WS_EVENTS.onClose === "function") { + this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); + // } + ws.close(code, reason); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + // ignore + } finally { + this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); + } + } + + // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { + // const wsSocks = ctx.dobj.getWebSockets(); + // const groupWs = wsSocks.map((ws) => ({ + // ws, + // group: ws.deserializeAttachment() as FPMetaGroup, + // })); + // const joinedMeta = groupWs.reduce((acc, { group }) => { + // if (group && group.lastMeta) { + // acc.push(...group.lastMeta.metas); + // } + // return acc + // }, [] as CRDTEntry[]) + // const now = new Date() + // const joinedQS = { + // req: { ...qs.req, metas: joinedMeta }, + // res: qs.res, + // } + // return acc; + // }, [] as CRDTEntry[]); + // if (joinedMeta.length === 0) { + // return []; + // } + // const now = new Date(); + // const joinedUp = { + // ...up, + // metas: joinedMeta, + // }; + // groupWs.forEach(({ ws, group }) => { + // // console.log("group->", group); + // // group = { + // // ...group, + // // msgSeq: (group ? group.msgSeq : 0) + 1, + // // } + // group = { + // ...group, + // qs: { + // ...group.qs, + // s: { + // ...group.qs.s, + // [up.type]: { + // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, + // }, + // }, + // }, + // lastUsed: now, + // } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // const toSend = { + // ...joinedUp, + // subscriberId: group.group.subscriberId, + // connId: group.group.connId, + // }; + // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); + // ws.send( + // // this is not the best way to do this + // JSON.stringify(toSend) + // ); + // }); + // return joinedMeta; + // } +} // // const app = new Hono<{ Bindings: Env }>(); @@ -385,7 +409,9 @@ const once = new ResolveOnce(); export default { fetch: async (req, env, ctx): Promise => { await once.once(() => { - const sthis = ensureSuperThis(); + const sthis = ensureSuperThis({ + logger: ensureLogger(env, "CF-Fireproof"), + }); const msgP = defaultMsgParams(sthis, { hasPersistent: true, protocol: env.FP_PROTOCOL === "ws" ? "ws" : "http", @@ -393,7 +419,7 @@ export default { const gs = defaultGestalt(msgP, { id: env.FP_PROTOCOL ? (env.FP_PROTOCOL === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - const honoServer = new HonoServer(sthis, msgP, gs, new CFHonoServer()); + const honoServer = new HonoServer(sthis, msgP, gs, new CFHonoServer(sthis, msgP.ende, env)); return honoServer.start(app); }); return app.fetch(req, env, ctx); diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 45a9bfb7..dfd0dfc9 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -24,23 +24,24 @@ STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" FP_DEBUG = "FPMetaGroups" +#FP_FORMAT = "yaml" +# TEST_DATE = "20241121T225359Z" FP_PROTOCOL = "http" +[env.test-reqRes.durable_objects] +bindings = [ + { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, +] + [env.test-stream.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" SECRET_ACCESS_KEY = "minioadmin" FP_DEBUG = "FPMetaGroups" -FP_PROTOCOL = "ws" - #FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" - -[env.test-reqRes.durable_objects] -bindings = [ - { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, -] +FP_PROTOCOL = "ws" [env.test-stream.durable_objects] bindings = [ diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index b8130808..6032e8b4 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -6,12 +6,28 @@ import { MsgIsError, MsgIsResGestalt, MsgIsResOpen, - Connection, defaultGestalt, MsgerParams, Gestalt, ReqOpen, + ReqSignedUrlParam, } from "./msg-types.js"; +import { + MsgIsResGetData, + MsgIsResPutData, + MsgIsResDelData, + buildReqPutData, + buildReqDelData, + buildReqGetData, +} from "./msg-types-data.js"; +import { + buildReqGetWAL, + buildReqPutWAL, + buildReqDelWAL, + MsgIsResGetWAL, + MsgIsResPutWAL, + MsgIsResDelWAL, +} from "./msg-types-wal.js"; import { applyStart, defaultMsgParams, MsgConnection, Msger } from "./msger.js"; import { HttpConnection } from "./http-connection.js"; import { WSConnection } from "./ws-connection.js"; @@ -19,6 +35,10 @@ import { HonoServer } from "./hono-server.js"; import { Hono } from "hono"; import { NodeHonoServer } from "./node-hono-server.js"; import { $ } from "zx"; +import * as fs from "fs/promises"; +import * as toml from "smol-toml"; +import { Env } from "./backend/env.js"; +import { calculatePreSignedUrl, PreSignedMsg } from "./pre-signed-url.js"; function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "http" }), { @@ -136,18 +156,50 @@ function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOp }; } +async function resolveToml() { + const tomlFile = "src/cloud/backend/wrangler.toml"; + const tomeStr = await fs.readFile(tomlFile, "utf-8"); + const wranglerFile = toml.parse(tomeStr) as unknown as { + env: { "test-reqRes": { vars: Env } }; + }; + return { + tomlFile, + env: wranglerFile.env["test-reqRes"].vars, + }; +} + +async function refURL(sp: PreSignedMsg) { + const { env } = await resolveToml(); + return ( + await calculatePreSignedUrl(sp, { + storageUrl: URI.from(env.STORAGE_URL), + aws: { + accessKeyId: env.ACCESS_KEY_ID, + secretAccessKey: env.SECRET_ACCESS_KEY, + region: env.REGION, + }, + test: { + // amzDate?: string; + }, + }) + ) + .Ok() + .asObj(); +} + const sthis = ensureSuperThis(); const msgP = defaultMsgParams(sthis, { hasPersistent: true }); for (const honoServer of [ { name: "NodeHonoServer", - factory: async (remoteGestalt: Gestalt, _port: number) => - new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer()), + factory: async (remoteGestalt: Gestalt, _port: number) => { + return new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer((await resolveToml()).env)); + }, }, { name: "CFHonoServer", factory: async (remoteGestalt: Gestalt, port: number) => { - const tomlFile = "src/cloud/backend/wrangler.toml"; + const { tomlFile } = await resolveToml(); $.verbose = !!process.env.FP_DEBUG; const runningWrangler = $` wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]} --no-show-interactive-dev-session & @@ -187,8 +239,8 @@ for (const honoServer of [ const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { key: { - ledgerName: "test", - tenantId: "test", + ledger: "test", + tenant: "test", }, reqId: "req-open-test", }); @@ -222,17 +274,12 @@ for (const honoServer of [ expect(rC.isOk()).toBeTruthy(); c = rC.Ok(); expect(c.conn).toEqual({ - conn: { - key: { - ledgerName: "test", - tenantId: "test", - }, - reqId: "req-open-test", - resId: c.conn?.conn.resId, + key: { + ledger: "test", + tenant: "test", }, - tid: qOpen.tid, - type: "resOpen", - version: "FP-MSG-1.0", + reqId: "req-open-test", + resId: c.conn.resId, }); }); afterEach(async () => { @@ -270,15 +317,13 @@ for (const honoServer of [ }); it("openConnection", async () => { - const req = buildReqOpen(sthis, { - ...(c.conn?.conn as Connection), - }); + const req = buildReqOpen(sthis, { ...c.conn }); const r = await c.request(req, { waitFor: MsgIsResOpen }); if (!MsgIsResOpen(r)) { assert.fail(JSON.stringify(r)); } expect(r).toEqual({ - conn: c.conn?.conn, + conn: c.conn, tid: req.tid, type: "resOpen", version: "FP-MSG-1.0", @@ -287,28 +332,16 @@ for (const honoServer of [ }); it("open", async () => { - const qOpen = buildReqOpen(sthis, { - key: { - ledgerName: "test", - tenantId: "test", - }, - reqId: "req-open-test", - }); const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); expect(rC.isOk()).toBeTruthy(); const c = rC.Ok(); expect(c.conn).toEqual({ - conn: { - key: { - ledgerName: "test", - tenantId: "test", - }, - reqId: "req-open-test", - resId: c.conn?.conn.resId, + key: { + ledger: "test", + tenant: "test", }, - tid: c.conn?.tid, - type: "resOpen", - version: "FP-MSG-1.0", + reqId: "req-open-test", + resId: c.conn.resId, }); expect(c).toBeInstanceOf(style.cInstance); expect(c.exchangedGestalt).toEqual({ @@ -317,6 +350,97 @@ for (const honoServer of [ }); await c.close(); }); + describe(`${honoServer.name} - Msgs`, () => { + let conn: MsgConnection; + beforeAll(async () => { + const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); + expect(rC.isOk()).toBeTruthy(); + conn = rC.Ok(); + }); + afterAll(async () => { + await conn.close(); + }); + it("Open", async () => { + const res = await conn.request(qOpen, { waitFor: MsgIsResOpen }); + expect(MsgIsResOpen(res)).toBeTruthy(); + expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn?.resId }); + }); + + function sup() { + return { + path: "test/me", + key: "key-test", + } satisfies ReqSignedUrlParam; + } + describe("Data", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetData(sthis, sp, conn.conn), { waitFor: MsgIsResGetData }); + if (MsgIsResGetData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetData", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutData(sthis, sp, conn.conn), { waitFor: MsgIsResPutData }); + if (MsgIsResPutData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutData", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelData(sthis, sp, conn.conn), { waitFor: MsgIsResDelData }); + if (MsgIsResDelData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelData", JSON.stringify(res)); + } + }); + }); + // describe("Meta", async () => { + // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); + // // expect(MsgIsError(res)).toBeTruthy(); + // }); + describe("WAL", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetWAL(sthis, sp, conn.conn), { waitFor: MsgIsResGetWAL }); + if (MsgIsResGetWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetWAL", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutWAL(sthis, sp, conn.conn), { waitFor: MsgIsResPutWAL }); + if (MsgIsResPutWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutWAL", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelWAL(sthis, sp, conn.conn), { waitFor: MsgIsResDelWAL }); + if (MsgIsResDelWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); + }); + }); }); } }); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index e989535f..38ae24eb 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -1,16 +1,20 @@ -import { exception2Result, HttpHeader, runtimeFn, URI } from "@adviser/cement"; +import { exception2Result, HttpHeader, Result, URI } from "@adviser/cement"; import { ensureLogger, Logger, SuperThis } from "@fireproof/core"; -import { Hono } from "hono"; +import { Context, Hono, Next } from "hono"; import { top_uint8 } from "../coerce-binary.js"; -import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg } from "./msg-types.js"; +import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg, Connection, MsgBase, buildResOpen } from "./msg-types.js"; import { MsgDispatcher } from "./msg-dispatch.js"; -import { UpgradeWebSocket } from "hono/ws"; +import { WSEvents } from "hono/ws"; +import { PreSignedConnMsg } from "./pre-signed-url.js"; +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type +export type ConnMiddleware = (conn: Connection, c: Context, next: Next) => Promise; export interface HonoServerImpl { start(app: Hono): Promise; serve(app: Hono, port?: number): Promise; close(): Promise; - upgradeWebSocket: UpgradeWebSocket; + calculatePreSignedUrl(p: PreSignedConnMsg): Promise>; + upgradeWebSocket: (createEvents: (c: Context) => WSEvents | Promise) => ConnMiddleware; readonly headers: HttpHeader; } @@ -41,18 +45,16 @@ export class HonoServer { // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); app.put("/fp", async (c) => { - const rMsg = await exception2Result(() => c.req.json()); + this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); + const rMsg = await exception2Result(() => c.req.json() as Promise); if (rMsg.isErr()) { c.status(500); return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rMsg.Err())); } - this.impl.headers.Items().forEach((i) => { - c.res.headers.append(i[0], i[1][0]); - }); - return dispatcher.dispatch(rMsg.Ok(), (msg) => c.json(msg)); + return dispatcher.dispatch(this.impl, rMsg.Ok(), (msg) => c.json(msg)); }); app.get("/ws", async (c, next) => { - this.impl.headers.AsHeaders().forEach((v, k) => c.res.headers.set(k, v)); + this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); if (rReqOpen.isErr()) { c.status(500); @@ -60,31 +62,45 @@ export class HonoServer { } const reqOpen = rReqOpen.Ok(); if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { - c.status(401); + c.status(400); return c.json( buildErrorMsg(this.sthis, this.sthis.logger, reqOpen, this.logger.Error().Msg("expected reqOpen").AsError()) ); } - const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); - dispatcher.addConn(reqOpen.conn); - return this.impl.upgradeWebSocket((_c) => ({ - onOpen: () => { - // console.log('Connection opened', c.req.url) - }, - onError: (error) => { - this.logger.Error().Err(error).Msg("WebSocket error"); - }, - onMessage: async (event, ws) => { - // console.log('onMsg event', event, event.data); - dispatcher.dispatch(this.msgP.ende.decode(await top_uint8(event.data)), (msg) => { - const str = this.msgP.ende.encode(msg); - ws.send(str); - }); - }, - onClose: () => { - // console.log('Connection closed') - }, - }))(c, next); + return this.impl.upgradeWebSocket((_c) => { + let dp: MsgDispatcher; + return { + onOpen: (_e, ws) => { + dp = new MsgDispatcher(this.sthis, this.gestalt); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const rConn = dp.addConn(reqOpen.conn!); + if (rConn.isErr()) { + ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rConn.Err()))); + } else { + ws.send(this.msgP.ende.encode(buildResOpen(this.sthis, reqOpen, rConn.Ok().resId))); + } + }, + onError: (error) => { + this.logger.Error().Err(error).Msg("WebSocket error"); + }, + onMessage: async (event, ws) => { + const rMsg = await exception2Result( + async () => this.msgP.ende.decode(await top_uint8(event.data)) as MsgBase + ); + if (rMsg.isErr()) { + ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rMsg.Err()))); + } else { + dp.dispatch(this.impl, rMsg.Ok(), (msg) => { + const str = this.msgP.ende.encode(msg); + ws.send(str); + }); + } + }, + onClose: () => { + // console.log('Connection closed') + }, + }; + })(reqOpen.conn, c, next); }); await this.impl.serve(app, port); return this; @@ -94,11 +110,11 @@ export class HonoServer { } } -export async function honoServer(_sthis: SuperThis, _msgP: MsgerParams, _gestalt: Gestalt) { - const rt = runtimeFn(); - if (rt.isNodeIsh) { - // const { NodeHonoServer } = await import("./node-hono-server.js"); - // return new HonoServer(sthis, msgP, gestalt, new NodeHonoServer()); - } - throw new Error("Not implemented"); -} +// export async function honoServer(_sthis: SuperThis, _msgP: MsgerParams, _gestalt: Gestalt) { +// const rt = runtimeFn(); +// if (rt.isNodeIsh) { +// // const { NodeHonoServer } = await import("./node-hono-server.js"); +// // return new HonoServer(sthis, msgP, gestalt, new NodeHonoServer()); +// } +// throw new Error("Not implemented"); +// } diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index f3d05f7c..dbbd2adc 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -1,7 +1,17 @@ -import { Logger, Result, URI, exception2Result } from "@adviser/cement"; +import { HttpHeader, Logger, Result, URI, exception2Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; -import { MsgBase, MsgIsResOpen, ReqOpen, ResOpen, buildErrorMsg, MsgerParams } from "./msg-types.js"; +import { + MsgBase, + MsgIsResOpen, + ReqOpen, + ResOpen, + buildErrorMsg, + MsgerParams, + Connection, + UpdateReqRes, + WithErrorMsg, + RequestOpts, +} from "./msg-types.js"; import { ExchangedGestalt, MsgConnection, OnMsgFn, selectRandom, timeout, UnReg } from "./msger.js"; export class HttpConnection implements MsgConnection { @@ -12,13 +22,11 @@ export class HttpConnection implements MsgConnection { readonly baseURIs: URI[]; - readonly qsOpen: { - readonly req?: ReqOpen; - res?: ResOpen; - }; + readonly _qsOpen: Partial>; - get conn(): ResOpen | undefined { - return this.qsOpen.res; + get conn(): Connection { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this._qsOpen.res!.conn; } readonly #onMsg = new Map(); @@ -34,17 +42,17 @@ export class HttpConnection implements MsgConnection { this.logger = ensureLogger(sthis, "HttpConnection"); this.msgParam = msgP; this.baseURIs = uris; - this.qsOpen = { req: reqOpen }; + this._qsOpen = { req: reqOpen }; this.exchangedGestalt = exGestalt; } async start(): Promise> { - if (this.qsOpen.req) { - const sOpen = await this.request(this.qsOpen.req, { waitFor: MsgIsResOpen }); + if (this._qsOpen.req) { + const sOpen = await this.request(this._qsOpen.req, { waitFor: MsgIsResOpen }); if (!MsgIsResOpen(sOpen)) { return Result.Err(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); } - this.qsOpen.res = sOpen; + this._qsOpen.res = sOpen; } return Result.Ok(undefined); } @@ -66,9 +74,9 @@ export class HttpConnection implements MsgConnection { } async request(req: Q, _opts: RequestOpts): Promise> { - const headers = new Headers(); - headers.append("Content-Type", this.msgParam.mime); - headers.append("Accept", this.msgParam.mime); + const headers = HttpHeader.from(); + headers.Set("Content-Type", this.msgParam.mime); + headers.Set("Accept", this.msgParam.mime); const rReqBody = exception2Result(() => this.msgParam.ende.encode(req)); if (rReqBody.isErr()) { return this.toMsg( @@ -80,7 +88,7 @@ export class HttpConnection implements MsgConnection { ) ); } - headers.append("Content-Length", rReqBody.Ok().byteLength.toString()); + headers.Set("Content-Length", rReqBody.Ok().byteLength.toString()); const url = selectRandom(this.baseURIs); this.logger.Debug().Url(url).Any("body", req).Msg("request"); const rRes = await exception2Result(() => @@ -88,7 +96,7 @@ export class HttpConnection implements MsgConnection { this.msgParam.timeout, fetch(url.toString(), { method: "PUT", - headers, + headers: headers.AsHeaderInit(), body: rReqBody.Ok(), }) ) diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts index 77df873b..efe41ca4 100644 --- a/src/cloud/msg-dispatch.ts +++ b/src/cloud/msg-dispatch.ts @@ -1,4 +1,4 @@ -import { HttpHeader, Logger, Result } from "@adviser/cement"; +import { Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { Gestalt, @@ -10,36 +10,55 @@ import { buildResOpen, Connection, } from "./msg-types.js"; +import { + MsgIsReqGetData, + buildResGetData, + MsgIsReqPutData, + MsgIsReqDelData, + buildResDelData, + buildResPutData, +} from "./msg-types-data.js"; +import { + MsgIsReqDelWAL, + MsgIsReqGetWAL, + MsgIsReqPutWAL, + buildResDelWAL, + buildResGetWAL, + buildResPutWAL, +} from "./msg-types-wal.js"; +import { PreSignedMsg } from "./pre-signed-url.js"; +import { HonoServerImpl } from "./hono-server.js"; + +export interface MsgContext { + calculatePreSignedUrl(p: PreSignedMsg): Promise; +} export class MsgDispatcher { readonly sthis: SuperThis; readonly logger: Logger; - readonly conns = new Map(); + conn?: Connection; readonly gestalt: Gestalt; + readonly id: string; constructor(sthis: SuperThis, gestalt: Gestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "Dispatcher"); this.gestalt = gestalt; + this.id = sthis.nextId().str; } addConn(aConn: Connection): Result { - const key = [aConn.key.ledgerName, aConn.key.tenantId].join(":"); - let conn = this.conns.get(key); - if (!conn) { - if (this.conns.size > 0) { - return Result.Err("connection"); - } - conn = { ...aConn, resId: this.sthis.nextId().str }; - this.conns.set(key, conn); + if (!this.conn) { + this.conn = { ...aConn, resId: this.sthis.nextId().str }; + return Result.Ok(this.conn); } - if (conn.reqId !== aConn.reqId) { - return Result.Err("unexpected reqId"); + if (aConn.reqId === this.conn.reqId) { + return Result.Ok(this.conn); } - return Result.Ok(conn); + return this.logger.Error().Msg(`unexpected reqId: ${aConn.reqId}!==${this.conn.reqId}`).ResultError(); } - dispatch(msg: MsgBase, send: (msg: MsgBase) => void) { + async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => void) { switch (true) { case MsgIsReqGestalt(msg): return send(buildResGestalt(msg, this.gestalt)); @@ -54,6 +73,27 @@ export class MsgDispatcher { } return send(buildResOpen(this.sthis, msg, rConn.Ok().resId)); } + + case MsgIsReqGetData(msg): { + return send(await buildResGetData(this.sthis, this.logger, msg, ctx)); + } + case MsgIsReqPutData(msg): { + return send(await buildResPutData(this.sthis, this.logger, msg, ctx)); + } + case MsgIsReqDelData(msg): { + return send(await buildResDelData(this.sthis, this.logger, msg, ctx)); + } + + case MsgIsReqGetWAL(msg): { + return send(await buildResGetWAL(this.sthis, this.logger, msg, ctx)); + } + case MsgIsReqPutWAL(msg): { + return send(await buildResPutWAL(this.sthis, this.logger, msg, ctx)); + } + case MsgIsReqDelWAL(msg): { + return send(await buildResDelWAL(this.sthis, this.logger, msg, ctx)); + } + default: return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); } diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts-off similarity index 98% rename from src/cloud/msg-processor.ts rename to src/cloud/msg-processor.ts-off index 31ef9814..788e3884 100644 --- a/src/cloud/msg-processor.ts +++ b/src/cloud/msg-processor.ts-off @@ -1,11 +1,10 @@ -import { exception2Result, Logger, Result } from "@adviser/cement"; +import { exception2Result, Logger, } from "@adviser/cement"; import { buildErrorMsg, buildResDelMeta, buildResGestalt, buildResGetMeta, buildResPutMeta, - ConnectionKey, defaultGestalt, ErrorMsg, getStoreFromType, diff --git a/src/cloud/msg-type-meta.ts b/src/cloud/msg-type-meta.ts new file mode 100644 index 00000000..682a8abd --- /dev/null +++ b/src/cloud/msg-type-meta.ts @@ -0,0 +1,262 @@ +import { VERSION } from "@adviser/cement"; +import { CRDTEntry } from "@fireproof/core"; +import { MsgBase, Connection, NextId, ReqRes, ReqSignedUrlParam, SignedUrlParam } from "./msg-types.js"; + +/* Subscribe Meta */ + +export interface ReqSubscribeMeta extends MsgBase { + readonly type: "reqSubscribeMeta"; + readonly subscriberId: string; + readonly conn: Connection; +} + +// export type ReqSubscribeMetaWithConnId = AddConnId; + +// export function MsgIsReqSubscribeMetaWithConnId(req: MsgBase): req is ReqSubscribeMetaWithConnId { +// return req.type === "reqSubscribeMetaWithConnId"; +// } + +export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { + return req.type === "reqSubscribeMeta"; +} + +export function buildReqSubscriptMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { + return { + tid: sthis.nextId().str, + subscriberId, + type: "reqSubscribeMeta", + version: VERSION, + conn: ck, + }; +} + +export interface ResSubscribeMeta extends MsgBase { + readonly type: "resSubscribeMeta"; + readonly subscriberId: string; + readonly conn: Connection; +} + +export function buildResSubscriptMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { + return { + tid: req.tid, + type: "resSubscribeMeta", + subscriberId: req.subscriberId, + conn: req.conn, + version: VERSION, + }; +} + +export function MsgIsResSubscribeMeta>( + qs: T +): qs is T & ReqRes { + return qs.res.type === "resSubscribeMeta"; +} + +/* Put Meta */ +export interface ReqPutMeta extends MsgBase { + readonly type: "reqPutMeta"; + readonly params: ReqSignedUrlParam; + readonly metas: CRDTEntry[]; + readonly conn: Connection; +} + +// export type ReqPutMetaWithConnId = AddConnId; + +// export function MsgIsReqPutMetaWithConnId(msg: MsgBase): msg is ReqPutMetaWithConnId { +// return msg.type === "reqPutMetaWithConnId"; +// } + +export interface PutMetaParam { + readonly metaId: string; + readonly metas: CRDTEntry[]; + readonly signedPutUrl: string; +} + +export interface ResPutMeta extends MsgBase, PutMetaParam { + readonly type: "resPutMeta"; + readonly metas: CRDTEntry[]; + readonly conn: Connection; +} + +export function buildReqPutMeta( + sthis: NextId, + conn: Connection, + signedUrlParams: ReqSignedUrlParam, + metas: CRDTEntry[] +): ReqPutMeta { + return { + tid: sthis.nextId().str, + type: "reqPutMeta", + conn, + version: VERSION, + params: signedUrlParams, + metas, + }; +} + +export function MsgIsReqPutMeta(msg: MsgBase): msg is ReqPutMeta { + return msg.type === "reqPutMeta"; +} + +export function buildResPutMeta(req: ReqPutMeta, metaParam: PutMetaParam): ResPutMeta { + return { + ...metaParam, + tid: req.tid, + type: "resPutMeta", + conn: req.conn, + version: VERSION, + }; +} + +export function MsgIsResPutMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resPutMeta" && qs.req.type === "reqPutMeta"; +} + +export interface ConnSubId { + readonly connId: string; + readonly subscriberId: string; +} + +/** + * This is used for non WebSocket server implementations + * to retrieve the meta data. It should be done by polling + * and might implement long polling. + * It will answer with a UpdateMetaEvent. + */ +export interface ReqUpdateMeta extends MsgBase, ConnSubId { + readonly type: "reqUpdateMeta"; + readonly conn: Connection; +} + +export interface UpdateMetaEvent extends MsgBase, ConnSubId { + readonly type: "updateMeta"; + readonly conn: Connection; + readonly metaId: string; + readonly metas: CRDTEntry[]; +} + +export function buildUpdateMetaEvent(rq: ReqRes, consub: ConnSubId): UpdateMetaEvent { + return { + ...consub, + tid: rq.res.tid, + type: "updateMeta", + conn: rq.res.conn, + metaId: rq.res.metaId, + metas: rq.req.metas, + version: rq.res.version, + }; +} + +export function MsgIsUpdateMetaEvent(msg: MsgBase): msg is UpdateMetaEvent { + return msg.type === "updateMeta"; +} + +/* Get Meta */ +export interface ReqGetMeta extends MsgBase { + readonly type: "reqGetMeta"; + readonly params: ReqSignedUrlParam; + readonly conn: Connection; +} + +// export type ReqGetMetaWithConnId = AddConnId; + +export function MsgIsReqGetMeta(msg: MsgBase): msg is ReqGetMeta { + return msg.type === "reqGetMeta"; +} + +// export function MsgIsReqGetMetaWithConnId(msg: MsgBase): msg is ReqGetMetaWithConnId { +// return msg.type === "reqGetMetaWithConnId"; +// } + +export interface GetMetaParam { + // readonly params: SignedUrlParam; + // readonly key: ConnectionKey; + readonly status: "found" | "not-found" | "redirect"; + readonly metas: CRDTEntry[]; + readonly connId: string; + // if set client should query this url to retrieve the meta + readonly signedGetUrl?: string; +} + +export interface ResGetMeta extends MsgBase, GetMetaParam { + readonly type: "resGetMeta"; + readonly params: SignedUrlParam; +} + +export function buildReqGetMeta(sthis: NextId, conn: Connection, signedUrlParams: ReqSignedUrlParam): ReqGetMeta { + return { + tid: sthis.nextId().str, + conn, + type: "reqGetMeta", + version: VERSION, + params: signedUrlParams, + }; +} + +export function buildResGetMeta(req: ReqGetMeta, metaParam: GetMetaParam): ResGetMeta { + return { + ...metaParam, + tid: req.tid, + type: "resGetMeta", + params: { ...req.params, method: "GET", store: "meta" }, + version: VERSION, + }; +} + +export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resGetMeta" && qs.req.type === "reqGetMeta"; +} + +/* Del Meta */ +export interface ReqDelMeta extends MsgBase { + readonly type: "reqDelMeta"; + readonly params: ReqSignedUrlParam; + readonly conn: Connection; +} + +// export type ReqDelMetaWithConnId = AddConnId; + +// export function MsgIsReqDelMetaWithConnId(msg: MsgBase): msg is ReqDelMetaWithConnId { +// return msg.type === "reqDelMetaWithConnId"; +// } + +export interface DelMetaParam { + readonly params: SignedUrlParam; + // readonly key: ConnectionKey; + readonly status: "found" | "not-found" | "redirect" | "unsupported"; + // readonly connId: string; + // if set client should query this url to retrieve the meta + readonly signedDelUrl?: string; +} + +export interface ResDelMeta extends MsgBase, DelMetaParam { + readonly type: "resDelMeta"; +} + +export function buildReqDelMeta(sthis: NextId, conn: Connection, signedUrlParams: SignedUrlParam): ReqDelMeta { + return { + tid: sthis.nextId().str, + conn, + type: "reqDelMeta", + version: VERSION, + params: signedUrlParams, + }; +} + +export function MsgIsReqDelMeta(msg: MsgBase): msg is ReqDelMeta { + return msg.type === "reqDelMeta"; +} + +export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDelMeta { + return { + ...metaParam, + tid: req.tid, + type: "resDelMeta", + // key: req.key, + version: VERSION, + }; +} + +export function MsgIsResDelMeta(qs: ReqRes): qs is ReqRes { + return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; +} diff --git a/src/cloud/msg-types-data.ts b/src/cloud/msg-types-data.ts new file mode 100644 index 00000000..25e083c7 --- /dev/null +++ b/src/cloud/msg-types-data.ts @@ -0,0 +1,127 @@ +import { VERSION, Logger, Result, URI } from "@adviser/cement"; +import { SuperThis } from "@fireproof/core"; +import { + ReqSignedUrl, + NextId, + Connection, + MsgBase, + ResSignedUrl, + WithErrorMsg, + buildRes, + ReqSignedUrlParam, +} from "./msg-types.js"; +import { PreSignedMsg } from "./pre-signed-url.js"; + +export interface ReqGetData extends ReqSignedUrl { + readonly type: "reqGetData"; +} + +export function buildReqGetData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetData { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqGetData", + // key: req.key, + version: VERSION, + }; +} + +export function MsgIsReqGetData(msg: MsgBase): msg is ReqGetData { + return msg.type === "reqGetData"; +} + +export interface ResGetData extends ResSignedUrl { + readonly type: "resGetData"; + // readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsResGetData(msg: MsgBase): msg is ResGetData { + return msg.type === "resGetData"; +} + +export interface CalculatePreSignedUrl { + calculatePreSignedUrl(p: PreSignedMsg): Promise>; +} + +export function buildResGetData( + sthis: SuperThis, + logger: Logger, + req: ReqGetData, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("GET", "data", "resGetData", sthis, logger, req, ctx); +} + +export interface ReqPutData extends ReqSignedUrl { + readonly type: "reqPutData"; + // readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsReqPutData(msg: MsgBase): msg is ReqPutData { + return msg.type === "reqPutData"; +} + +export function buildReqPutData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutData { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqPutData", + // key: req.key, + version: VERSION, + }; +} + +export interface ResPutData extends ResSignedUrl { + readonly type: "resPutData"; +} + +export function MsgIsResPutData(msg: MsgBase): msg is ResPutData { + return msg.type === "resPutData"; +} + +export function buildResPutData( + sthis: SuperThis, + logger: Logger, + req: ReqPutData, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("PUT", "data", "resPutData", sthis, logger, req, ctx); +} + +export interface ReqDelData extends ReqSignedUrl { + readonly type: "reqDelData"; +} + +export function MsgIsReqDelData(msg: MsgBase): msg is ReqDelData { + return msg.type === "reqDelData"; +} + +export function buildReqDelData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelData { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqDelData", + // key: req.key, + version: VERSION, + }; +} + +export interface ResDelData extends ResSignedUrl { + readonly type: "resDelData"; +} + +export function MsgIsResDelData(msg: MsgBase): msg is ResDelData { + return msg.type === "resDelData"; +} + +export function buildResDelData( + sthis: SuperThis, + logger: Logger, + req: ReqDelData, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("DELETE", "data", "resDelData", sthis, logger, req, ctx); +} diff --git a/src/cloud/msg-types-wal.ts b/src/cloud/msg-types-wal.ts new file mode 100644 index 00000000..da21b6a3 --- /dev/null +++ b/src/cloud/msg-types-wal.ts @@ -0,0 +1,123 @@ +import { VERSION, Logger } from "@adviser/cement"; +import { SuperThis } from "@fireproof/core"; +import { + MsgBase, + Connection, + WithErrorMsg, + buildRes, + NextId, + ReqSignedUrl, + ResSignedUrl, + ReqSignedUrlParam, +} from "./msg-types.js"; +import { CalculatePreSignedUrl } from "./msg-types-data.js"; + +export interface ReqGetWAL extends ReqSignedUrl { + readonly type: "reqGetWAL"; +} + +export function MsgIsReqGetWAL(msg: MsgBase): msg is ReqGetWAL { + return msg.type === "reqGetWAL"; +} + +export function buildReqGetWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetWAL { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqGetWAL", + // key: req.key, + version: VERSION, + }; +} + +export interface ResGetWAL extends ResSignedUrl { + readonly type: "resGetWAL"; + // readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsResGetWAL(msg: MsgBase): msg is ResGetWAL { + return msg.type === "resGetWAL"; +} + +export function buildResGetWAL( + sthis: SuperThis, + logger: Logger, + req: ReqGetWAL, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("GET", "wal", "resGetWAL", sthis, logger, req, ctx); +} + +export interface ReqPutWAL extends Omit { + readonly type: "reqPutWAL"; + // readonly payload: Uint8Array; // transfered via JSON base64 +} + +export function MsgIsReqPutWAL(msg: MsgBase): msg is ReqPutWAL { + return msg.type === "reqPutWAL"; +} + +export function buildReqPutWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutWAL { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqPutWAL", + // key: req.key, + version: VERSION, + }; +} + +export interface ResPutWAL extends Omit { + readonly type: "resPutWAL"; +} + +export function MsgIsResPutWAL(msg: MsgBase): msg is ResPutWAL { + return msg.type === "resPutWAL"; +} + +export function buildResPutWAL( + sthis: SuperThis, + logger: Logger, + req: ReqPutWAL, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("PUT", "wal", "resPutWAL", sthis, logger, req, ctx); +} + +export interface ReqDelWAL extends Omit { + readonly type: "reqDelWAL"; +} + +export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { + return msg.type === "reqDelWAL"; +} + +export function buildReqDelWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelWAL { + return { + params: sup, + conn, + tid: sthis.nextId().str, + type: "reqDelWAL", + // key: req.key, + version: VERSION, + }; +} + +export interface ResDelWAL extends Omit { + readonly type: "resDelWAL"; +} + +export function MsgIsResDelWAL(msg: MsgBase): msg is ResDelWAL { + return msg.type === "resDelWAL"; +} + +export function buildResDelWAL( + sthis: SuperThis, + logger: Logger, + req: ReqDelWAL, + ctx: CalculatePreSignedUrl +): Promise> { + return buildRes("DELETE", "wal", "resDelWAL", sthis, logger, req, ctx); +} diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 84ed96ac..34d00422 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,8 +1,17 @@ -import { Future } from "@adviser/cement"; -import { CRDTEntry, Logger, SuperThis } from "@fireproof/core"; +import { exception2Result, Future } from "@adviser/cement"; +import { Logger, SuperThis } from "@fireproof/core"; +import { CalculatePreSignedUrl } from "./msg-types-data.js"; +import { PreSignedMsg } from "./pre-signed-url.js"; export const VERSION = "FP-MSG-1.0"; +export type WithErrorMsg = T | ErrorMsg; + +export interface RequestOpts { + readonly waitFor: (msg: MsgBase) => boolean; + readonly timeout?: number; // ms +} + export interface EnDeCoder { encode(node: T): Uint8Array; decode(data: Uint8Array): T; @@ -11,6 +20,7 @@ export interface EnDeCoder { export interface WaitForTid { readonly tid: string; readonly future: Future; + readonly timeout?: number; // undefined match all readonly waitFor: (msg: MsgBase) => boolean; } @@ -19,7 +29,7 @@ export interface WaitForTid { // readonly connId: string; // } // type AddConnId = Omit & ConnId & { readonly type: N }; -interface NextId { +export interface NextId { readonly nextId: SuperThis["nextId"]; } @@ -34,13 +44,13 @@ export interface UCanAuth { }; } -export interface ConnectionKey { - readonly tenantId: string; - readonly ledgerName: string; +export interface TenantLedger { + readonly tenant: string; + readonly ledger: string; } export interface Connection { - readonly key: ConnectionKey; + readonly key: TenantLedger; readonly reqId: string; readonly resId: string; } @@ -272,10 +282,7 @@ export function MsgIsResGestalt(msg: MsgBase): msg is ResGestalt { return msg.type === "resGestalt"; } -export interface ReqOpenConnection { - readonly key: ConnectionKey; - readonly reqId?: string; -} +export type ReqOpenConnection = Omit & { readonly reqId?: string }; export interface ReqOpen extends MsgBase { readonly type: "reqOpen"; @@ -320,54 +327,57 @@ export function MsgIsResOpen(msg: MsgBase): msg is ResOpen { return msg.type === "resOpen"; } -export interface SignedUrlParam extends ConnectionKey { - readonly path?: string; +export interface ReqClose extends Omit { + readonly type: "reqClose"; +} + +export function MsgIsReqClose(msg: MsgBase): msg is ReqClose { + return msg.type === "reqClose"; +} + +export interface ResClose extends Omit { + readonly type: "resClose"; +} + +export function MsgIsResClose(msg: MsgBase): msg is ResClose { + return msg.type === "resClose"; +} + +export interface SignedUrlParam { readonly method: HttpMethods; readonly store: FPStoreTypes; + // base path + readonly path?: string; + // name of the file readonly key: string; readonly expires?: number; // seconds readonly index?: string; } -export interface ReqRes { - readonly req: Q; - readonly res: S; +export type ReqSignedUrlParam = Omit; + +export interface UpdateReqRes { + req: Q; + res: S; } +export type ReqRes = Readonly>; + export interface ReqOptRes { readonly req: Q; readonly res?: S; } -export interface ReqSignedUrlParam { - readonly tid?: string; - readonly version?: string; - readonly auth?: AuthType; - readonly params: { - // readonly protocol?: "ws" | "wss"; // ws or wss - // readonly tenantId: string; - // readonly name: string; - readonly connectionKey: ConnectionKey; - readonly path?: string; - readonly method: HttpMethods; - readonly store: FPStoreTypes; - readonly key: string; - readonly expires?: number; // seconds - readonly index?: string; - }; -} - -/* Signed URL */ - -export function buildReqSignedUrl(req: ReqSignedUrlParam): ReqSignedUrlParam { - return { - tid: req.tid, - params: { - // protocol: "wss", - ...req.params, - }, - }; -} +// /* Signed URL */ +// export function buildReqSignedUrl(req: ReqSignedUrlParam): ReqSignedUrlParam { +// return { +// tid: req.tid, +// params: { +// // protocol: "wss", +// ...req.params, +// }, +// }; +// } // export function MsgIsReqSignedUrl(msg: MsgBase): msg is ReqSignedUrl { // return msg.type === "reqSignedUrl"; @@ -395,15 +405,15 @@ export function getStoreFromType(req: MsgBase): StoreAndType { ); } -export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { - return { - tid: req.tid, - type: getStoreFromType(req).resType, - version: VERSION, - params: req.params, - signedUrl, - }; -} +// export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { +// return { +// tid: req.tid, +// type: getStoreFromType(req).resType, +// version: VERSION, +// params: req.params, +// signedUrl, +// }; +// } export function buildErrorMsg( sthis: SuperThis, @@ -424,356 +434,49 @@ export function buildErrorMsg( body, stack, } satisfies ErrorMsg; - logger.Error().Any("msg", msg).Msg("error"); + logger.Error().Any("ErrorMsg", msg).Msg("error"); return msg; } export interface ReqSignedUrl extends MsgBase { // readonly type: "reqSignedUrl"; - readonly params: SignedUrlParam; + readonly conn: Connection; + readonly params: ReqSignedUrlParam; } export interface ResSignedUrl extends MsgBase { // readonly type: "resSignedUrl"; - readonly params: SignedUrlParam; - readonly signedUrl: string; -} - -/* Subscribe Meta */ - -export interface ReqSubscribeMeta extends MsgBase { - readonly type: "reqSubscribeMeta"; - readonly subscriberId: string; - readonly key: ConnectionKey; -} - -// export type ReqSubscribeMetaWithConnId = AddConnId; - -// export function MsgIsReqSubscribeMetaWithConnId(req: MsgBase): req is ReqSubscribeMetaWithConnId { -// return req.type === "reqSubscribeMetaWithConnId"; -// } - -export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { - return req.type === "reqSubscribeMeta"; -} - -export function buildReqSubscriptMeta(sthis: NextId, ck: ConnectionKey, subscriberId: string): ReqSubscribeMeta { - return { - tid: sthis.nextId().str, - subscriberId, - type: "reqSubscribeMeta", - version: VERSION, - key: ck, - }; -} - -export interface ResSubscribeMeta extends MsgBase { - readonly type: "resSubscribeMeta"; - readonly subscriberId: string; readonly conn: Connection; - readonly key: ConnectionKey; -} - -export function buildResSubscriptMeta(req: ReqSubscribeMeta, ctx: Connection): ResSubscribeMeta { - return { - tid: req.tid, - type: "resSubscribeMeta", - conn: ctx, - subscriberId: req.subscriberId, - key: req.key, - version: VERSION, - }; -} - -export function MsgIsResSubscribeMeta>( - qs: T -): qs is T & ReqRes { - return qs.res.type === "resSubscribeMeta"; -} - -/* Put Meta */ -export interface ReqPutMeta extends MsgBase { - readonly type: "reqPutMeta"; - readonly key: ConnectionKey; readonly params: SignedUrlParam; - readonly metas: CRDTEntry[]; -} - -// export type ReqPutMetaWithConnId = AddConnId; - -// export function MsgIsReqPutMetaWithConnId(msg: MsgBase): msg is ReqPutMetaWithConnId { -// return msg.type === "reqPutMetaWithConnId"; -// } - -export interface PutMetaParam { - readonly metaId: string; - readonly metas: CRDTEntry[]; - readonly signedPutUrl: string; - readonly connId: string; -} - -export interface ResPutMeta extends MsgBase, PutMetaParam { - readonly type: "resPutMeta"; - readonly key: ConnectionKey; -} - -export function buildReqPutMeta( - sthis: NextId, - key: ConnectionKey, - signedUrlParams: SignedUrlParam, - metas: CRDTEntry[] -): ReqPutMeta { - return { - tid: sthis.nextId().str, - type: "reqPutMeta", - version: VERSION, - params: signedUrlParams, - key, - metas, - }; -} - -export function MsgIsReqPutMeta(msg: MsgBase): msg is ReqPutMeta { - return msg.type === "reqPutMeta"; -} - -export function buildResPutMeta(req: ReqPutMeta, metaParam: PutMetaParam): ResPutMeta { - return { - ...metaParam, - tid: req.tid, - type: "resPutMeta", - key: req.key, - version: VERSION, - }; -} - -export function MsgIsResPutMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resPutMeta" && qs.req.type === "reqPutMeta"; -} - -export interface ConnSubId { - readonly connId: string; - readonly subscriberId: string; -} - -/** - * This is used for non WebSocket server implementations - * to retrieve the meta data. It should be done by polling - * and might implement long polling. - * It will answer with a UpdateMetaEvent. - */ -export interface ReqUpdateMeta extends MsgBase, ConnSubId { - readonly type: "reqUpdateMeta"; - readonly key: ConnectionKey; -} - -export interface UpdateMetaEvent extends MsgBase, ConnSubId { - readonly type: "updateMeta"; - readonly key: ConnectionKey; - readonly metaId: string; - readonly metas: CRDTEntry[]; -} - -export function buildUpdateMetaEvent(rq: ReqRes, consub: ConnSubId): UpdateMetaEvent { - return { - ...consub, - tid: rq.res.tid, - type: "updateMeta", - key: rq.res.key, - metaId: rq.res.metaId, - metas: rq.req.metas, - version: rq.res.version, - }; -} - -export function MsgIsUpdateMetaEvent(msg: MsgBase): msg is UpdateMetaEvent { - return msg.type === "updateMeta"; -} - -/* Get Meta */ -export interface ReqGetMeta extends MsgBase { - readonly type: "reqGetMeta"; - readonly params: SignedUrlParam; - readonly key: ConnectionKey; -} - -// export type ReqGetMetaWithConnId = AddConnId; - -export function MsgIsReqGetMeta(msg: MsgBase): msg is ReqGetMeta { - return msg.type === "reqGetMeta"; -} - -// export function MsgIsReqGetMetaWithConnId(msg: MsgBase): msg is ReqGetMetaWithConnId { -// return msg.type === "reqGetMetaWithConnId"; -// } - -export interface GetMetaParam { - // readonly params: SignedUrlParam; - // readonly key: ConnectionKey; - readonly status: "found" | "not-found" | "redirect"; - readonly metas: CRDTEntry[]; - readonly connId: string; - // if set client should query this url to retrieve the meta - readonly signedGetUrl?: string; -} - -export interface ResGetMeta extends MsgBase, GetMetaParam { - readonly type: "resGetMeta"; - readonly params: SignedUrlParam; - readonly key: ConnectionKey; -} - -export function buildReqGetMeta(sthis: NextId, key: ConnectionKey, signedUrlParams: SignedUrlParam): ReqGetMeta { - return { - tid: sthis.nextId().str, - key, - type: "reqGetMeta", - version: VERSION, - params: signedUrlParams, - }; + readonly signedUrl: string; } -export function buildResGetMeta(req: ReqGetMeta, metaParam: GetMetaParam): ResGetMeta { - return { - ...metaParam, +export async function buildRes( + method: SignedUrlParam["method"], + store: FPStoreTypes, + type: string, + sthis: SuperThis, + logger: Logger, + req: Q, + ctx: CalculatePreSignedUrl +): Promise> { + const psm = { + params: { + ...req.params, + method, + store, + }, + conn: req.conn, tid: req.tid, - type: "resGetMeta", - params: req.params, - key: req.key, - version: VERSION, - }; -} - -export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resGetMeta" && qs.req.type === "reqGetMeta"; -} - -/* Del Meta */ -export interface ReqDelMeta extends MsgBase { - readonly type: "reqDelMeta"; - readonly params: SignedUrlParam; - readonly key: ConnectionKey; -} - -// export type ReqDelMetaWithConnId = AddConnId; - -// export function MsgIsReqDelMetaWithConnId(msg: MsgBase): msg is ReqDelMetaWithConnId { -// return msg.type === "reqDelMetaWithConnId"; -// } - -export interface DelMetaParam { - readonly params: SignedUrlParam; - // readonly key: ConnectionKey; - readonly status: "found" | "not-found" | "redirect" | "unsupported"; - readonly connId: string; - // if set client should query this url to retrieve the meta - readonly signedDelUrl?: string; -} - -export interface ResDelMeta extends MsgBase, DelMetaParam { - readonly type: "resDelMeta"; -} - -export function buildReqDelMeta(sthis: NextId, key: ConnectionKey, signedUrlParams: SignedUrlParam): ReqDelMeta { - return { - tid: sthis.nextId().str, - key, - type: "reqDelMeta", - version: VERSION, - params: signedUrlParams, - }; -} - -export function MsgIsReqDelMeta(msg: MsgBase): msg is ReqDelMeta { - return msg.type === "reqDelMeta"; -} - -export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDelMeta { + } satisfies PreSignedMsg; + const rSignedUrl = await ctx.calculatePreSignedUrl(psm); + if (rSignedUrl.isErr()) { + return buildErrorMsg(sthis, logger, req, rSignedUrl.Err()); + } return { - ...metaParam, - tid: req.tid, - type: "resDelMeta", - // key: req.key, - version: VERSION, - }; -} - -export function MsgIsResDelMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; -} - -export interface ReqGetData extends ReqSignedUrl { - readonly type: "reqGetData"; -} - -export function MsgIsReqGetData(msg: MsgBase): msg is ReqGetData { - return msg.type === "reqGetData"; -} - -export interface ResGetData extends ResSignedUrl { - readonly type: "resGetData"; - readonly payload: Uint8Array; // transfered via JSON base64 -} - -export interface ReqPutData extends ReqSignedUrl { - readonly type: "reqPutData"; - readonly payload: Uint8Array; // transfered via JSON base64 -} - -export function MsgIsReqPutData(msg: MsgBase): msg is ReqPutData { - return msg.type === "reqPutData"; -} - -export interface ResPutData extends ResSignedUrl { - readonly type: "resPutData"; -} - -export interface ReqDelData extends ReqSignedUrl { - readonly type: "reqGetData"; -} - -export function MsgIsReqDelData(msg: MsgBase): msg is ReqDelData { - return msg.type === "reqDelData"; -} - -export interface ResDelData extends ResSignedUrl { - readonly type: "resDelData"; -} - -export interface ReqGetWAL extends ReqSignedUrl { - readonly type: "reqGetWAL"; -} - -export function MsgIsReqGetWAL(msg: MsgBase): msg is ReqGetWAL { - return msg.type === "reqGetWAL"; -} - -export interface ResGetWAL extends ResSignedUrl { - readonly type: "resGetWAL"; - readonly payload: Uint8Array; // transfered via JSON base64 -} - -export interface ReqPutWAL extends Omit { - readonly type: "reqPutWAL"; - readonly payload: Uint8Array; // transfered via JSON base64 -} - -export function MsgIsReqPutWAL(msg: MsgBase): msg is ReqPutWAL { - return msg.type === "reqPutWAL"; -} - -export interface ResPutWAL extends Omit { - readonly type: "resPutWAL"; -} - -export interface ReqDelWAL extends Omit { - readonly type: "reqGetWAL"; -} - -export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { - return msg.type === "reqDelWAL"; -} - -export interface ResDelWAL extends Omit { - readonly type: "resDelWAL"; + ...req, + params: psm.params, + type, + signedUrl: rSignedUrl.Ok().toString(), + } as unknown as WithErrorMsg; } diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 7317fc8b..12c03beb 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -1,6 +1,7 @@ import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; import { buildReqGestalt, + Connection, defaultGestalt, EnDeCoder, Gestalt, @@ -9,11 +10,11 @@ import { MsgIsResGestalt, ReqGestalt, ReqOpen, + RequestOpts, ResGestalt, - ResOpen, + WithErrorMsg, } from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; -import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; import { HttpConnection } from "./http-connection.js"; import { WSConnection } from "./ws-connection.js"; @@ -49,7 +50,8 @@ export interface ExchangedGestalt { export interface MsgConnection { // readonly ws: WebSocket; // readonly params: ConnectionKey; - conn?: ResOpen; + // qsOpen: ReqRes; + conn: Connection; readonly exchangedGestalt: ExchangedGestalt; request(req: Q, opts: RequestOpts): Promise>; start(): Promise>; diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index b60f8fe1..44d337aa 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -1,7 +1,9 @@ -import { UpgradeWebSocket } from "hono/ws"; -import { CORS, HonoServerImpl } from "./hono-server.js"; -import { HttpHeader } from "@adviser/cement"; -import { Hono } from "hono"; +import { UpgradeWebSocket, WSEvents } from "hono/ws"; +import { ConnMiddleware, CORS, HonoServerImpl } from "./hono-server.js"; +import { HttpHeader, Result, URI } from "@adviser/cement"; +import { Context, Hono } from "hono"; +import { calculatePreSignedUrl, PreSignedConnMsg } from "./pre-signed-url.js"; +import { Env } from "./backend/env.js"; interface ServerType { close(fn: () => void): void; @@ -10,14 +12,33 @@ interface ServerType { type serveFn = (options: unknown, listeningListener?: ((info: unknown) => void) | undefined) => ServerType; export class NodeHonoServer implements HonoServerImpl { - upgradeWebSocket!: UpgradeWebSocket; + _upgradeWebSocket!: UpgradeWebSocket; _injectWebSocket!: (t: unknown) => void; _serve!: serveFn; _server!: ServerType; readonly headers: HttpHeader; - constructor(headers?: HttpHeader) { + readonly env: Env; + constructor(env: Env, headers?: HttpHeader) { this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + this.env = env; + } + + calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { + return calculatePreSignedUrl(p, { + storageUrl: URI.from(this.env.STORAGE_URL), + aws: { + accessKeyId: this.env.ACCESS_KEY_ID, + secretAccessKey: this.env.SECRET_ACCESS_KEY, + region: this.env.REGION, + }, + }); + } + + upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { + return async (_conn, c, next) => { + return this._upgradeWebSocket(createEvents)(c, next); + }; } async start(app: Hono): Promise { @@ -25,7 +46,7 @@ export class NodeHonoServer implements HonoServerImpl { const { serve } = await import("@hono/node-server"); this._serve = serve as serveFn; const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }); - this.upgradeWebSocket = upgradeWebSocket; + this._upgradeWebSocket = upgradeWebSocket; this._injectWebSocket = injectWebSocket as (t: unknown) => void; } diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts index b811faaa..b4bf0edc 100644 --- a/src/cloud/pre-signed-url.ts +++ b/src/cloud/pre-signed-url.ts @@ -1,50 +1,78 @@ -import { Result, URI, BuildURI } from "@adviser/cement"; +import { Result, URI } from "@adviser/cement"; import { AwsClient } from "aws4fetch"; -import { Env } from "./backend/env.js"; -import { ReqSignedUrl } from "./msg-types.js"; +import { Connection, SignedUrlParam } from "./msg-types.js"; -export async function calculatePreSignedUrl(req: ReqSignedUrl, env: Env, amzDate?: string): Promise> { - // verify if you are not overriding - let store: string = req.params.store; - if (req.params.index?.length) { - store = `${store}-${req.params.index}`; +export interface PreSignedMsg { + readonly params: SignedUrlParam; + readonly tid: string; + readonly conn?: Connection; +} + +export interface PreSignedConnMsg { + readonly params: SignedUrlParam; + readonly tid: string; + readonly conn: Connection; +} + +export interface PreSignedEnv { + readonly storageUrl: URI; + readonly aws: { + readonly accessKeyId: string; + readonly secretAccessKey: string; + readonly region?: string; + }; + readonly test?: { + readonly amzDate?: string; + }; +} + +export async function calculatePreSignedUrl(ipsm: PreSignedMsg, env: PreSignedEnv): Promise> { + if (!ipsm.conn) { + return Result.Err(new Error("Connection is not supported")); } - const expiresInSeconds = req.params.expires || 60 * 60; + const psm = ipsm as PreSignedConnMsg; - let suffix = ""; - switch (req.params.store) { - case "wal": - case "meta": - suffix = ".json"; - break; - default: - break; + // verify if you are not overriding + let store: string = psm.params.store; + if (psm.params.index?.length) { + store = `${store}-${psm.params.index}`; } + const expiresInSeconds = psm.params.expires || 60 * 60; + + const suffix = ""; + // switch (psm.params.store) { + // case "wal": + // case "meta": + // suffix = ".json"; + // break; + // default: + // break; + // } - const opUrl = BuildURI.from(env.STORAGE_URL) - // .protocol(vals.protocol === "ws" ? "http:" : "https:") + const opUrl = env.storageUrl + .build() + // .protocol(vals.protocuol === "ws" ? "http:" : "https:") .setParam("X-Amz-Expires", expiresInSeconds.toString()) - .setParam("tid", req.tid) - .appendRelative(req.params.tenantId) - .appendRelative(req.params.name) + .setParam("tid", psm.tid) + .appendRelative(psm.conn.key.tenant) + .appendRelative(psm.conn.key.ledger) .appendRelative(store) - .appendRelative(`${req.params.key}${suffix}`) + .appendRelative(`${psm.params.key}${suffix}`) .URI(); const a4f = new AwsClient({ - accessKeyId: env.ACCESS_KEY_ID, - secretAccessKey: env.SECRET_ACCESS_KEY, - region: env.REGION || "us-east-1", + ...env.aws, + region: env.aws.region || "us-east-1", service: "s3", }); const signedUrl = await a4f .sign( new Request(opUrl.toString(), { - method: req.params.method, + method: psm.params.method, }), { aws: { signQuery: true, - datetime: amzDate, + datetime: env.test?.amzDate, // datetime: env.TEST_DATE, }, } diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index 13159eb3..fddf72bd 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -1,6 +1,5 @@ import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { RequestOpts, WithErrorMsg } from "./msg-processor.js"; import { MsgBase, MsgIsError, @@ -10,6 +9,9 @@ import { MsgIsResOpen, MsgerParams, WaitForTid, + Connection, + WithErrorMsg, + RequestOpts, } from "./msg-types.js"; import { ExchangedGestalt, MsgConnection, OnMsgFn, UnReg } from "./msger.js"; @@ -36,8 +38,9 @@ export class WSConnection implements MsgConnection { readonly waitForTid = new Map(); opened = false; - get conn(): ResOpen | undefined { - return this.wqs.resOpen; + get conn(): Connection { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.wqs.resOpen!.conn!; } constructor(sthis: SuperThis, wsq: WSReqOpen, msgP: MsgerParams, exGestalt: ExchangedGestalt) { @@ -52,17 +55,29 @@ export class WSConnection implements MsgConnection { const onOpenFuture: Future> = new Future>(); const timer = setTimeout(() => { const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError(); - this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, err)); + this.toMsg(buildErrorMsg(this.sthis, this.logger, {} as MsgBase, err)); + console.log("WSConnection.start-timer"); onOpenFuture.resolve(Result.Err(err)); }, this.msgP.timeout); this.wqs.ws.onopen = () => { + console.log("WSConnection.onopen"); onOpenFuture.resolve(Result.Ok(undefined)); this.opened = true; }; this.wqs.ws.onerror = (ierr) => { const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError(); onOpenFuture.resolve(Result.Err(err)); - this.toMsg(buildErrorMsg(this.sthis, this.logger, { tid: "internal", conn: this.conn } as MsgBase, err)); + let conn: Connection; + try { + conn = this.conn; + } catch (_err) { + conn = { + key: { tenant: "not-connect", ledger: "not-connect" }, + reqId: "not-connect", + resId: "not-connect", + }; + } + this.toMsg(buildErrorMsg(this.sthis, this.logger, { conn } as MsgBase, err)); }; this.wqs.ws.onmessage = (evt) => { if (!this.opened) { @@ -70,7 +85,7 @@ export class WSConnection implements MsgConnection { buildErrorMsg( this.sthis, this.logger, - { tid: "internal" } as MsgBase, + {} as MsgBase, this.logger.Error().Msg("Received message before onOpen").AsError() ) ); @@ -86,11 +101,14 @@ export class WSConnection implements MsgConnection { }); }; /* wait for onOpen */ - const rOpen = await onOpenFuture.asPromise().finally(() => clearTimeout(timer)); + const rOpen = await onOpenFuture.asPromise().finally(() => { + clearTimeout(timer); + }); if (rOpen.isErr()) { return rOpen; } const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }); + console.log("WSConnection.start-4"); if (!MsgIsResOpen(resOpen)) { return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); } @@ -157,7 +175,7 @@ export class WSConnection implements MsgConnection { return buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Msg("Connection not open").AsError()); } const future = new Future(); - this.waitForTid.set(req.tid, { tid: req.tid, future, waitFor: opts.waitFor }); + this.waitForTid.set(req.tid, { tid: req.tid, future, waitFor: opts.waitFor, timeout: opts.timeout }); await this.sendMsg(req); return future.asPromise(); } From d4139384f9d25a84d51bf30ddeff447f756e7488 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Wed, 25 Dec 2024 19:51:23 +0100 Subject: [PATCH 36/83] chore: refactor cloud test helper --- package.json | 6 +- pnpm-lock.yaml | 38 +- src/cloud/backend/env.d.ts | 3 + src/cloud/backend/server.ts | 6 +- .../client/{gateway.ts-off => gateway.ts} | 511 +++++++++--------- src/cloud/connection.test.ts | 192 +------ src/cloud/hono-server.ts | 4 +- src/cloud/msg-processor.ts | 259 +++++++++ src/cloud/msg-type-meta.ts | 4 +- src/cloud/msg-types-data.ts | 30 +- src/cloud/msg-types-wal.ts | 30 +- src/cloud/msg-types.ts | 39 +- src/cloud/msger.ts | 6 +- src/cloud/test-helper.ts | 190 +++++++ src/cloud/ws-connection.ts | 3 - 15 files changed, 788 insertions(+), 533 deletions(-) rename src/cloud/client/{gateway.ts-off => gateway.ts} (53%) create mode 100644 src/cloud/msg-processor.ts create mode 100644 src/cloud/test-helper.ts diff --git a/package.json b/package.json index 29a7c0a0..01b495a3 100644 --- a/package.json +++ b/package.json @@ -98,14 +98,14 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.2.45" + "@adviser/cement": "^0.3.0" }, "dependencies": { - "@adviser/cement": "^0.2.45", + "@adviser/cement": "^0.3.0", "@aws-sdk/client-s3": "^3.705.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "^0.19.118", + "@fireproof/core": "^0.19.119", "@fireproof/vendor": "^1.0.0", "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 90d28d46..e078a726 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.45 - version: 0.2.45(typescript@5.7.2) + specifier: ^0.3.0 + version: 0.3.0(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.705.0 version: 3.705.0 @@ -21,8 +21,8 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: ^0.19.118 - version: 0.19.118(react@18.3.1)(typescript@5.7.2) + specifier: ^0.19.119 + version: 0.19.119(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: ^1.0.0 version: 1.0.0 @@ -216,8 +216,8 @@ importers: packages: - '@adviser/cement@0.2.45': - resolution: {integrity: sha512-322C+IWgUhjomzTKohy86maLoOASUf5ZrIAs01dfZF2NLey/6GlUi3vehR4MpDXo/8lceuvemVCw/wd7kmWOtg==} + '@adviser/cement@0.3.0': + resolution: {integrity: sha512-E0J+oHIHCfBsRX3IVYSXKtMczfsyuPS8CbAVYZeNYtaJFItq29IGMMXi0s9B9Y8BpLycHCaPvSydOxCKE/sPYw==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -1074,8 +1074,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.118': - resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} + '@fireproof/core@0.19.119': + resolution: {integrity: sha512-PSluwTsob3i5+tnrxGIQDNGsJJZ2xzs1uxAaBHyPoeo+wqoDkH86XTJTDpIR2SuL2RfMhX2t8EvtsF5sz4C8/Q==} peerDependencies: react: ^18.3.1 @@ -2905,8 +2905,8 @@ packages: resolution: {integrity: sha512-mQ2o1VayrZ6Jaz8VyP8B7h/hdn2iAnbUOrQh4rTiwbpULhktpD8IpHGBw8Qo2fmv97Z1P3YzLF3X/DkbIHBQmA==} engines: {node: '>=8.11.4', npm: 6.10.1} - memfs@4.15.0: - resolution: {integrity: sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==} + memfs@4.15.1: + resolution: {integrity: sha512-ufCzgFwiVnR6R9cCYuvwznJdhdYXEvFl0hpnM4cCtVaVkHuqBR+6fo2sqt1SSMdp+uiHw9GyPZr3OMM5tqjSmQ==} engines: {node: '>= 4.0.0'} memoizee@0.4.17: @@ -3137,8 +3137,8 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@6.1.0: - resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} engines: {node: '>=18'} p-locate@5.0.0: @@ -4074,7 +4074,7 @@ packages: snapshots: - '@adviser/cement@0.2.45(typescript@5.7.2)': + '@adviser/cement@0.3.0(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4984,16 +4984,16 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.119(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.2.45(typescript@5.7.2) + '@adviser/cement': 0.3.0(typescript@5.7.2) '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 idb: 8.0.1 - memfs: 4.15.0 + memfs: 4.15.1 multiformats: 13.3.1 - p-limit: 6.1.0 + p-limit: 6.2.0 p-map: 7.0.3 p-retry: 6.2.1 prolly-trees: 1.0.4 @@ -7378,7 +7378,7 @@ snapshots: is-nan-x: 2.1.1 to-number-x: 3.2.2 - memfs@4.15.0: + memfs@4.15.1: dependencies: '@jsonjoy.com/json-pack': 1.1.1(tslib@2.8.1) '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) @@ -7643,7 +7643,7 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@6.1.0: + p-limit@6.2.0: dependencies: yocto-queue: 1.1.1 diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index 73c55d17..b7cc3bf5 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -9,6 +9,7 @@ export interface Env { // bucket: R2Bucket; // kv_store: KVNamespace; + /** AWS/S3 access key ID for storage backend */ ACCESS_KEY_ID: string; ACCOUNT_ID: string; BUCKET_NAME: string; @@ -25,7 +26,9 @@ export interface Env { FP_STACK: string; FP_FORMAT: string; FP_PROTOCOL: string; + /** Test date in ISO8601 format (YYYYMMDD'T'HHmmss'Z'). Optional. */ TEST_DATE?: string; + /** Maximum idle time in seconds before connection timeout. Optional. */ MAX_IDLE_TIME?: string; FP_META_GROUPS: DurableObjectNamespace; diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 70435e03..44d0efb2 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -414,7 +414,11 @@ export default { }); const msgP = defaultMsgParams(sthis, { hasPersistent: true, - protocol: env.FP_PROTOCOL === "ws" ? "ws" : "http", + protocolCapabilities: env.FP_PROTOCOL + ? env.FP_PROTOCOL === "ws" + ? ["stream"] + : ["reqRes"] + : ["reqRes", "stream"], }); const gs = defaultGestalt(msgP, { id: env.FP_PROTOCOL ? (env.FP_PROTOCOL === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", diff --git a/src/cloud/client/gateway.ts-off b/src/cloud/client/gateway.ts similarity index 53% rename from src/cloud/client/gateway.ts-off rename to src/cloud/client/gateway.ts index 0c9c431b..1709c6fb 100644 --- a/src/cloud/client/gateway.ts-off +++ b/src/cloud/client/gateway.ts @@ -1,26 +1,22 @@ // import PartySocket, { PartySocketOptions } from "partysocket"; -import { Result, URI, KeyedResolvOnce, exception2Result, Future } from "@adviser/cement"; -import { bs, CRDTEntry, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; +import { Result, URI, KeyedResolvOnce, exception2Result, key } from "@adviser/cement"; +import { bs, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@fireproof/core"; import { - buildReqDelMeta, - buildReqGetMeta, - buildReqPutMeta, - buildReqSubscriptMeta, - ConnectionKey, + buildErrorMsg, + buildReqOpen, + Connection, + FPStoreTypes, HttpMethods, + keyTenantLedger, MsgBase, MsgIsError, - MsgIsUpdateMetaEvent, ReqSignedUrl, - ResDelMeta, - ResGetMeta, - ResPutMeta, - ResSignedUrl, - ResSubscribeMeta, + TenantLedger, + WithErrorMsg, } from "../msg-types.js"; -import { newWebSocket } from "../new-websocket.js"; import { to_uint8 } from "../../coerce-binary.js"; -import { MsgConnection } from "../msger.js"; +import { MsgConnection, Msger } from "../msger.js"; +import { MsgIsResGetData, MsgIsResPutData, ResDelData, ResGetData, ResPutData } from "../msg-types-data.js"; const VERSION = "v0.1-fp-cloud"; @@ -38,66 +34,85 @@ abstract class BaseGateway { this.logger = ensureLogger(sthis, module); } - abstract getConn(uri: URI, conn: Connection): Promise>; - async get(uri: URI, prConn: Promise>): Promise> { + abstract getConn(uri: URI, conn: MsgConnection): Promise>; + async get(uri: URI, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in getConn").ResultError(); } const conn = rConn.Ok(); - this.logger.Debug().Any("conn", conn.key).Msg("get"); + // this.logger.Debug().Any("conn", conn.key).Msg("get"); return this.getConn(uri, conn); } - abstract putConn(uri: URI, body: Uint8Array, conn: Connection): Promise>; - async put(uri: URI, body: Uint8Array, prConn: Promise>): Promise> { + abstract putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise>; + async put(uri: URI, body: Uint8Array, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); } const conn = rConn.Ok(); - this.logger.Debug().Any("conn", conn.key).Msg("put"); + // this.logger.Debug().Any("conn", conn.key).Msg("put"); return this.putConn(uri, body, conn); } - abstract delConn(uri: URI, conn: Connection): Promise>; - async delete(uri: URI, prConn: Promise>): Promise> { + + abstract delConn(uri: URI, conn: MsgConnection): Promise>; + async delete(uri: URI, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); } const conn = rConn.Ok(); - this.logger.Debug().Any("conn", conn.key).Msg("del"); + // this.logger.Debug().Any("conn", conn.key).Msg("del"); return this.delConn(uri, conn); } - prepareReqSignedUrl(uri: URI, method: HttpMethods, cKey: ConnectionKey): Result { + // prepareReqSignedUrl(type: string, method: HttpMethods, store: FPStoreTypes, uri: URI, conn: Connection): Result { + + // const sig = { + // conn, + // params: { + // method, + // store, + // key: uri.getParam(" + // } satisfies ReqSignedUrl; + // return Result.Ok(buildReqSignedUrl(this.sthis, type, sig, conn)) + // } + + async getResSignedUrl( + type: string, + method: HttpMethods, + store: FPStoreTypes, + waitForFn: (msg: MsgBase) => boolean, + uri: URI, + conn: MsgConnection + ): Promise> { const rParams = uri.getParamsResult({ - store: 0, - key: 0, + key: key.REQUIRED, + store: key.REQUIRED, + path: key.OPTIONAL, + index: key.OPTIONAL, }); if (rParams.isErr()) { - return this.logger.Error().Err(rParams).Msg("Error in getParamsResult").ResultError(); + return buildErrorMsg(this.sthis, this.logger, {} as MsgBase, rParams.Err()); } - const { store, key } = rParams.Ok(); - return Result.Ok({ - buildReqSignedUrl({ - // auth: await getUcanAuthFromUri(uri), - params: { - ...cKey, - store: store as FPStoreTypes, - key, - method, - }, - }) - ); - } - - async getResSignedUrl(uri: URI, method: HttpMethods, conn: Connection): Promise> { - const rsu = this.prepareReqSignedUrl(uri, method, conn.key); - if (rsu.isErr()) { - return Result.Err(rsu.Err()); - } - return conn.request(rsu.Ok(), { waitType: "resSignedUrl" }); + const params = rParams.Ok(); + if (store !== params.store) { + return buildErrorMsg(this.sthis, this.logger, {} as MsgBase, new Error("store mismatch")); + } + const rsu = { + tid: this.sthis.nextId().str, + type, + conn: conn.conn, + params: { + method, + store, + ...params, + key: params.key, + }, + version: VERSION, + } as ReqSignedUrl; + return conn.request(rsu, { waitFor: waitForFn }); } async putObject(uri: URI, uploadUrl: string, body: Uint8Array): Promise> { @@ -157,28 +172,50 @@ class DataGateway extends BaseGateway implements StoreTypeGateway { constructor(sthis: SuperThis) { super(sthis, "DataGateway"); } - async getConn(uri: URI, conn: Connection): Promise> { - const rResSignedUrl = await this.getResSignedUrl(uri, "GET", conn); - if (rResSignedUrl.isErr()) { + async getConn(uri: URI, conn: MsgConnection): Promise> { + // type: string, method: HttpMethods, store: FPStoreTypes, waitForFn: + const rResSignedUrl = await this.getResSignedUrl( + "reqGetData", + "GET", + "data", + MsgIsResGetData, + uri, + conn + ); + if (MsgIsError(rResSignedUrl)) { return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); } - const { signedUrl: downloadUrl } = rResSignedUrl.Ok(); + const { signedUrl: downloadUrl } = rResSignedUrl; return this.getObject(uri, downloadUrl); } - async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { - const rResSignedUrl = await this.getResSignedUrl(uri, "PUT", conn); - if (rResSignedUrl.isErr()) { + async putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise> { + const rResSignedUrl = await this.getResSignedUrl( + "reqPutData", + "PUT", + "data", + MsgIsResPutData, + uri, + conn + ); + if (MsgIsError(rResSignedUrl)) { return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); } - const { signedUrl: uploadUrl } = rResSignedUrl.Ok(); + const { signedUrl: uploadUrl } = rResSignedUrl; return this.putObject(uri, uploadUrl, body); } - async delConn(uri: URI, conn: Connection): Promise> { - const rResSignedUrl = await this.getResSignedUrl(uri, "DELETE", conn); - if (rResSignedUrl.isErr()) { + async delConn(uri: URI, conn: MsgConnection): Promise> { + const rResSignedUrl = await this.getResSignedUrl( + "reqDelData", + "DELETE", + "data", + MsgIsResPutData, + uri, + conn + ); + if (MsgIsError(rResSignedUrl)) { return this.logger.Error().Err(rResSignedUrl).Msg("Error in buildResSignedUrl").ResultError(); } - const { signedUrl: deleteUrl } = rResSignedUrl.Ok(); + const { signedUrl: deleteUrl } = rResSignedUrl; return this.delObject(uri, deleteUrl); } } @@ -188,68 +225,74 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { super(sthis, "MetaGateway"); } - async getConn(uri: URI, conn: Connection): Promise> { - const rkey = uri.getParamResult("key"); - if (rkey.isErr()) { - return Result.Err(rkey.Err()); - } - const rsu = buildReqGetMeta(this.sthis, conn.key, { - ...conn.key, - method: "GET", - store: "meta", - key: rkey.Ok(), - }); - const rRes = await conn.request(rsu, { - waitType: "resGetMeta", - }); - if (rRes.isErr()) { - return Result.Err(rRes.Err()); - } - const res = rRes.Ok(); - if (MsgIsError(res)) { - return Result.Err(res); - } - if (res.signedGetUrl) { - return this.getObject(uri, res.signedGetUrl); - } - return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async getConn(uri: URI, conn: MsgConnection): Promise> { + // const rkey = uri.getParamResult("key"); + // if (rkey.isErr()) { + // return Result.Err(rkey.Err()); + // } + // const rsu = buildReqGetMeta(this.sthis, conn.key, { + // ...conn.key, + // method: "GET", + // store: "meta", + // key: rkey.Ok(), + // }); + // const rRes = await conn.request(rsu, { + // waitType: "resGetMeta", + // }); + // if (rRes.isErr()) { + // return Result.Err(rRes.Err()); + // } + // const res = rRes.Ok(); + // if (MsgIsError(res)) { + // return Result.Err(res); + // } + // if (res.signedGetUrl) { + // return this.getObject(uri, res.signedGetUrl); + // } + // return Result.Ok(this.sthis.txt.encode(JSON.stringify(res.metas))); + return Result.Ok(new Uint8Array()); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise> { + // const bodyRes = Result.Ok(body); // await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); + // if (bodyRes.isErr()) { + // return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); + // } + // const rsu = this.prepareReqSignedUrl(uri, "PUT", conn.key); + // if (rsu.isErr()) { + // return Result.Err(rsu.Err()); + // } + // const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; + // this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); + // const req = buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas); + // const res = await conn.request(req, { waitType: "resPutMeta" }); + // if (res.isErr()) { + // return Result.Err(res.Err()); + // } + // // console.log("putMeta", JSON.stringify({dbMetas, res})); + // this.logger.Debug().Any("qs", { req, res: res.Ok() }).Msg("putMeta"); + // this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); + // return res; + return Result.Ok(undefined); } - async putConn(uri: URI, body: Uint8Array, conn: Connection): Promise> { - const bodyRes = Result.Ok(body); // await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); - if (bodyRes.isErr()) { - return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); - } - const rsu = this.prepareReqSignedUrl(uri, "PUT", conn.key); - if (rsu.isErr()) { - return Result.Err(rsu.Err()); - } - const dbMetas = JSON.parse(this.sthis.txt.decode(bodyRes.Ok())) as CRDTEntry[]; - this.logger.Debug().Any("dbMetas", dbMetas).Msg("putMeta"); - const req = buildReqPutMeta(this.sthis, conn.key, rsu.Ok().params, dbMetas); - const res = await conn.request(req, { waitType: "resPutMeta" }); - if (res.isErr()) { - return Result.Err(res.Err()); - } - // console.log("putMeta", JSON.stringify({dbMetas, res})); - this.logger.Debug().Any("qs", { req, res: res.Ok() }).Msg("putMeta"); - this.putObject(uri, res.Ok().signedPutUrl, bodyRes.Ok()); - return res; - } - async delConn(uri: URI, conn: Connection): Promise> { - const rsu = this.prepareReqSignedUrl(uri, "DELETE", conn.key); - if (rsu.isErr()) { - return Result.Err(rsu.Err()); - } - const res = await conn.request(buildReqDelMeta(this.sthis, conn.key, rsu.Ok().params), { - waitType: "resDelMeta", - }); - if (res.isErr()) { - return Result.Err(res.Err()); - } - const { signedDelUrl } = res.Ok(); - if (signedDelUrl) { - return this.delObject(uri, signedDelUrl); - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async delConn(uri: URI, conn: MsgConnection): Promise> { + // const rsu = this.prepareReqSignedUrl(uri, "DELETE", conn.key); + // if (rsu.isErr()) { + // return Result.Err(rsu.Err()); + // } + // const res = await conn.request(buildReqDelMeta(this.sthis, conn.key, rsu.Ok().params), { + // waitType: "resDelMeta", + // }); + // if (res.isErr()) { + // return Result.Err(res.Err()); + // } + // const { signedDelUrl } = res.Ok(); + // if (signedDelUrl) { + // return this.delObject(uri, signedDelUrl); + // } + // return Result.Ok(undefined); return Result.Ok(undefined); } } @@ -327,7 +370,7 @@ interface Subscription { readonly unsub: () => void; } const subscriptions = new Map(); -const doServerSubscribe = new KeyedResolvOnce(); +// const doServerSubscribe = new KeyedResolvOnce(); const trackPuts = new Set(); export class FireproofCloudGateway implements bs.Gateway { readonly logger: Logger; @@ -374,21 +417,6 @@ export class FireproofCloudGateway implements bs.Gateway { return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); } - async put(uri: URI, body: Uint8Array): Promise> { - const ret = await getStoreTypeGateway(this.sthis, uri).put(uri, body, this.getCloudConnection(uri)); - if (ret.isOk()) { - if (uri.getParam("testMode")) { - trackPuts.add(uri.toString()); - } - } - return ret; - } - - async delete(uri: URI): Promise { - trackPuts.delete(uri.toString()); - return getStoreTypeGateway(this.sthis, uri).delete(uri, this.getCloudConnection(uri)); - } - async close(uri: URI): Promise { const uriStr = uri.toString(); // CAUTION here is my happen a mutation of subscriptions caused by unsub @@ -409,10 +437,10 @@ export class FireproofCloudGateway implements bs.Gateway { } // fireproof://localhost:1999/?name=test-public-api&protocol=ws&store=meta - async getCloudConnection(uri: URI): Promise> { + async getCloudConnection(uri: URI): Promise> { const rParams = uri.getParamsResult({ name: 0, - protocol: "wss", + protocol: "https", store: 0, storekey: 0, }); @@ -426,115 +454,86 @@ export class FireproofCloudGateway implements bs.Gateway { if (rfingerprint.isErr()) { return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); } - const connectionKey = { - tenantId: uri.build().getParam("tendenId", rfingerprint.Ok().fingerPrint) as string, - name: params.name, - // protocol: params.protocol as ConnectionKey["protocol"], - } satisfies ConnectionKey; - - const wsUrl = uri - .build() - .protocol(params.protocol === "ws" ? "ws" : "wss") - .appendRelative("ws") - .cleanParams(); - - // forces to open a new websocket connection - const connId = uri.getParam("connId"); - if (connId) { - wsUrl.setParam("connId", connId); - } - return Result.Ok( - await keyedConnections.get(wsUrl.toString()).once(async (cKey) => { - const ws = await newWebSocket(wsUrl); - const waitOpen = new Future(); - ws.onopen = () => { - this.logger.Debug().Url(wsUrl).Msg("ws open"); - waitOpen.resolve(); - }; - ws.onerror = (err) => { - this.logger.Error().Err(err).Url(wsUrl).Msg("ws error"); - keyedConnections.unget(cKey); - }; - ws.onclose = () => { - keyedConnections.unget(cKey); - this.logger.Debug().Url(wsUrl).Msg("ws close"); - }; - await waitOpen.asPromise(); - return new ConnectionImpl(this.sthis, ws, connectionKey, () => { - keyedConnections.unget(cKey); - }); - }) - ); - } - - private notifySubscribers(data: Uint8Array, callbacks: ((msg: Uint8Array) => void)[] = []): void { - for (const cb of callbacks) { - try { - cb(data); - } catch (error) { - this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); - } - } - } - async subscribe(uri: URI, callback: (meta: Uint8Array) => void): Promise { - const rParams = uri.getParamsResult({ - store: 0, - storekey: 0, - }); - if (rParams.isErr()) { - return this.logger.Error().Err(rParams).Msg("Error in subscribe").ResultError(); - } - const { store } = rParams.Ok(); - if (store !== "meta") { - return Result.Err(new Error("store must be meta")); - } - const rConn = await this.getCloudConnection(uri); - if (rConn.isErr()) { - return this.logger.Error().Err(rConn).Msg("Error in subscribe:getCloudConnection").ResultError(); - } - const conn = rConn.Ok(); - const rResSubscribeMeta = await doServerSubscribe.get(pkKey(conn.key)).once(async () => { - const subId = this.sthis.nextId().str; - const fn = (subId: string) => (msg: MsgBase) => { - if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { - // console.log("onMessage", subId, conn.key, msg.metas); - const s = subscriptions.get(subId); - if (!s) { - return; - } - console.log("msg", JSON.stringify(msg)); - this.notifySubscribers( - this.sthis.txt.encode(JSON.stringify(msg.metas)), - s.map((s) => s.callback) - ); - } - }; - conn.onMessage(fn(subId)); - return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { - waitType: "resSubscribeMeta", - }); + const qOpen = buildReqOpen(this.sthis, { + key: { + tenant: uri.build().getParam("tenant", rfingerprint.Ok().fingerPrint) as string, + ledger: params.name, + // protocol: params.protocol as ConnectionKey["protocol"], + } satisfies TenantLedger, }); - if (rResSubscribeMeta.isErr()) { - return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); - } - const subId = rResSubscribeMeta.Ok().subscriberId; - let callbacks = subscriptions.get(subId); - if (!callbacks) { - callbacks = []; - subscriptions.set(subId, callbacks); - } - const sid = this.sthis.nextId().str; - const unsub = () => { - const idx = callbacks.findIndex((c) => c.sid === sid); - if (idx !== -1) { - callbacks.splice(idx, 1); - } - if (callbacks.length === 0) { - subscriptions.delete(subId); - } - }; - callbacks.push({ uri: uri.toString(), callback, sid, unsub }); - return Result.Ok(unsub); + return keyedConnections.get(keyTenantLedger(qOpen.conn.key)).once(async () => Msger.open(this.sthis, uri, qOpen)); + } + + // private notifySubscribers(data: Uint8Array, callbacks: ((msg: Uint8Array) => void)[] = []): void { + // for (const cb of callbacks) { + // try { + // cb(data); + // } catch (error) { + // this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); + // } + // } + // } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async subscribe(uri: URI, callback: (meta: Uint8Array) => void): Promise { + return Result.Err(new Error("Not implemented")); + // const rParams = uri.getParamsResult({ + // store: 0, + // storekey: 0, + // }); + // if (rParams.isErr()) { + // return this.logger.Error().Err(rParams).Msg("Error in subscribe").ResultError(); + // } + // const { store } = rParams.Ok(); + // if (store !== "meta") { + // return Result.Err(new Error("store must be meta")); + // } + // const rConn = await this.getCloudConnection(uri); + // if (rConn.isErr()) { + // return this.logger.Error().Err(rConn).Msg("Error in subscribe:getCloudConnection").ResultError(); + // } + // const conn = rConn.Ok(); + // const rResSubscribeMeta = await doServerSubscribe.get(pkKey(conn.key)).once(async () => { + // const subId = this.sthis.nextId().str; + // const fn = (subId: string) => (msg: MsgBase) => { + // if (MsgIsUpdateMetaEvent(msg) && subId === msg.subscriberId) { + // // console.log("onMessage", subId, conn.key, msg.metas); + // const s = subscriptions.get(subId); + // if (!s) { + // return; + // } + // console.log("msg", JSON.stringify(msg)); + // this.notifySubscribers( + // this.sthis.txt.encode(JSON.stringify(msg.metas)), + // s.map((s) => s.callback) + // ); + // } + // }; + // conn.onMessage(fn(subId)); + // return conn.request(buildReqSubscriptMeta(this.sthis, conn.key, subId), { + // waitType: "resSubscribeMeta", + // }); + // }); + // if (rResSubscribeMeta.isErr()) { + // return this.logger.Error().Err(rResSubscribeMeta).Msg("Error in subscribe:request").ResultError(); + // } + // const subId = rResSubscribeMeta.Ok().subscriberId; + // let callbacks = subscriptions.get(subId); + // if (!callbacks) { + // callbacks = []; + // subscriptions.set(subId, callbacks); + // } + // const sid = this.sthis.nextId().str; + // const unsub = () => { + // const idx = callbacks.findIndex((c) => c.sid === sid); + // if (idx !== -1) { + // callbacks.splice(idx, 1); + // } + // if (callbacks.length === 0) { + // subscriptions.delete(subId); + // } + // }; + // callbacks.push({ uri: uri.toString(), callback, sid, unsub }); + // return Result.Ok(unsub); } async destroy(_uri: URI): Promise> { @@ -543,15 +542,15 @@ export class FireproofCloudGateway implements bs.Gateway { } } -function pkKey(set?: ConnectionKey): string { - const ret = JSON.stringify( - Object.entries(set || {}) - .sort(([a], [b]) => a.localeCompare(b)) - .filter(([k]) => k !== "id") - .map(([k, v]) => ({ [k]: v })) - ); - return ret; -} +// function pkKey(set?: ConnectionKey): string { +// const ret = JSON.stringify( +// Object.entries(set || {}) +// .sort(([a], [b]) => a.localeCompare(b)) +// .filter(([k]) => k !== "id") +// .map(([k, v]) => ({ [k]: v })) +// ); +// return ret; +// } export class FireproofCloudTestStore implements bs.TestGateway { readonly logger: Logger; diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 6032e8b4..c5877a81 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -1,5 +1,5 @@ -import { ensureSuperThis, SuperThis } from "@fireproof/core"; -import { Future, URI } from "@adviser/cement"; +import { ensureSuperThis } from "@fireproof/core"; +import { URI } from "@adviser/cement"; import { buildReqGestalt, buildReqOpen, @@ -7,9 +7,6 @@ import { MsgIsResGestalt, MsgIsResOpen, defaultGestalt, - MsgerParams, - Gestalt, - ReqOpen, ReqSignedUrlParam, } from "./msg-types.js"; import { @@ -29,144 +26,10 @@ import { MsgIsResDelWAL, } from "./msg-types-wal.js"; import { applyStart, defaultMsgParams, MsgConnection, Msger } from "./msger.js"; -import { HttpConnection } from "./http-connection.js"; -import { WSConnection } from "./ws-connection.js"; import { HonoServer } from "./hono-server.js"; import { Hono } from "hono"; -import { NodeHonoServer } from "./node-hono-server.js"; -import { $ } from "zx"; -import * as fs from "fs/promises"; -import * as toml from "smol-toml"; -import { Env } from "./backend/env.js"; import { calculatePreSignedUrl, PreSignedMsg } from "./pre-signed-url.js"; - -function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "http" }), { - id: "HTTP-server", - }); - const exGt = { my, remote }; - return { - name: "HTTP", - remoteGestalt: remote, - cInstance: HttpConnection, - ok: { - url: () => URI.from(`http://127.0.0.1:${port}/fp`), - open: () => - applyStart( - Msger.openHttp( - sthis, - qOpen, - [URI.from(`http://localhost:${port}/fp`)], - { - ...msgP, - protocol: "http", - timeout: 1000, - }, - exGt - ) - ), - }, - connRefused: { - url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), - open: () => - Msger.openHttp( - sthis, - qOpen, - [URI.from(`http://localhost:${port - 1}/fp`)], - { - ...msgP, - protocol: "http", - timeout: 1000, - }, - exGt - ), - }, - timeout: { - url: () => URI.from(`http://4.7.1.1:${port}/fp`), - open: () => - Msger.openHttp( - sthis, - qOpen, - [URI.from(`http://4.7.1.1:${port}/fp`)], - { - ...msgP, - protocol: "http", - timeout: 500, - }, - exGt - ), - }, - }; -} - -function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { - const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocol: "ws" }), { id: "WS-server" }); - const exGt = { my, remote }; - return { - name: "WS", - remoteGestalt: remote, - cInstance: WSConnection, - ok: { - url: () => URI.from(`http://127.0.0.1:${port}/ws`), - open: () => - applyStart( - Msger.openWS( - sthis, - qOpen, - URI.from(`http://localhost:${port}/ws`), - { - ...msgP, - protocol: "ws", - timeout: 1000, - }, - exGt - ) - ), - }, - connRefused: { - url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), - open: () => - Msger.openWS( - sthis, - qOpen, - URI.from(`http://localhost:${port - 1}/ws`), - { - ...msgP, - protocol: "ws", - timeout: 1000, - }, - exGt - ), - }, - timeout: { - url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), - open: () => - Msger.openWS( - sthis, - qOpen, - URI.from(`http://4.7.1.1:${port - 1}/ws`), - { - ...msgP, - protocol: "ws", - timeout: 500, - }, - exGt - ), - }, - }; -} - -async function resolveToml() { - const tomlFile = "src/cloud/backend/wrangler.toml"; - const tomeStr = await fs.readFile(tomlFile, "utf-8"); - const wranglerFile = toml.parse(tomeStr) as unknown as { - env: { "test-reqRes": { vars: Env } }; - }; - return { - tomlFile, - env: wranglerFile.env["test-reqRes"].vars, - }; -} +import { CFHonoServerFactory, httpStyle, NodeHonoServerFactory, resolveToml, wsStyle } from "./test-helper.js"; async function refURL(sp: PreSignedMsg) { const { env } = await resolveToml(); @@ -189,52 +52,7 @@ async function refURL(sp: PreSignedMsg) { const sthis = ensureSuperThis(); const msgP = defaultMsgParams(sthis, { hasPersistent: true }); -for (const honoServer of [ - { - name: "NodeHonoServer", - factory: async (remoteGestalt: Gestalt, _port: number) => { - return new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer((await resolveToml()).env)); - }, - }, - { - name: "CFHonoServer", - factory: async (remoteGestalt: Gestalt, port: number) => { - const { tomlFile } = await resolveToml(); - $.verbose = !!process.env.FP_DEBUG; - const runningWrangler = $` - wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]} --no-show-interactive-dev-session & - waitPid=$! - echo "PID:$waitPid" - wait $waitPid`; - const waitReady = new Future(); - let pid: number | undefined; - runningWrangler.stdout.on("data", (chunk) => { - // console.log(">>", chunk.toString()) - const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; - if (mightPid) { - pid = +mightPid; - } - if (chunk.includes("Ready on http")) { - waitReady.resolve(true); - } - }); - runningWrangler.stderr.on("data", (chunk) => { - // eslint-disable-next-line no-console - console.error("!!", chunk.toString()); - }); - await waitReady.asPromise(); - const hs = { - start: async () => { - return hs; - }, - close: async () => { - if (pid) process.kill(pid); - }, - } as unknown as HonoServer; - return hs; - }, - }, -]) { +for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { describe(`${honoServer.name} - Connection`, () => { const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { @@ -250,7 +68,7 @@ for (const honoServer of [ let server: HonoServer; beforeAll(async () => { const app = new Hono(); - server = await (await honoServer.factory(style.remoteGestalt, port)).start(app, port); + server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).start(app, port); }); afterAll(async () => { await server.close(); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index 38ae24eb..de440457 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -48,7 +48,7 @@ export class HonoServer { this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); const rMsg = await exception2Result(() => c.req.json() as Promise); if (rMsg.isErr()) { - c.status(500); + c.status(400); return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rMsg.Err())); } return dispatcher.dispatch(this.impl, rMsg.Ok(), (msg) => c.json(msg)); @@ -57,7 +57,7 @@ export class HonoServer { this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); if (rReqOpen.isErr()) { - c.status(500); + c.status(400); return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rReqOpen.Err())); } const reqOpen = rReqOpen.Ok(); diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts new file mode 100644 index 00000000..bded0854 --- /dev/null +++ b/src/cloud/msg-processor.ts @@ -0,0 +1,259 @@ +import { exception2Result, Logger } from "@adviser/cement"; +import { + buildErrorMsg, + buildResDelMeta, + buildResGestalt, + buildResGetMeta, + buildResPutMeta, + defaultGestalt, + ErrorMsg, + getStoreFromType, + MsgBase, + MsgIsReqDelData, + MsgIsReqDelMeta, + MsgIsReqDelWAL, + MsgIsReqGestalt, + MsgIsReqGetData, + MsgIsReqGetMeta, + MsgIsReqGetWAL, + MsgIsReqPutData, + MsgIsReqPutMeta, + MsgIsReqPutWAL, + MsgIsReqSubscribeMeta, + ReqDelMeta, + ReqGetMeta, + ReqOptRes, + ReqPutMeta, + ReqRes, + ResDelMeta, + ResGetMeta, + ResPutMeta, +} from "./msg-types.js"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; +import { SuperThis } from "@fireproof/core"; + +export interface CtxBase { + readonly logger: Logger; +} + +export interface ReqOptResCtx extends ReqOptRes { + readonly ctx?: C; +} + +export interface ReqResCtx extends ReqRes { + readonly ctx: C; +} + +export interface MsgProcessor { + dispatch( + decodeFn: () => Promise + ): Promise, O>>; + + // signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise>; + // subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise>; + + // delMeta(req: ReqDelMeta, ctx: CtxBase): Promise>; + // putMeta(req: ReqPutMeta, ctx: CtxBase): Promise>; + // getMeta(req: ReqGetMeta, ctx: CtxBase): Promise>; +} + +export interface RequestOpts { + readonly waitFor: (msg: MsgBase) => boolean; + readonly timeout?: number; // ms +} +// export interface Connection { +// readonly ws: WebSocket; +// readonly key: ConnectionKey; +// request(msg: MsgBase, opts: RequestOpts): Promise>; +// onMessage(msgFn: (msg: MsgBase) => void): () => void; +// close(): Promise; +// } + +export abstract class MsgProcessorBase implements MsgProcessor { + readonly logger: Logger; + readonly serverId: string; + readonly ctx: O; + readonly sthis: SuperThis; + constructor(sthis: SuperThis, logger: Logger, ctx: O, serverId: string) { + this.serverId = serverId; + this.logger = logger; + this.ctx = ctx; + this.sthis = sthis; + } + + async dispatch( + decodeFn: () => Promise, + reqFn: (msg: Q, ctx: O) => Promise> = async (req) => ({ req }) + ): Promise> { + const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); + if (rReqMsg.isErr()) { + const errMsg = buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); + return { + req: errMsg as unknown as Q, + res: errMsg, + ctx: this.ctx, + }; + } + const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, this.ctx); + const ctx = { ...(optCtx || this.ctx) }; + switch (true) { + case MsgIsReqGestalt(req): + return { + req, + res: buildResGestalt(req, defaultGestalt(this.serverId, true)) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqGetData(req): + case MsgIsReqGetWAL(req): + return { + req, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "GET", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqPutData(req): + case MsgIsReqPutWAL(req): + if (req.payload) { + return { + req, + res: buildErrorMsg(this.logger, req, new Error("inband payload not implemented")) as S | ErrorMsg, + ctx, + }; + } + return { + req, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "PUT", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, + ctx, + }; + + case MsgIsReqDelData(req): + case MsgIsReqDelWAL(req): + return { + req, + res: (await this.signedUrl( + { + ...req, + params: { + ...req.params, + method: "DELETE", + store: getStoreFromType(req).store, + }, + }, + ctx + )) as S | ErrorMsg, + ctx, + }; + + // case MsgIsReqSignedUrl(req): + // return { + // req, + // res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, + // ctx, + // }; + case MsgIsReqSubscribeMeta(req): + return { + req, + res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqPutMeta(req): + return { + req, + res: (await this.putMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqGetMeta(req): + return { + req, + res: (await this.getMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + case MsgIsReqDelMeta(req): + return { + req, + res: (await this.delMeta(req, ctx)) as S | ErrorMsg, + ctx, + }; + } + return { + req: req, + res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, + ctx, + }; + } + + async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { + // delete meta does nothing in this implementation + // if you delete meta basically you are deleting the whole ledger + return buildResDelMeta(req, { + params: req.params, + status: "unsupported", + connId: ctx.group.connId, + }); + } + + async getMeta(req: ReqGetMeta, ctx: CF): Promise { + const rSignedUrl = await calculatePreSignedUrl( + { + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: { ...req.params, method: "GET" }, + }, + ctx.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + return buildResGetMeta(req, { + signedGetUrl: rSignedUrl.Ok().toString(), + status: "found", + metas: [], + connId: "", + }); + } + + async putMeta(req: ReqPutMeta, ctx: CtxHasGroup): Promise { + const rSignedUrl = await calculatePreSignedUrl( + { + tid: req.tid, + type: "reqSignedUrl", + version: req.version, + params: { ...req.params, method: "PUT" }, + }, + ctx.env + ); + if (rSignedUrl.isErr()) { + return buildErrorMsg(this.logger, req, rSignedUrl.Err()); + } + // roughly time ordered + return buildResPutMeta(req, { + // metaId should be a hash of metas. + metaId: new Date().getTime().toString(), + metas: req.metas, + signedPutUrl: rSignedUrl.Ok().toString(), + connId: ctx.group.connId, + }); + } +} diff --git a/src/cloud/msg-type-meta.ts b/src/cloud/msg-type-meta.ts index 682a8abd..df758111 100644 --- a/src/cloud/msg-type-meta.ts +++ b/src/cloud/msg-type-meta.ts @@ -20,7 +20,7 @@ export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { return req.type === "reqSubscribeMeta"; } -export function buildReqSubscriptMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { +export function buildReqSubscribeMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { return { tid: sthis.nextId().str, subscriberId, @@ -36,7 +36,7 @@ export interface ResSubscribeMeta extends MsgBase { readonly conn: Connection; } -export function buildResSubscriptMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { +export function buildResSubscribeMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { return { tid: req.tid, type: "resSubscribeMeta", diff --git a/src/cloud/msg-types-data.ts b/src/cloud/msg-types-data.ts index 25e083c7..bdf5389a 100644 --- a/src/cloud/msg-types-data.ts +++ b/src/cloud/msg-types-data.ts @@ -1,4 +1,4 @@ -import { VERSION, Logger, Result, URI } from "@adviser/cement"; +import { Logger, Result, URI } from "@adviser/cement"; import { SuperThis } from "@fireproof/core"; import { ReqSignedUrl, @@ -9,6 +9,7 @@ import { WithErrorMsg, buildRes, ReqSignedUrlParam, + buildReqSignedUrl, } from "./msg-types.js"; import { PreSignedMsg } from "./pre-signed-url.js"; @@ -17,14 +18,7 @@ export interface ReqGetData extends ReqSignedUrl { } export function buildReqGetData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetData { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqGetData", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqGetData", sup, conn); } export function MsgIsReqGetData(msg: MsgBase): msg is ReqGetData { @@ -63,14 +57,7 @@ export function MsgIsReqPutData(msg: MsgBase): msg is ReqPutData { } export function buildReqPutData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutData { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqPutData", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqPutData", sup, conn); } export interface ResPutData extends ResSignedUrl { @@ -99,14 +86,7 @@ export function MsgIsReqDelData(msg: MsgBase): msg is ReqDelData { } export function buildReqDelData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelData { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqDelData", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqDelData", sup, conn); } export interface ResDelData extends ResSignedUrl { diff --git a/src/cloud/msg-types-wal.ts b/src/cloud/msg-types-wal.ts index da21b6a3..a5f3123c 100644 --- a/src/cloud/msg-types-wal.ts +++ b/src/cloud/msg-types-wal.ts @@ -1,4 +1,4 @@ -import { VERSION, Logger } from "@adviser/cement"; +import { Logger } from "@adviser/cement"; import { SuperThis } from "@fireproof/core"; import { MsgBase, @@ -9,6 +9,7 @@ import { ReqSignedUrl, ResSignedUrl, ReqSignedUrlParam, + buildReqSignedUrl, } from "./msg-types.js"; import { CalculatePreSignedUrl } from "./msg-types-data.js"; @@ -21,14 +22,7 @@ export function MsgIsReqGetWAL(msg: MsgBase): msg is ReqGetWAL { } export function buildReqGetWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetWAL { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqGetWAL", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqGetWAL", sup, conn); } export interface ResGetWAL extends ResSignedUrl { @@ -59,14 +53,7 @@ export function MsgIsReqPutWAL(msg: MsgBase): msg is ReqPutWAL { } export function buildReqPutWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutWAL { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqPutWAL", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqPutWAL", sup, conn); } export interface ResPutWAL extends Omit { @@ -95,14 +82,7 @@ export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { } export function buildReqDelWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelWAL { - return { - params: sup, - conn, - tid: sthis.nextId().str, - type: "reqDelWAL", - // key: req.key, - version: VERSION, - }; + return buildReqSignedUrl(sthis, "reqDelWAL", sup, conn); } export interface ResDelWAL extends Omit { diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 34d00422..18195a60 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -1,4 +1,4 @@ -import { exception2Result, Future } from "@adviser/cement"; +import { Future } from "@adviser/cement"; import { Logger, SuperThis } from "@fireproof/core"; import { CalculatePreSignedUrl } from "./msg-types-data.js"; import { PreSignedMsg } from "./pre-signed-url.js"; @@ -49,6 +49,10 @@ export interface TenantLedger { readonly ledger: string; } +export function keyTenantLedger(t: TenantLedger): string { + return `${t.tenant}:${t.ledger}`; +} + export interface Connection { readonly key: TenantLedger; readonly reqId: string; @@ -167,7 +171,8 @@ export interface MsgerParams { readonly mime: string; readonly auth?: AuthType; readonly hasPersistent?: boolean; - readonly protocol: "http" | "ws"; + readonly protocolCapabilities?: ProtocolCapabilities[]; + // readonly protocol: "http" | "ws"; readonly timeout: number; // msec } @@ -178,9 +183,9 @@ export function defaultGestalt(msgP: MsgerParams, gestalt: GestaltParam): Gestal return { storeTypes: ["meta", "data", "wal"], httpEndpoints: ["/fp"], - wsEndpoints: msgP.protocol === "ws" ? ["/ws"] : [], + wsEndpoints: ["/ws"], encodings: ["JSON"], - protocolCapabilities: msgP.protocol === "ws" ? ["stream"] : ["reqRes"], + protocolCapabilities: msgP.protocolCapabilities || ["reqRes", "stream"], auth: [], requiresAuth: false, data: msgP.hasPersistent @@ -282,10 +287,15 @@ export function MsgIsResGestalt(msg: MsgBase): msg is ResGestalt { return msg.type === "resGestalt"; } -export type ReqOpenConnection = Omit & { readonly reqId?: string }; +export interface ReqOpenConnection { + readonly key: TenantLedger; + readonly reqId?: string; + readonly resId?: string; +} -export interface ReqOpen extends MsgBase { +export interface ReqOpen extends Omit { readonly type: "reqOpen"; + readonly conn: Connection; } export function buildReqOpen(sthis: NextId, conn: ReqOpenConnection): ReqOpen { @@ -301,7 +311,7 @@ export function buildReqOpen(sthis: NextId, conn: ReqOpenConnection): ReqOpen { } export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { - return msg.type === "reqOpen"; + return msg.type === "reqOpen" && !!msg.conn && !!msg.conn.reqId; } export interface ResOpen extends MsgBase { @@ -444,6 +454,21 @@ export interface ReqSignedUrl extends MsgBase { readonly params: ReqSignedUrlParam; } +export function buildReqSignedUrl( + sthis: NextId, + type: string, + params: ReqSignedUrlParam, + conn: Connection +): T { + return { + tid: sthis.nextId().str, + type, + version: VERSION, + conn, + params, + } as T; +} + export interface ResSignedUrl extends MsgBase { // readonly type: "resSignedUrl"; readonly conn: Connection; diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 12c03beb..54fc0884 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -70,8 +70,8 @@ export function defaultMsgParams(sthis: SuperThis, igs: Partial): M return { ende: jsonEnDe(sthis), mime: "application/json", - protocol: "http", timeout: 3000, + protocolCapabilities: ["reqRes", "stream"], ...igs, } satisfies MsgerParams; } @@ -139,12 +139,12 @@ export class Msger { sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, - imsgP: MsgerParams + imsgP: Partial = {} ): Promise> { // initial exchange with JSON encoding const jsGI = defaultMsgParams(sthis, { ...imsgP, ende: jsonEnDe(sthis) }); const url = URI.from(curl); - const gs = defaultGestalt(imsgP, { id: "FP-Universal-Client" }); + const gs = defaultGestalt(defaultMsgParams(sthis, imsgP), { id: "FP-Universal-Client" }); /* * request Gestalt with Http */ diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts new file mode 100644 index 00000000..1e162fdf --- /dev/null +++ b/src/cloud/test-helper.ts @@ -0,0 +1,190 @@ +import { Future, URI } from "@adviser/cement"; +import { SuperThis } from "@fireproof/core"; +import { $, fs } from "zx"; +import { HttpConnection } from "./http-connection.js"; +import { MsgerParams, ReqOpen, Gestalt, defaultGestalt } from "./msg-types.js"; +import { defaultMsgParams, applyStart, Msger } from "./msger.js"; +import { WSConnection } from "./ws-connection.js"; +import * as toml from "smol-toml"; +import { Env } from "./backend/env.js"; +import { HonoServer } from "./hono-server.js"; +import { NodeHonoServer } from "./node-hono-server.js"; + +export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["reqRes"] }), { + id: "HTTP-server", + }); + const exGt = { my, remote }; + return { + name: "HTTP", + remoteGestalt: remote, + cInstance: HttpConnection, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/fp`), + open: () => + applyStart( + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://localhost:${port}/fp`)], + { + ...msgP, + // protocol: "http", + timeout: 1000, + }, + exGt + ) + ), + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), + open: () => + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://localhost:${port - 1}/fp`)], + { + ...msgP, + // protocol: "http", + timeout: 1000, + }, + exGt + ), + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port}/fp`), + open: () => + Msger.openHttp( + sthis, + qOpen, + [URI.from(`http://4.7.1.1:${port}/fp`)], + { + ...msgP, + // protocol: "http", + timeout: 500, + }, + exGt + ), + }, + }; +} + +export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { + const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["stream"] }), { + id: "WS-server", + }); + const exGt = { my, remote }; + return { + name: "WS", + remoteGestalt: remote, + cInstance: WSConnection, + ok: { + url: () => URI.from(`http://127.0.0.1:${port}/ws`), + open: () => + applyStart( + Msger.openWS( + sthis, + qOpen, + URI.from(`http://localhost:${port}/ws`), + { + ...msgP, + // protocol: "ws", + timeout: 1000, + }, + exGt + ) + ), + }, + connRefused: { + url: () => URI.from(`http://127.0.0.1:${port - 1}/ws`), + open: () => + Msger.openWS( + sthis, + qOpen, + URI.from(`http://localhost:${port - 1}/ws`), + { + ...msgP, + // protocol: "ws", + timeout: 1000, + }, + exGt + ), + }, + timeout: { + url: () => URI.from(`http://4.7.1.1:${port - 1}/ws`), + open: () => + Msger.openWS( + sthis, + qOpen, + URI.from(`http://4.7.1.1:${port - 1}/ws`), + { + ...msgP, + // protocol: "ws", + timeout: 500, + }, + exGt + ), + }, + }; +} + +export async function resolveToml() { + const tomlFile = "src/cloud/backend/wrangler.toml"; + const tomeStr = await fs.readFile(tomlFile, "utf-8"); + const wranglerFile = toml.parse(tomeStr) as unknown as { + env: { "test-reqRes": { vars: Env } }; + }; + return { + tomlFile, + env: wranglerFile.env["test-reqRes"].vars, + }; +} + +export function NodeHonoServerFactory() { + return { + name: "NodeHonoServer", + factory: async (sthis: SuperThis, msgP: MsgerParams, remoteGestalt: Gestalt, _port: number) => { + return new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer((await resolveToml()).env)); + }, + }; +} +export function CFHonoServerFactory() { + return { + name: "CFHonoServer", + factory: async (_sthis: SuperThis, _msgP: MsgerParams, remoteGestalt: Gestalt, port: number) => { + const { tomlFile } = await resolveToml(); + $.verbose = !!process.env.FP_DEBUG; + const runningWrangler = $` + wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]} --no-show-interactive-dev-session & + waitPid=$! + echo "PID:$waitPid" + wait $waitPid`; + const waitReady = new Future(); + let pid: number | undefined; + runningWrangler.stdout.on("data", (chunk) => { + // console.log(">>", chunk.toString()) + const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; + if (mightPid) { + pid = +mightPid; + } + if (chunk.includes("Ready on http")) { + waitReady.resolve(true); + } + }); + runningWrangler.stderr.on("data", (chunk) => { + // eslint-disable-next-line no-console + console.error("!!", chunk.toString()); + }); + await waitReady.asPromise(); + const hs = { + start: async () => { + return hs; + }, + close: async () => { + if (pid) process.kill(pid); + }, + } as unknown as HonoServer; + return hs; + }, + }; +} diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index fddf72bd..36b1b616 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -56,11 +56,9 @@ export class WSConnection implements MsgConnection { const timer = setTimeout(() => { const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError(); this.toMsg(buildErrorMsg(this.sthis, this.logger, {} as MsgBase, err)); - console.log("WSConnection.start-timer"); onOpenFuture.resolve(Result.Err(err)); }, this.msgP.timeout); this.wqs.ws.onopen = () => { - console.log("WSConnection.onopen"); onOpenFuture.resolve(Result.Ok(undefined)); this.opened = true; }; @@ -108,7 +106,6 @@ export class WSConnection implements MsgConnection { return rOpen; } const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }); - console.log("WSConnection.start-4"); if (!MsgIsResOpen(resOpen)) { return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); } From c850fae2d25d511d83db8925bad24002ae41d811 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Wed, 25 Dec 2024 22:20:35 +0100 Subject: [PATCH 37/83] chore: added data/wal store tests --- src/cloud/client/cloud-gateway.test.ts | 129 ++++++ src/cloud/client/gateway.ts | 35 +- src/cloud/cloud.test.ts | 537 ------------------------- src/cloud/cloud.test.ts-off | 533 ++++++++++++++++++++++++ src/cloud/hono-server.ts | 3 +- src/cloud/node-hono-server.ts | 5 +- tests/start-s3.sh | 4 +- vitest.cloud.config.ts | 2 +- 8 files changed, 695 insertions(+), 553 deletions(-) create mode 100644 src/cloud/client/cloud-gateway.test.ts delete mode 100644 src/cloud/cloud.test.ts create mode 100644 src/cloud/cloud.test.ts-off diff --git a/src/cloud/client/cloud-gateway.test.ts b/src/cloud/client/cloud-gateway.test.ts new file mode 100644 index 00000000..8567450a --- /dev/null +++ b/src/cloud/client/cloud-gateway.test.ts @@ -0,0 +1,129 @@ +import { Hono } from "hono"; +import { HonoServer } from "../hono-server.js"; +import { buildReqOpen, defaultGestalt } from "../msg-types.js"; +import { NodeHonoServerFactory, CFHonoServerFactory, wsStyle } from "../test-helper.js"; +import { bs, ensureSuperThis, NotFoundError } from "@fireproof/core"; +import { defaultMsgParams } from "../msger.js"; +import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./gateway.js"; +import { BuildURI } from "@adviser/cement"; + +const sthis = ensureSuperThis(); +const msgP = defaultMsgParams(sthis, { hasPersistent: true }); +const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); +for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { + const qOpen = buildReqOpen(sthis, { + key: { + ledger: "test", + tenant: "test", + }, + }); + const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); + const style = wsStyle(sthis, port, msgP, qOpen, my); + describe(`${honoServer.name} - Gateway`, () => { + let server: HonoServer; + let gw: bs.Gateway; + let unregister: () => void; + let url: BuildURI; + beforeAll(async () => { + const app = new Hono(); + server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).start(app, port); + unregister = registerFireproofCloudStoreProtocol("fireproof:"); + gw = new FireproofCloudGateway(sthis); + url = BuildURI.from(`fireproof://localhost:${port}/`) + .setParam("protocol", "http") + .setParam("name", "ledger-name") + .setParam("tenant", "tendant"); + }); + afterAll(async () => { + await server.close(); + unregister(); + }); + describe("data", () => { + it("get not found", async () => { + await Promise.all( + Array(20) + .fill(async () => { + url.setParam("store", "data"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); + }); + + it("put - get - del - get", async () => { + await Promise.all( + Array(20) + .fill(async () => { + const resStart = await gw.start(url.URI()); + expect(resStart.isOk()).toBeTruthy(); + + url.setParam("store", "data"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + + const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); + expect(resPut.isOk()).toBeTruthy(); + const resGet = await gw.get(kurl); + expect(resGet.isOk()).toBeTruthy(); + expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); + const resDel = await gw.delete(kurl); + expect(resDel.isOk()).toBeTruthy(); + + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); + }); + }); + + describe("WAL", () => { + it("get not found", async () => { + await Promise.all( + Array(20) + .fill(async () => { + url.setParam("store", "wal"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); + }); + + it("put - get - del - get", async () => { + await Promise.all( + Array(20) + .fill(async () => { + const resStart = await gw.start(url.URI()); + expect(resStart.isOk()).toBeTruthy(); + + url.setParam("store", "wal"); + const key = `theWALKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + + const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); + expect(resPut.isOk()).toBeTruthy(); + const resGet = await gw.get(kurl); + expect(resGet.isOk()).toBeTruthy(); + expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); + const resDel = await gw.delete(kurl); + expect(resDel.isOk()).toBeTruthy(); + + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); + }); + }); + }); +} diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index 1709c6fb..ad80affc 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -439,29 +439,42 @@ export class FireproofCloudGateway implements bs.Gateway { // fireproof://localhost:1999/?name=test-public-api&protocol=ws&store=meta async getCloudConnection(uri: URI): Promise> { const rParams = uri.getParamsResult({ - name: 0, + name: key.REQUIRED, protocol: "https", - store: 0, - storekey: 0, + store: key.REQUIRED, + storekey: key.OPTIONAL, + tenant: key.OPTIONAL, }); if (rParams.isErr()) { return this.logger.Error().Url(uri).Err(rParams).Msg("getCloudConnection:err").ResultError(); } const params = rParams.Ok(); - const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); - const kb = await rt.kb.getKeyBag(this.sthis); - const rfingerprint = await kb.getNamedKey(dataKey); - if (rfingerprint.isErr()) { - return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); + let tenant: string; + if (params.tenant) { + tenant = params.tenant; + } else { + if (!params.storekey) { + return this.logger.Error().Url(uri).Msg("no tendant or storekey given").ResultError(); + } + const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); + const kb = await rt.kb.getKeyBag(this.sthis); + const rfingerprint = await kb.getNamedKey(dataKey); + if (rfingerprint.isErr()) { + return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); + } + tenant = rfingerprint.Ok().fingerPrint; } const qOpen = buildReqOpen(this.sthis, { key: { - tenant: uri.build().getParam("tenant", rfingerprint.Ok().fingerPrint) as string, + tenant: tenant, ledger: params.name, - // protocol: params.protocol as ConnectionKey["protocol"], } satisfies TenantLedger, }); - return keyedConnections.get(keyTenantLedger(qOpen.conn.key)).once(async () => Msger.open(this.sthis, uri, qOpen)); + let cUrl = uri.build().protocol(params.protocol).cleanParams().URI(); + if (cUrl.pathname === "/") { + cUrl = cUrl.build().pathname("/fp").URI(); + } + return keyedConnections.get(keyTenantLedger(qOpen.conn.key)).once(async () => Msger.open(this.sthis, cUrl, qOpen)); } // private notifySubscribers(data: Uint8Array, callbacks: ((msg: Uint8Array) => void)[] = []): void { diff --git a/src/cloud/cloud.test.ts b/src/cloud/cloud.test.ts deleted file mode 100644 index 90eda9c0..00000000 --- a/src/cloud/cloud.test.ts +++ /dev/null @@ -1,537 +0,0 @@ -// import { env } from "cloudflare:test" -import { BuildURI, Future, URI } from "@adviser/cement"; -import { ReqSignedUrl, ResSignedUrl } from "./msg-types.js"; -import { Env } from "./backend/env.js"; -import { $ } from "zx"; -import fs from "fs/promises"; -import * as toml from "smol-toml"; -import { bs, CRDTEntry, Database, ensureSuperThis, fireproof, isNotFoundError, rt } from "@fireproof/core"; -import { AwsClient } from "aws4fetch"; -import { smokeDB } from "../../tests/helper.js"; -// import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.ts-off"; -import { calculatePreSignedUrl } from "./pre-signed-url.js"; -import { newWebSocket } from "./new-websocket.js"; - -function testReqSignedUrl(tid = "test") { - return { - tid: tid, - type: "reqSignedUrl", - params: { - // protocol: "ws", - path: "/hallo", - ledgerName: "test-name", - method: "GET", - tenantId: "tenantId", - store: "wal", - key: "main", - }, - version: "test", - } satisfies ReqSignedUrl; -} - -async function testResSignedUrl(env: Env, tid?: string, amzDate?: string): Promise { - const req = testReqSignedUrl(tid); - const rSignedUrl = await calculatePreSignedUrl(req, env, amzDate); - if (rSignedUrl.isErr()) { - throw rSignedUrl.Err(); - } - return { - params: req.params, - signedUrl: rSignedUrl.Ok().toString(), - // `http://localhost:8080/tenantId/test-name/wal/main.json?tid=${tid}&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=accessKeyId%2F20241121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20241121T225359Z&X-Amz-Expires=86400&X-Amz-Signature=f52d5ecfbb6be93210dd57cb49ba1e426a8aee24a0738aedb636ae5722fcdded&X-Amz-SignedHeaders=host`, - tid: tid || "test", - type: "resSignedUrl", - version: env.VERSION, - } satisfies ResSignedUrl; -} - -describe("CloudBackendTest", () => { - const sthis = ensureSuperThis(); - let env: Env; - let pid: number; - const port = +(process.env.FP_WRANGLER_PORT || 0) || ~~(1024 + Math.random() * (0x10000 - 1024)); - const wrangler = BuildURI.from("http://localhost") - .port("" + port) - .URI(); - async function cfFetch(relative: string, init: RequestInit) { - return fetch(wrangler.build().appendRelative(relative).asURL(), init); - } - beforeAll(async () => { - const tomlFile = "src/cloud/backend/wrangler.toml"; - const tomeStr = await fs.readFile(tomlFile, "utf-8"); - const wranglerFile = toml.parse(tomeStr) as unknown as { - env: { test: { vars: Env } }; - }; - env = wranglerFile.env.test.vars; - if (process.env.FP_WRANGLER_PORT) { - return; - } - $.verbose = !!process.env.FP_DEBUG; - const runningWrangler = $` - wrangler dev -c ${tomlFile} --port ${port} --env test --no-show-interactive-dev-session & - waitPid=$! - echo "PID:$waitPid" - wait $waitPid`; - const waitReady = new Future(); - runningWrangler.stdout.on("data", (chunk) => { - // console.log(">>", chunk.toString()) - const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; - if (mightPid) { - pid = +mightPid; - } - if (chunk.includes("Ready on http")) { - waitReady.resolve(true); - } - }); - runningWrangler.stderr.on("data", (chunk) => { - // eslint-disable-next-line no-console - console.error("!!", chunk.toString()); - }); - await waitReady.asPromise(); - // await f.asPromise() - // wrangler dev -c src/cloud/backend/wrangler.toml --port 4711 --env test - }); - - afterAll(async () => { - // console.log("kill", runningWrangler.pid, runningWrangler) - // process.kill(runningWrangler.pid) - // process.stdin.write(Array(4).fill("x\n\r").join("")) - if (pid) process.kill(pid); - }); - - describe("raw tests", () => { - it("return 404", async () => { - const res = await cfFetch("/posts", {}); - expect(res.status).toBe(404); - expect(await res.json()).toEqual({ - message: "Notfound:/posts", - tid: "internal", - type: "error", - version: env.VERSION, - }); - }); - it("return 422 invalid json", async () => { - const res = await cfFetch("/fp", { method: "PUT" }); - expect(res.status).toBe(422); - expect(await res.json()).toEqual({ - message: "Unexpected end of JSON input", - tid: "internal", - type: "error", - version: env.VERSION, - }); - }); - - it("return 422 illegal msg", async () => { - const res = await cfFetch("/fp", { - method: "PUT", - body: JSON.stringify({ - bucket: "test", - key: "test", - }), - }); - expect(res.status).toBe(422); - expect(await res.json()).toEqual({ - message: "unknown msg.type=undefined", - tid: "internal", - type: "error", - version: env.VERSION, - }); - }); - - it("return 200 msg", async () => { - const res = await cfFetch("/fp", { - method: "PUT", - body: JSON.stringify(testReqSignedUrl()), - }); - expect(res.status).toBe(200); - expect(await res.json()).toEqual(await testResSignedUrl(env)); - }); - - // it("reqOpen without websocket", async () => { - // const conn = await msgOpen(cfURL, { } - // }); - - // it("reqOpen with websocket", async () => { - // }); - - it("use websockets SignedUrl", async () => { - await Promise.all( - Array(100) - .fill(null) - .map(async () => { - const url = wrangler.build().appendRelative("/ws").protocol("ws:"); - const so = await newWebSocket(url); - const done = new Future(); - let total = 10; - let tid = `${total}-test-${Math.random()}`; - so.onopen = () => { - so.send(JSON.stringify(testReqSignedUrl(tid))); - }; - so.onmessage = async (msg) => { - try { - const res = JSON.parse(msg.data.toString()) as ResSignedUrl; - expect(res).toEqual(await testResSignedUrl(env, tid, URI.from(res.signedUrl).getParam("X-Amz-Date"))); - if (--total === 0) { - done.resolve(true); - } else { - tid = `${total}-test-${Math.random()}`; - so.send(JSON.stringify(testReqSignedUrl(tid))); - } - } catch (err) { - done.reject(err); - } - }; - so.onerror = (ev) => { - assert.fail(`WebSocket error: ${ev}`); - }; - return done.asPromise().then(() => so.close(1000, "done")); - }) - ); - }); - }); - - describe("FireproofCloudGateway", () => { - let db: Database; - let unregister: () => void; - interface ExtendedGateway extends bs.Gateway { - headerSize: number; - subscribe?: (url: URI, callback: (meta: Uint8Array) => void) => Promise; // Changed VoidResult to UnsubscribeResult - } - - // has to leave - interface ExtendedStore { - gateway: ExtendedGateway; - _url: URI; - name: string; - } - - beforeAll(() => { - unregister = registerFireproofCloudStoreProtocol("fireproof:"); - }); - - beforeEach(() => { - const config = { - store: { - stores: { - base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), - // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", - }, - }, - }; - const name = "fireproof-cloud-test-db-" + sthis.nextId().str; - db = fireproof(name, config); - }); - - afterEach(async () => { - // Clear the database before each test - if (db) { - await db.close(); - await db.destroy(); - } - }); - - afterAll(() => { - unregister(); - }); - - // it("env setup is ok", () => { - // // expect(process.env.FP_STORAGE_URL).toMatch(/fireproof:\/\/localhost:1999/); - // }); - - it("should have loader and options", () => { - const loader = db.blockstore.loader; - expect(loader).toBeDefined(); - if (!loader) { - throw new Error("Loader is not defined"); - } - expect(loader.ebOpts).toBeDefined(); - expect(loader.ebOpts.store).toBeDefined(); - expect(loader.ebOpts.store.stores).toBeDefined(); - if (!loader.ebOpts.store.stores) { - throw new Error("Loader stores is not defined"); - } - if (!loader.ebOpts.store.stores.base) { - throw new Error("Loader stores.base is not defined"); - } - - const baseUrl = URI.from(loader.ebOpts.store.stores.base); - expect(baseUrl.protocol).toBe("fireproof:"); - // expect(baseUrl.hostname).toBe("localhost"); - // expect(baseUrl.port || "").toBe("1999"); - }); - - it("should initialize and perform basic operations", async () => { - const docs = await smokeDB(db); - - // // get a new db instance - // db = new Database(name, config); - - // Test update operation - const updateDoc = await db.get<{ content: string }>(docs[0]._id); - updateDoc.content = "Updated content"; - const updateResult = await db.put(updateDoc); - expect(updateResult.id).toBe(updateDoc._id); - - const updatedDoc = await db.get<{ content: string }>(updateDoc._id); - expect(updatedDoc.content).toBe("Updated content"); - - // Test delete operation - await db.del(updateDoc._id); - try { - await db.get(updateDoc._id); - throw new Error("Document should have been deleted"); - } catch (e) { - const error = e as Error; - expect(error.message).toContain("Not found"); - } - }); - - it("should subscribe to changes", async () => { - // Extract stores from the loader - const metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore; - - const metaGateway = metaStore?.gateway; - - const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main"); - await metaGateway?.start(metaStore?._url); - - let didCall = false; - - expect(metaGateway.subscribe).toBeTypeOf("function"); - if (metaGateway.subscribe) { - const future = new Future(); - - const metaSubscribeResult = await metaGateway.subscribe(metaUrl?.Ok(), (data: Uint8Array) => { - // console.log("data", data); - const decodedData = sthis.txt.decode(data); - expect(decodedData).toContain("parents"); - didCall = true; - future.resolve(); - }); - expect(metaSubscribeResult.isOk()).toBeTruthy(); - const ok = await db.put({ _id: "key1", hello: "world1" }); - expect(ok).toBeTruthy(); - expect(ok.id).toBe("key1"); - await future.asPromise(); - expect(didCall).toBeTruthy(); - metaSubscribeResult.Ok()(); - } - }); - }); - describe("AwsClient R2", () => { - it("make presigned url", async () => { - const sthis = ensureSuperThis(); - const a4f = new AwsClient({ - accessKeyId: sthis.env.get("CF_ACCESS_KEY_ID") || "accessKeyId", - secretAccessKey: sthis.env.get("CF_SECRET_ACCESS_KEY") || "secretAccessKey", - region: "us-east-1", - service: "s3", - }); - const buildUrl = BuildURI.from(sthis.env.get("CF_STORAGE_URL") || "https://bucket.example.com/db/main") - .appendRelative("db/main") - .setParam("X-Amz-Expires", "22"); - const signedUrl = await a4f - .sign(new Request(buildUrl.toString(), { method: "PUT" }), { - aws: { - signQuery: true, - datetime: "2021-09-01T12:34:56Z", - }, - }) - .then((res) => res.url); - expect(URI.from(signedUrl).asObj()).toEqual( - buildUrl - .setParam("X-Amz-Date", "2021-09-01T12:34:56Z") - .setParam("X-Amz-Algorithm", "AWS4-HMAC-SHA256") - .setParam("X-Amz-Credential", `${a4f.accessKeyId}/2021-09-/${a4f.region}/${a4f.service}/aws4_request`) - .setParam("X-Amz-SignedHeaders", "host") - .setParam( - "X-Amz-Signature", - sthis.env.get("CF_PRESIGNED_SIGNATURE") || - "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" - ) - .asObj() - ); - }); - }); - - describe(`store=meta`, () => { - const store = "meta"; - let gw: bs.Gateway; - const sthis = ensureSuperThis(); - let uri: URI; - beforeAll(async () => { - gw = new FireproofCloudGateway(sthis); - const id = sthis.nextId().str; - uri = BuildURI.from("fireproof://localhost") - .port("" + port) - .setParam("store", store) - .setParam("name", id) - .setParam("protocol", "ws") - .setParam("storekey", id) - .setParam("testMode", "true") - .URI(); - - const last: Uint8Array[] = []; - const cnt = 4; - Array(cnt) - .fill(null) - .map(async () => { - const rOk = (await gw.subscribe?.(uri, (meta: Uint8Array) => { - last.push(meta); - if (last.length === cnt) { - expect(last[0]).toEqual(last[1]); - expect(last[1]).toEqual(last[2]); - expect(last[2]).toEqual(last[3]); - last.length = 0; - } - })) as bs.VoidResult; - expect(rOk.isOk()).toBeTruthy(); - }); - - const keyBag = await rt.kb.getKeyBag(sthis); - await keyBag.getNamedKey(`@${id}:data@`); - }); - - afterAll(async () => { - const rOk = await gw.close(uri); - expect(rOk.isOk()).toBeTruthy(); - }); - - const subscribeCallbacks: { - connId: string; - uri: URI; - cb: ReturnType void>>; - unsub: bs.UnsubscribeResult; - }[] = []; - beforeEach(async () => { - await Promise.all( - Array(1) - .fill(null) - .map(async () => { - const cb = vitest.fn(); - const connId = sthis.nextId().str; - const uriConnId = uri.build().setParam("connId", connId).URI(); - const unsub = (await gw.subscribe?.(uriConnId, (meta: Uint8Array) => - cb(sthis.txt.decode(meta), connId) - )) as bs.UnsubscribeResult; - subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }); - }) - ); - }); - afterEach(() => { - subscribeCallbacks.forEach(({ unsub }) => unsub.Ok()()); - subscribeCallbacks.length = 0; - }); - - function crdtEntry(connId = "default"): Uint8Array { - return sthis.txt.encode( - JSON.stringify([ - { - cid: `${connId}:bafyreidjlylxmmb3yuz7levzzbso3g7ql54zovxl3mkhbbqxmmfnfbkoym`, - data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWdvdHM3dmFzeHhhdmdoY3FjeHo3ZXJibTdtY21ramQybTV0bXpzcGdhbG91d2lpcjYzZnkifV19Z3BhcmVudHOA", - parents: [], - }, - { - cid: `${connId}:bafyreie7izpgpmxd6heoiweoyblgyzoxt74xrp5wcpqo66bmjv2plgmceq`, - data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWQyZ2l1c2t2YWJoZTZ5ZHdsdXo0aGx4Z3lyNTZ5dmZmbjVpdndqdmhlYXl3cWJ4bHFmeGEifV19Z3BhcmVudHOA", - parents: [], - }, - ] satisfies CRDTEntry[]) - ); - } - - it(`buildUrl`, async () => { - const rOk = await gw.buildUrl(uri, "KEY"); - const url = rOk.Ok(); - expect(url.getParam("store")).toBe(store); - expect(url.getParam("key")).toBe("KEY"); - }); - it(`start`, async () => { - const rOk = await gw.start(uri); - const url = rOk.Ok(); - expect(url.getParam("store")).toBe(store); - expect(url.getParam("version")).toBeTruthy(); - }); - - it(`unsubscribe`, async () => { - subscribeCallbacks.forEach((sub) => sub.unsub.Ok()()); - const rOk = await gw.put(uri.build().setParam("key", "main").URI(), crdtEntry()); - // console.log(rOk); - expect(rOk.isOk()).toBeTruthy(); - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); - }); - - it(`get-put-delete`, async () => { - async function getNotFound() { - for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { - for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.get(u.build().setParam("key", key).URI()); - expect(rOk.isErr()).toBeTruthy(); - expect(isNotFoundError(rOk.Err())).toBeTruthy(); - } - } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); - } - console.log("getNotFound-pre"); - - subscribeCallbacks.forEach(({ cb }) => { - expect(cb).toHaveBeenCalledTimes(0); - }); - // get not found - await getNotFound(); - // put - async function put() { - for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { - for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.put( - u.build().setParam("key", key).URI(), - crdtEntry(`${key}:${u.getParam("connId", "default")}`) - ); - expect(rOk.isOk()).toBeTruthy(); - } - } - // console.log('put', subscribeCallbacks.map(({ cb }) => cb.mock.calls)); - subscribeCallbacks.forEach(({ cb, connId }) => { - // expect(cb).toHaveBeenCalledTimes(subscribeCallbacks.length * 2); - for (const key of ["KEY1", "KEY2"]) { - expect(cb).toHaveBeenCalledWith(sthis.txt.decode(crdtEntry(`${key}:${connId}`)), connId); - } - }); - } - // console.log('put-pre') - await put(); - subscribeCallbacks.forEach(({ cb }) => cb.mockClear()); - - async function get() { - for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { - for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.get(u.build().setParam("key", key).URI()); - const data = JSON.parse(sthis.txt.decode(rOk.Ok())) as CRDTEntry[]; - expect(data).toEqual(subscribeCallbacks.map(({ connId }) => crdtEntry(connId))); - } - } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); - } - console.log("get-pre"); - await get(); - async function del() { - for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { - for (const key of ["KEY1", "KEY2"]) { - const rOk = await gw.delete(u.build().setParam("key", key).URI()); - expect(rOk.isOk()).toBeTruthy(); - } - } - subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); - } - console.log("del-pre"); - await del(); - // get not found - console.log("getNotFound-pre"); - await getNotFound(); - }); - it(`close`, async () => { - const rOk = await gw.close(uri); - expect(rOk.isOk()).toBeTruthy(); - }); - }); -}); diff --git a/src/cloud/cloud.test.ts-off b/src/cloud/cloud.test.ts-off new file mode 100644 index 00000000..a0811ec5 --- /dev/null +++ b/src/cloud/cloud.test.ts-off @@ -0,0 +1,533 @@ +// import { env } from "cloudflare:test" +import { BuildURI, Future, URI } from "@adviser/cement"; +import { ReqSignedUrl, ResSignedUrl } from "./msg-types.js"; +import { Env } from "./backend/env.js"; +import { $ } from "zx"; +import fs from "fs/promises"; +import * as toml from "smol-toml"; +import { bs, CRDTEntry, Database, ensureSuperThis, fireproof, isNotFoundError, rt } from "@fireproof/core"; +import { AwsClient } from "aws4fetch"; +import { smokeDB } from "../../tests/helper.js"; +// import { FireproofCloudGateway, registerFireproofCloudStoreProtocol } from "./client/gateway.ts-off"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; +import { newWebSocket } from "./new-websocket.js"; +import { registerFireproofCloudStoreProtocol } from "./client/gateway.js"; + +// function testReqSignedUrl(tid = "test") { +// return { +// tid: tid, +// type: "reqSignedUrl", +// params: { +// // protocol: "ws", +// path: "/hallo", +// store: "wal", +// key: "main", +// }, +// version: "test", +// } satisfies ReqSignedUrl; +// } + +// async function testResSignedUrl(env: Env, tid?: string, amzDate?: string): Promise { +// const req = testReqSignedUrl(tid); +// const rSignedUrl = await calculatePreSignedUrl(req, env, amzDate); +// if (rSignedUrl.isErr()) { +// throw rSignedUrl.Err(); +// } +// return { +// params: req.params, +// signedUrl: rSignedUrl.Ok().toString(), +// // `http://localhost:8080/tenantId/test-name/wal/main.json?tid=${tid}&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=accessKeyId%2F20241121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20241121T225359Z&X-Amz-Expires=86400&X-Amz-Signature=f52d5ecfbb6be93210dd57cb49ba1e426a8aee24a0738aedb636ae5722fcdded&X-Amz-SignedHeaders=host`, +// tid: tid || "test", +// type: "resSignedUrl", +// version: env.VERSION, +// } satisfies ResSignedUrl; +// } + +// describe("CloudBackendTest", () => { +// const sthis = ensureSuperThis(); +// let env: Env; +// let pid: number; +// const port = +(process.env.FP_WRANGLER_PORT || 0) || ~~(1024 + Math.random() * (0x10000 - 1024)); +// const wrangler = BuildURI.from("http://localhost") +// .port("" + port) +// .URI(); +// async function cfFetch(relative: string, init: RequestInit) { +// return fetch(wrangler.build().appendRelative(relative).asURL(), init); +// } +// beforeAll(async () => { +// const tomlFile = "src/cloud/backend/wrangler.toml"; +// const tomeStr = await fs.readFile(tomlFile, "utf-8"); +// const wranglerFile = toml.parse(tomeStr) as unknown as { +// env: { test: { vars: Env } }; +// }; +// env = wranglerFile.env.test.vars; +// if (process.env.FP_WRANGLER_PORT) { +// return; +// } +// $.verbose = !!process.env.FP_DEBUG; +// const runningWrangler = $` +// wrangler dev -c ${tomlFile} --port ${port} --env test --no-show-interactive-dev-session & +// waitPid=$! +// echo "PID:$waitPid" +// wait $waitPid`; +// const waitReady = new Future(); +// runningWrangler.stdout.on("data", (chunk) => { +// // console.log(">>", chunk.toString()) +// const mightPid = chunk.toString().match(/PID:(\d+)/)?.[1]; +// if (mightPid) { +// pid = +mightPid; +// } +// if (chunk.includes("Ready on http")) { +// waitReady.resolve(true); +// } +// }); +// runningWrangler.stderr.on("data", (chunk) => { +// // eslint-disable-next-line no-console +// console.error("!!", chunk.toString()); +// }); +// await waitReady.asPromise(); +// // await f.asPromise() +// // wrangler dev -c src/cloud/backend/wrangler.toml --port 4711 --env test +// }); + +// afterAll(async () => { +// // console.log("kill", runningWrangler.pid, runningWrangler) +// // process.kill(runningWrangler.pid) +// // process.stdin.write(Array(4).fill("x\n\r").join("")) +// if (pid) process.kill(pid); +// }); + +// describe("raw tests", () => { +// it("return 404", async () => { +// const res = await cfFetch("/posts", {}); +// expect(res.status).toBe(404); +// expect(await res.json()).toEqual({ +// message: "Notfound:/posts", +// tid: "internal", +// type: "error", +// version: env.VERSION, +// }); +// }); +// it("return 422 invalid json", async () => { +// const res = await cfFetch("/fp", { method: "PUT" }); +// expect(res.status).toBe(422); +// expect(await res.json()).toEqual({ +// message: "Unexpected end of JSON input", +// tid: "internal", +// type: "error", +// version: env.VERSION, +// }); +// }); + +// it("return 422 illegal msg", async () => { +// const res = await cfFetch("/fp", { +// method: "PUT", +// body: JSON.stringify({ +// bucket: "test", +// key: "test", +// }), +// }); +// expect(res.status).toBe(422); +// expect(await res.json()).toEqual({ +// message: "unknown msg.type=undefined", +// tid: "internal", +// type: "error", +// version: env.VERSION, +// }); +// }); + +// it("return 200 msg", async () => { +// const res = await cfFetch("/fp", { +// method: "PUT", +// body: JSON.stringify(testReqSignedUrl()), +// }); +// expect(res.status).toBe(200); +// expect(await res.json()).toEqual(await testResSignedUrl(env)); +// }); + +// // it("reqOpen without websocket", async () => { +// // const conn = await msgOpen(cfURL, { } +// // }); + +// // it("reqOpen with websocket", async () => { +// // }); + +// it("use websockets SignedUrl", async () => { +// await Promise.all( +// Array(100) +// .fill(null) +// .map(async () => { +// const url = wrangler.build().appendRelative("/ws").protocol("ws:"); +// const so = await newWebSocket(url); +// const done = new Future(); +// let total = 10; +// let tid = `${total}-test-${Math.random()}`; +// so.onopen = () => { +// so.send(JSON.stringify(testReqSignedUrl(tid))); +// }; +// so.onmessage = async (msg) => { +// try { +// const res = JSON.parse(msg.data.toString()) as ResSignedUrl; +// expect(res).toEqual(await testResSignedUrl(env, tid, URI.from(res.signedUrl).getParam("X-Amz-Date"))); +// if (--total === 0) { +// done.resolve(true); +// } else { +// tid = `${total}-test-${Math.random()}`; +// so.send(JSON.stringify(testReqSignedUrl(tid))); +// } +// } catch (err) { +// done.reject(err); +// } +// }; +// so.onerror = (ev) => { +// assert.fail(`WebSocket error: ${ev}`); +// }; +// return done.asPromise().then(() => so.close(1000, "done")); +// }) +// ); +// }); +// }); + +describe("FireproofCloudGateway", () => { + let db: Database; + let unregister: () => void; + interface ExtendedGateway extends bs.Gateway { + headerSize: number; + subscribe?: (url: URI, callback: (meta: Uint8Array) => void) => Promise; // Changed VoidResult to UnsubscribeResult + } + + // has to leave + interface ExtendedStore { + gateway: ExtendedGateway; + _url: URI; + name: string; + } + + beforeAll(() => { + unregister = registerFireproofCloudStoreProtocol("fireproof:"); + }); + + beforeEach(() => { + const config = { + store: { + stores: { + base: wrangler.build().protocol("fireproof:").setParam("protocol", "ws").setParam("testMode", "true"), + // process.env.FP_STORAGE_URL, // || "fireproof://localhost:1968", + }, + }, + }; + const name = "fireproof-cloud-test-db-" + sthis.nextId().str; + db = fireproof(name, config); + }); + + afterEach(async () => { + // Clear the database before each test + if (db) { + await db.close(); + await db.destroy(); + } + }); + + afterAll(() => { + unregister(); + }); + + // it("env setup is ok", () => { + // // expect(process.env.FP_STORAGE_URL).toMatch(/fireproof:\/\/localhost:1999/); + // }); + + it("should have loader and options", () => { + const loader = db.blockstore.loader; + expect(loader).toBeDefined(); + if (!loader) { + throw new Error("Loader is not defined"); + } + expect(loader.ebOpts).toBeDefined(); + expect(loader.ebOpts.store).toBeDefined(); + expect(loader.ebOpts.store.stores).toBeDefined(); + if (!loader.ebOpts.store.stores) { + throw new Error("Loader stores is not defined"); + } + if (!loader.ebOpts.store.stores.base) { + throw new Error("Loader stores.base is not defined"); + } + + const baseUrl = URI.from(loader.ebOpts.store.stores.base); + expect(baseUrl.protocol).toBe("fireproof:"); + // expect(baseUrl.hostname).toBe("localhost"); + // expect(baseUrl.port || "").toBe("1999"); + }); + + it("should initialize and perform basic operations", async () => { + const docs = await smokeDB(db); + + // // get a new db instance + // db = new Database(name, config); + + // Test update operation + const updateDoc = await db.get<{ content: string }>(docs[0]._id); + updateDoc.content = "Updated content"; + const updateResult = await db.put(updateDoc); + expect(updateResult.id).toBe(updateDoc._id); + + const updatedDoc = await db.get<{ content: string }>(updateDoc._id); + expect(updatedDoc.content).toBe("Updated content"); + + // Test delete operation + await db.del(updateDoc._id); + try { + await db.get(updateDoc._id); + throw new Error("Document should have been deleted"); + } catch (e) { + const error = e as Error; + expect(error.message).toContain("Not found"); + } + }); + + it("should subscribe to changes", async () => { + // Extract stores from the loader + const metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore; + + const metaGateway = metaStore?.gateway; + + const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main"); + await metaGateway?.start(metaStore?._url); + + let didCall = false; + + expect(metaGateway.subscribe).toBeTypeOf("function"); + if (metaGateway.subscribe) { + const future = new Future(); + + const metaSubscribeResult = await metaGateway.subscribe(metaUrl?.Ok(), (data: Uint8Array) => { + // console.log("data", data); + const decodedData = sthis.txt.decode(data); + expect(decodedData).toContain("parents"); + didCall = true; + future.resolve(); + }); + expect(metaSubscribeResult.isOk()).toBeTruthy(); + const ok = await db.put({ _id: "key1", hello: "world1" }); + expect(ok).toBeTruthy(); + expect(ok.id).toBe("key1"); + await future.asPromise(); + expect(didCall).toBeTruthy(); + metaSubscribeResult.Ok()(); + } + }); +}); +describe("AwsClient R2", () => { + it("make presigned url", async () => { + const sthis = ensureSuperThis(); + const a4f = new AwsClient({ + accessKeyId: sthis.env.get("CF_ACCESS_KEY_ID") || "accessKeyId", + secretAccessKey: sthis.env.get("CF_SECRET_ACCESS_KEY") || "secretAccessKey", + region: "us-east-1", + service: "s3", + }); + const buildUrl = BuildURI.from(sthis.env.get("CF_STORAGE_URL") || "https://bucket.example.com/db/main") + .appendRelative("db/main") + .setParam("X-Amz-Expires", "22"); + const signedUrl = await a4f + .sign(new Request(buildUrl.toString(), { method: "PUT" }), { + aws: { + signQuery: true, + datetime: "2021-09-01T12:34:56Z", + }, + }) + .then((res) => res.url); + expect(URI.from(signedUrl).asObj()).toEqual( + buildUrl + .setParam("X-Amz-Date", "2021-09-01T12:34:56Z") + .setParam("X-Amz-Algorithm", "AWS4-HMAC-SHA256") + .setParam("X-Amz-Credential", `${a4f.accessKeyId}/2021-09-/${a4f.region}/${a4f.service}/aws4_request`) + .setParam("X-Amz-SignedHeaders", "host") + .setParam( + "X-Amz-Signature", + sthis.env.get("CF_PRESIGNED_SIGNATURE") || "bbae4604fbe51a4ce9972183d8871a8a187ab0f4d2415afd6dc728f8ccc9900f" + ) + .asObj() + ); + }); +}); + +describe(`store=meta`, () => { + const store = "meta"; + let gw: bs.Gateway; + const sthis = ensureSuperThis(); + let uri: URI; + beforeAll(async () => { + gw = new FireproofCloudGateway(sthis); + const id = sthis.nextId().str; + uri = BuildURI.from("fireproof://localhost") + .port("" + port) + .setParam("store", store) + .setParam("name", id) + .setParam("protocol", "ws") + .setParam("storekey", id) + .setParam("testMode", "true") + .URI(); + + const last: Uint8Array[] = []; + const cnt = 4; + Array(cnt) + .fill(null) + .map(async () => { + const rOk = (await gw.subscribe?.(uri, (meta: Uint8Array) => { + last.push(meta); + if (last.length === cnt) { + expect(last[0]).toEqual(last[1]); + expect(last[1]).toEqual(last[2]); + expect(last[2]).toEqual(last[3]); + last.length = 0; + } + })) as bs.VoidResult; + expect(rOk.isOk()).toBeTruthy(); + }); + + const keyBag = await rt.kb.getKeyBag(sthis); + await keyBag.getNamedKey(`@${id}:data@`); + }); + + afterAll(async () => { + const rOk = await gw.close(uri); + expect(rOk.isOk()).toBeTruthy(); + }); + + const subscribeCallbacks: { + connId: string; + uri: URI; + cb: ReturnType void>>; + unsub: bs.UnsubscribeResult; + }[] = []; + beforeEach(async () => { + await Promise.all( + Array(1) + .fill(null) + .map(async () => { + const cb = vitest.fn(); + const connId = sthis.nextId().str; + const uriConnId = uri.build().setParam("connId", connId).URI(); + const unsub = (await gw.subscribe?.(uriConnId, (meta: Uint8Array) => + cb(sthis.txt.decode(meta), connId) + )) as bs.UnsubscribeResult; + subscribeCallbacks.push({ cb, unsub, connId, uri: uriConnId }); + }) + ); + }); + afterEach(() => { + subscribeCallbacks.forEach(({ unsub }) => unsub.Ok()()); + subscribeCallbacks.length = 0; + }); + + function crdtEntry(connId = "default"): Uint8Array { + return sthis.txt.encode( + JSON.stringify([ + { + cid: `${connId}:bafyreidjlylxmmb3yuz7levzzbso3g7ql54zovxl3mkhbbqxmmfnfbkoym`, + data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWdvdHM3dmFzeHhhdmdoY3FjeHo3ZXJibTdtY21ramQybTV0bXpzcGdhbG91d2lpcjYzZnkifV19Z3BhcmVudHOA", + parents: [], + }, + { + cid: `${connId}:bafyreie7izpgpmxd6heoiweoyblgyzoxt74xrp5wcpqo66bmjv2plgmceq`, + data: "MomRkYXRhoWZkYk1ldGFYU3siY2FycyI6W3siLyI6ImJhZzR5dnFhYmNpcWQyZ2l1c2t2YWJoZTZ5ZHdsdXo0aGx4Z3lyNTZ5dmZmbjVpdndqdmhlYXl3cWJ4bHFmeGEifV19Z3BhcmVudHOA", + parents: [], + }, + ] satisfies CRDTEntry[]) + ); + } + + it(`buildUrl`, async () => { + const rOk = await gw.buildUrl(uri, "KEY"); + const url = rOk.Ok(); + expect(url.getParam("store")).toBe(store); + expect(url.getParam("key")).toBe("KEY"); + }); + it(`start`, async () => { + const rOk = await gw.start(uri); + const url = rOk.Ok(); + expect(url.getParam("store")).toBe(store); + expect(url.getParam("version")).toBeTruthy(); + }); + + it(`unsubscribe`, async () => { + subscribeCallbacks.forEach((sub) => sub.unsub.Ok()()); + const rOk = await gw.put(uri.build().setParam("key", "main").URI(), crdtEntry()); + // console.log(rOk); + expect(rOk.isOk()).toBeTruthy(); + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); + }); + + it(`get-put-delete`, async () => { + async function getNotFound() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.get(u.build().setParam("key", key).URI()); + expect(rOk.isErr()).toBeTruthy(); + expect(isNotFoundError(rOk.Err())).toBeTruthy(); + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); + } + console.log("getNotFound-pre"); + + subscribeCallbacks.forEach(({ cb }) => { + expect(cb).toHaveBeenCalledTimes(0); + }); + // get not found + await getNotFound(); + // put + async function put() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.put( + u.build().setParam("key", key).URI(), + crdtEntry(`${key}:${u.getParam("connId", "default")}`) + ); + expect(rOk.isOk()).toBeTruthy(); + } + } + // console.log('put', subscribeCallbacks.map(({ cb }) => cb.mock.calls)); + subscribeCallbacks.forEach(({ cb, connId }) => { + // expect(cb).toHaveBeenCalledTimes(subscribeCallbacks.length * 2); + for (const key of ["KEY1", "KEY2"]) { + expect(cb).toHaveBeenCalledWith(sthis.txt.decode(crdtEntry(`${key}:${connId}`)), connId); + } + }); + } + // console.log('put-pre') + await put(); + subscribeCallbacks.forEach(({ cb }) => cb.mockClear()); + + async function get() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.get(u.build().setParam("key", key).URI()); + const data = JSON.parse(sthis.txt.decode(rOk.Ok())) as CRDTEntry[]; + expect(data).toEqual(subscribeCallbacks.map(({ connId }) => crdtEntry(connId))); + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); + } + console.log("get-pre"); + await get(); + async function del() { + for (const u of [...subscribeCallbacks.map(({ uri }) => uri), uri]) { + for (const key of ["KEY1", "KEY2"]) { + const rOk = await gw.delete(u.build().setParam("key", key).URI()); + expect(rOk.isOk()).toBeTruthy(); + } + } + subscribeCallbacks.forEach(({ cb }) => expect(cb).not.toHaveBeenCalled()); + } + console.log("del-pre"); + await del(); + // get not found + console.log("getNotFound-pre"); + await getNotFound(); + }); + it(`close`, async () => { + const rOk = await gw.close(uri); + expect(rOk.isOk()).toBeTruthy(); + }); +}); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index de440457..804c9361 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -106,7 +106,8 @@ export class HonoServer { return this; } async close() { - return this.impl.close(); + const ret = await this.impl.close(); + return ret; } } diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 44d337aa..743fc482 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -57,6 +57,9 @@ export class NodeHonoServer implements HonoServerImpl { this._injectWebSocket(this._server); } async close(): Promise { - return new Promise((res) => this._server.close(() => res())); + this._server.close(() => { + /* */ + }); + // return new Promise((res) => this._server.close(() => res())); } } diff --git a/tests/start-s3.sh b/tests/start-s3.sh index 61b40616..2a1f4623 100644 --- a/tests/start-s3.sh +++ b/tests/start-s3.sh @@ -1,11 +1,11 @@ docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'minio'| sed 's/\..*$//') -docker run -d -p 9000:9000 --name minio \ +docker run -d -p 9001:9001 -p 9000:9000 --name minio \ -e "MINIO_ACCESS_KEY=minioadmin" \ -e "MINIO_SECRET_KEY=minioadmin" \ -v /tmp/data:/data \ -v /tmp/config:/root/.minio \ - minio/minio server /data + minio/minio server /data --json --console-address :9001 export AWS_ACCESS_KEY_ID=minioadmin export AWS_SECRET_ACCESS_KEY=minioadmin diff --git a/vitest.cloud.config.ts b/vitest.cloud.config.ts index 71efb795..e4a250ab 100644 --- a/vitest.cloud.config.ts +++ b/vitest.cloud.config.ts @@ -16,7 +16,7 @@ export default defineConfig({ // "node_modules/@fireproof/core/tests/**/*test.?(c|m)[jt]s?(x)", // "node_modules/@fireproof/core/tests/**/*gateway.test.?(c|m)[jt]s?(x)", // "src/connector.test.ts", - "src/cloud/*test.?(c|m)[jt]s?(x)", + "src/cloud/**/*test.?(c|m)[jt]s?(x)", ], globals: true, setupFiles: "./setup.cloud.ts", From 2a87674df1cfdee6d617ccccd794590c1dec61ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:24:25 +0000 Subject: [PATCH 38/83] chore(deps-dev): bump vitest from 2.1.6 to 2.1.8 Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 2.1.6 to 2.1.8. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v2.1.8/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 01b495a3..6fd62f45 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "wait-on": "^8.0.1", "wrangler": "^3.93.0", "ws": "^8.18.0", + "vitest": "^2.1.8", "zx": "^8.2.4" }, "repository": { From c66dc62d28941c42fd5c9155d4e1b387c67f471b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:26:28 +0000 Subject: [PATCH 39/83] chore(deps): bump @adviser/cement from 0.2.40 to 0.2.41 Bumps [@adviser/cement](https://github.com/mabels/cement) from 0.2.40 to 0.2.41. - [Commits](https://github.com/mabels/cement/compare/v0.2.40...v0.2.41) --- updated-dependencies: - dependency-name: "@adviser/cement" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 4 ++++ pnpm-lock.yaml | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 6fd62f45..147c8d9f 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,10 @@ "@fireproof/vendor": "^1.0.0", "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", + "@adviser/cement": "^0.2.41", + "@aws-sdk/client-s3": "^3.703.0", + "@fireproof/core": "0.19.116", + "@fireproof/vendor": "1.0.0", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e078a726..48f5d9f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,10 +9,10 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.3.0 - version: 0.3.0(typescript@5.7.2) + specifier: ^0.2.41 + version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': - specifier: ^3.705.0 + specifier: ^3.703.0 version: 3.705.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 @@ -21,10 +21,10 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: ^0.19.119 - version: 0.19.119(react@18.3.1)(typescript@5.7.2) + specifier: 0.19.116 + version: 0.19.116(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': - specifier: ^1.0.0 + specifier: 1.0.0 version: 1.0.0 '@hono/node-server': specifier: ^1.13.7 @@ -216,8 +216,8 @@ importers: packages: - '@adviser/cement@0.3.0': - resolution: {integrity: sha512-E0J+oHIHCfBsRX3IVYSXKtMczfsyuPS8CbAVYZeNYtaJFItq29IGMMXi0s9B9Y8BpLycHCaPvSydOxCKE/sPYw==} + '@adviser/cement@0.2.41': + resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} engines: {node: '>=16'} '@aws-crypto/crc32@5.2.0': @@ -1074,8 +1074,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.119': - resolution: {integrity: sha512-PSluwTsob3i5+tnrxGIQDNGsJJZ2xzs1uxAaBHyPoeo+wqoDkH86XTJTDpIR2SuL2RfMhX2t8EvtsF5sz4C8/Q==} + '@fireproof/core@0.19.116': + resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} peerDependencies: react: ^18.3.1 @@ -4074,7 +4074,7 @@ packages: snapshots: - '@adviser/cement@0.3.0(typescript@5.7.2)': + '@adviser/cement@0.2.41(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4984,9 +4984,9 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.119(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.3.0(typescript@5.7.2) + '@adviser/cement': 0.2.41(typescript@5.7.2) '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 From 9aed44e793783624e22bb6a81cc12356eea38407 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:40:40 +0000 Subject: [PATCH 40/83] chore(deps): bump @aws-sdk/client-s3 from 3.703.0 to 3.705.0 Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.703.0 to 3.705.0. - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.705.0/clients/client-s3) --- updated-dependencies: - dependency-name: "@aws-sdk/client-s3" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 147c8d9f..c5a7c644 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@adviser/cement": "^0.2.41", - "@aws-sdk/client-s3": "^3.703.0", + "@aws-sdk/client-s3": "^3.705.0", "@fireproof/core": "0.19.116", "@fireproof/vendor": "1.0.0", "@jspm/core": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48f5d9f4..10b840d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,7 +12,7 @@ importers: specifier: ^0.2.41 version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': - specifier: ^3.703.0 + specifier: ^3.705.0 version: 3.705.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 From aadc856ed6389ad66252d206cd50540a91d0f59f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:00:50 +0000 Subject: [PATCH 41/83] chore(deps-dev): bump vite from 6.0.2 to 6.0.3 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.2 to 6.0.3. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.0.3/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index c5a7c644..d224d7bb 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "tsx": "^4.19.2", "typescript": "^5.7.2", "typescript-eslint": "^8.17.0", - "vite": "^6.0.2", + "vite": "^6.0.3", "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", "wait-on": "^8.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 10b840d6..b4d1bfbf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,11 +196,11 @@ importers: specifier: ^8.17.0 version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) vite: - specifier: ^6.0.2 - version: 6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + specifier: ^6.0.3 + version: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.1) @@ -3886,8 +3886,8 @@ packages: terser: optional: true - vite@6.0.2: - resolution: {integrity: sha512-XdQ+VsY2tJpBsKGs0wf3U/+azx8BBpYRHFAyKm5VeEZNOJZRB63q7Sc8Iup3k0TrN3KO6QgyzFf+opSbfY1y0g==} + vite@6.0.3: + resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -8412,13 +8412,13 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.2) optionalDependencies: - vite: 6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + vite: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -8432,7 +8432,7 @@ snapshots: '@types/node': 22.10.1 fsevents: 2.3.3 - vite@6.0.2(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1): + vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1): dependencies: esbuild: 0.24.0 postcss: 8.4.49 From a1eef1f134cf33ada4b0f51f73552395e561bc22 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 9 Dec 2024 15:29:15 +0100 Subject: [PATCH 42/83] from single scripts to docker-compose (#177) * chore: from single scripts to docker-compose * chore: improve exit code handling * chore: zx do not throw * chore: make zx happy with strings vs. arrays * chore: on error exitCode * chore: fix the checksum errors --- package.json | 14 +------ tests/docker-compose.ts | 15 +++++++ tests/docker-compose.yaml | 85 +++++++++++++++++++++++++++++++++++++++ tests/start-netlify.sh | 3 -- tests/start-partykit.sh | 3 -- tests/start-s3.sh | 22 ---------- tests/start-ucan.sh | 3 -- 7 files changed, 102 insertions(+), 43 deletions(-) create mode 100644 tests/docker-compose.ts create mode 100644 tests/docker-compose.yaml delete mode 100644 tests/start-netlify.sh delete mode 100644 tests/start-partykit.sh delete mode 100644 tests/start-s3.sh delete mode 100644 tests/start-ucan.sh diff --git a/package.json b/package.json index d224d7bb..bf3cfad9 100644 --- a/package.json +++ b/package.json @@ -28,19 +28,9 @@ "smoke": "pnpm run '/smoke:/'", "smoke:ucan": "sh smoke/ucan/it.sh", "clean": "rm -rf node_modules dist", - "pretest-docker": "pnpm run '/^pretest:/'; docker ps; tsx tests/waiton.ts", - "pretest:s3": "bash ./tests/start-s3.sh", - "pretest:ucan": "bash ./tests/start-ucan.sh", - "pretest:partykit": "bash ./tests/start-partykit.sh", - "pretest:netlify": "bash ./tests/start-netlify.sh", - "pretest:cloud": "bash ./tests/start-cloud.sh", + "pretest-docker": "tsx tests/docker-compose.ts -f tests/docker-compose.yaml up -d --wait --build", "test": "vitest --run", - "posttest-docker": "pnpm run '/^posttest:/'", - "posttest:cloud": "docker rm -f cloud", - "posttest:ucan": "docker rm -f ucan", - "posttest:partykit": "docker rm -f partykit", - "posttest:netlify": "docker rm -f netlify", - "posttest:minio": "docker rm -f minio", + "posttest-docker": "tsx tests/docker-compose.ts -f tests/docker-compose.yaml down", "format": "prettier .", "lint": "eslint" }, diff --git a/tests/docker-compose.ts b/tests/docker-compose.ts new file mode 100644 index 00000000..2cbce6a5 --- /dev/null +++ b/tests/docker-compose.ts @@ -0,0 +1,15 @@ +import { $ } from "zx"; + +async function main() { + $.verbose = true; + const out = await $`which docker-compose`.catch(() => ({ exitCode: 1 })); + const dockerComposePrg = out.exitCode === 0 ? ["docker-compose"] : ["docker", "compose"]; + const res = await $`${dockerComposePrg} ${process.argv.slice(2)}`; + process.exit(res.exitCode); +} + +// eslint-disable-next-line no-console +main().catch((e) => { + console.error(e); + process.exit(2); +}); diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml new file mode 100644 index 00000000..3b9df0c6 --- /dev/null +++ b/tests/docker-compose.yaml @@ -0,0 +1,85 @@ +services: + netlify: + image: connect-netlify + build: + context: .. + dockerfile: ./tests/Dockerfile.connect-netlify + ports: + - 8888:8888 + + partykit: + image: connect-partykit + build: + context: .. + dockerfile: ./tests/Dockerfile.connect-partykit + ports: + - 1999:1999 + + minio: + image: minio/minio + ports: + - 9000:9000 + environment: + MINIO_ACCESS_KEY: minioadmin + MINIO_SECRET_KEY: minioadmin + volumes: + - /tmp/data:/data + - /tmp/config:/root/.minio + command: server /data + + create-bucket: + image: amazon/aws-cli + environment: + AWS_ACCESS_KEY_ID: minioadmin + AWS_SECRET_ACCESS_KEY: minioadmin + AWS_EC2_METADATA_DISABLED: true + command: --endpoint-url http://minio:9000/ s3 mb s3://testbucket + depends_on: + minio: + condition: service_started + + #docker run -d -p 9000:9000 --name minio \ + # -e "MINIO_ACCESS_KEY=minioadmin" \ + # -e "MINIO_SECRET_KEY=minioadmin" \ + # -v /tmp/data:/data \ + # -v /tmp/config:/root/.minio \ + # minio/minio server /data + # + #sleep 5 + #aws --endpoint-url http://127.0.0.1:9000/ s3 mb s3://testbucket + #export AWS_S3_BUCKET=testbucket + #export AWS_S3_ACCESS_KEY=minioadmin + #export AWS_S3_SECRET_KEY=minioadmin + #export AWS_S3_ENDPOINT=http://127.0.0.1:9000 + + ucan: + build: + # context: ucan + context: .. + dockerfile: ./tests/Dockerfile.fp-ucan + ports: + - 8787:8787 + + #docker buildx build -t fireproof-ucan:latest -f ./tests/Dockerfile.fp-ucan . + #docker run --name ucan -d -p 8787:8787 fireproof-ucan + + wait-for-ready: + image: curlimages/curl + command: "sleep 86400" + depends_on: + netlify: + condition: service_started + partykit: + condition: service_started + ucan: + condition: service_started + minio: + condition: service_started + healthcheck: + test: + - CMD-SHELL + - "-c" + - "curl http://netlify:8888 ; curl http://minio:9000 ; curl http://ucan:8787 ; curl http://partykit:1999" + interval: 5s + retries: 30 + timeout: 2s diff --git a/tests/start-netlify.sh b/tests/start-netlify.sh deleted file mode 100644 index 8b6e731a..00000000 --- a/tests/start-netlify.sh +++ /dev/null @@ -1,3 +0,0 @@ -docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'netlify'| sed 's/\..*$//') -docker buildx build -t connect-netlify:latest -f ./tests/Dockerfile.connect-netlify . -docker run --name netlify -d -p 8888:8888 connect-netlify diff --git a/tests/start-partykit.sh b/tests/start-partykit.sh deleted file mode 100644 index 751bfe64..00000000 --- a/tests/start-partykit.sh +++ /dev/null @@ -1,3 +0,0 @@ -docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'partykit'| sed 's/\..*$//') -docker buildx build -t connect-partykit:latest -f ./tests/Dockerfile.connect-partykit . -docker run --name partykit -d -p 1999:1999 connect-partykit diff --git a/tests/start-s3.sh b/tests/start-s3.sh deleted file mode 100644 index 2a1f4623..00000000 --- a/tests/start-s3.sh +++ /dev/null @@ -1,22 +0,0 @@ -docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'minio'| sed 's/\..*$//') - -docker run -d -p 9001:9001 -p 9000:9000 --name minio \ - -e "MINIO_ACCESS_KEY=minioadmin" \ - -e "MINIO_SECRET_KEY=minioadmin" \ - -v /tmp/data:/data \ - -v /tmp/config:/root/.minio \ - minio/minio server /data --json --console-address :9001 - -export AWS_ACCESS_KEY_ID=minioadmin -export AWS_SECRET_ACCESS_KEY=minioadmin -export AWS_EC2_METADATA_DISABLED=true - -sleep 5 -aws --endpoint-url http://127.0.0.1:9000/ s3 mb s3://testbucket - -export AWS_S3_BUCKET=testbucket -export AWS_S3_ACCESS_KEY=minioadmin -export AWS_S3_SECRET_KEY=minioadmin -export AWS_S3_ENDPOINT=http://127.0.0.1:9000 - - diff --git a/tests/start-ucan.sh b/tests/start-ucan.sh deleted file mode 100644 index 40b7ce82..00000000 --- a/tests/start-ucan.sh +++ /dev/null @@ -1,3 +0,0 @@ -docker rm -f $(docker ps --format '{{.ID}}.{{.Names}}' -a | grep 'ucan'| sed 's/\..*$//') -docker buildx build -t fireproof-ucan:latest -f ./tests/Dockerfile.fp-ucan . -docker run --name ucan -d -p 8787:8787 fireproof-ucan From 347c46fff135e01dd55c14f6eabd1854dd8464c4 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Tue, 10 Dec 2024 00:00:01 -0500 Subject: [PATCH 43/83] chore: bump version 0.19.117 --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index bf3cfad9..73be582b 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "@hono/node-ws": "^1.0.4", "@adviser/cement": "^0.2.41", "@aws-sdk/client-s3": "^3.705.0", - "@fireproof/core": "0.19.116", + "@fireproof/core": "0.19.117", "@fireproof/vendor": "1.0.0", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4d1bfbf..16040575 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: 0.19.116 - version: 0.19.116(react@18.3.1)(typescript@5.7.2) + specifier: 0.19.117 + version: 0.19.117(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 @@ -1074,8 +1074,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.116': - resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} + '@fireproof/core@0.19.117': + resolution: {integrity: sha512-24+SqrpJqJpUEVZgm5NDY4p95qgSfzu4MwVkcWa7Qj7cxg7wxqo45B44m8BqbiS4LlSeN7agE/oj5EP7BdRL9g==} peerDependencies: react: ^18.3.1 @@ -4984,7 +4984,7 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.117(react@18.3.1)(typescript@5.7.2)': dependencies: '@adviser/cement': 0.2.41(typescript@5.7.2) '@fireproof/vendor': 1.0.0 From 0e56a0e0d6fa57315c891eb3eba4905f7fe93c4f Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Tue, 10 Dec 2024 00:32:26 -0500 Subject: [PATCH 44/83] chore: skip 0.19.117 --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 73be582b..17ff44b8 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "@hono/node-ws": "^1.0.4", "@adviser/cement": "^0.2.41", "@aws-sdk/client-s3": "^3.705.0", - "@fireproof/core": "0.19.117", + "@fireproof/core": "0.19.118", "@fireproof/vendor": "1.0.0", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16040575..e06ba7af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: 0.19.117 - version: 0.19.117(react@18.3.1)(typescript@5.7.2) + specifier: 0.19.118 + version: 0.19.118(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': specifier: 1.0.0 version: 1.0.0 @@ -1074,8 +1074,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.117': - resolution: {integrity: sha512-24+SqrpJqJpUEVZgm5NDY4p95qgSfzu4MwVkcWa7Qj7cxg7wxqo45B44m8BqbiS4LlSeN7agE/oj5EP7BdRL9g==} + '@fireproof/core@0.19.118': + resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} peerDependencies: react: ^18.3.1 @@ -4984,7 +4984,7 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.117(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': dependencies: '@adviser/cement': 0.2.41(typescript@5.7.2) '@fireproof/vendor': 1.0.0 From 12023a7ab257523407a074f7afff0c4be8e77b0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:52:51 +0000 Subject: [PATCH 45/83] chore(deps-dev): bump @types/node from 22.10.1 to 22.10.2 Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.10.1 to 22.10.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 68 +++++++++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 17ff44b8..2b76f90b 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@smithy/types": "^3.7.1", "@types/better-sqlite3": "^7.6.12", "@types/eslint__js": "^8.42.3", - "@types/node": "^22.10.1", + "@types/node": "^22.10.2", "@types/wait-on": "^5.3.4", "@types/ws": "^8.5.13", "@typescript-eslint/typescript-estree": "^8.17.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e06ba7af..ca14b4ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 3.705.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 - version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1)) + version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 @@ -151,8 +151,8 @@ importers: specifier: ^8.42.3 version: 8.42.3 '@types/node': - specifier: ^22.10.1 - version: 22.10.1 + specifier: ^22.10.2 + version: 22.10.2 '@types/wait-on': specifier: ^5.3.4 version: 5.3.4 @@ -197,13 +197,13 @@ importers: version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) vite: specifier: ^6.0.3 - version: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + version: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 - version: 2.1.8(@types/node@22.10.1) + version: 2.1.8(@types/node@22.10.2) wrangler: specifier: ^3.93.0 version: 3.93.0(@cloudflare/workers-types@4.20241205.0) @@ -1591,8 +1591,8 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@22.10.1': - resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} + '@types/node@22.10.2': + resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} '@types/retry@0.12.1': resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} @@ -4592,7 +4592,7 @@ snapshots: dependencies: mime: 3.0.0 - '@cloudflare/vitest-pool-workers@0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.1))': + '@cloudflare/vitest-pool-workers@0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))': dependencies: '@vitest/runner': 2.1.8 '@vitest/snapshot': 2.1.8 @@ -4602,7 +4602,7 @@ snapshots: esbuild: 0.17.19 miniflare: 3.20241205.0 semver: 7.6.3 - vitest: 2.1.8(@types/node@22.10.1) + vitest: 2.1.8(@types/node@22.10.2) wrangler: 3.93.0(@cloudflare/workers-types@4.20241205.0) zod: 3.23.8 transitivePeerDependencies: @@ -5609,7 +5609,7 @@ snapshots: '@types/better-sqlite3@7.6.12': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 '@types/eslint@9.6.1': dependencies: @@ -5625,23 +5625,23 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.10.1 + '@types/node': 22.10.2 optional: true '@types/json-schema@7.0.15': {} '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 optional: true '@types/minimatch@3.0.5': {} '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 - '@types/node@22.10.1': + '@types/node@22.10.2': dependencies: undici-types: 6.20.0 @@ -5651,11 +5651,11 @@ snapshots: '@types/wait-on@5.3.4': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 '@types/ws@8.5.13': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': dependencies: @@ -5794,13 +5794,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.1))': + '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.2))': dependencies: '@vitest/spy': 2.1.8 estree-walker: 3.0.3 magic-string: 0.30.12 optionalDependencies: - vite: 5.4.11(@types/node@22.10.1) + vite: 5.4.11(@types/node@22.10.2) '@vitest/pretty-format@2.1.8': dependencies: @@ -7809,7 +7809,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.10.1 + '@types/node': 22.10.2 long: 5.2.3 protons-runtime@5.5.0: @@ -8394,13 +8394,13 @@ snapshots: varint@6.0.0: {} - vite-node@2.1.8(@types/node@22.10.1): + vite-node@2.1.8(@types/node@22.10.2): dependencies: cac: 6.7.14 debug: 4.3.7 es-module-lexer: 1.5.4 pathe: 1.1.2 - vite: 5.4.11(@types/node@22.10.1) + vite: 5.4.11(@types/node@22.10.2) transitivePeerDependencies: - '@types/node' - less @@ -8412,43 +8412,43 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.2) optionalDependencies: - vite: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + vite: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) transitivePeerDependencies: - supports-color - typescript - vite@5.4.11(@types/node@22.10.1): + vite@5.4.11(@types/node@22.10.2): dependencies: esbuild: 0.21.5 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 fsevents: 2.3.3 - vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1): + vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: esbuild: 0.24.0 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 fsevents: 2.3.3 tsx: 4.19.2 yaml: 2.5.1 vitest-pool-workers@0.0.1: {} - vitest@2.1.8(@types/node@22.10.1): + vitest@2.1.8(@types/node@22.10.2): dependencies: '@vitest/expect': 2.1.8 - '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.1)) + '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.2)) '@vitest/pretty-format': 2.1.8 '@vitest/runner': 2.1.8 '@vitest/snapshot': 2.1.8 @@ -8464,11 +8464,11 @@ snapshots: tinyexec: 0.3.1 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 5.4.11(@types/node@22.10.1) - vite-node: 2.1.8(@types/node@22.10.1) + vite: 5.4.11(@types/node@22.10.2) + vite-node: 2.1.8(@types/node@22.10.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.2 transitivePeerDependencies: - less - lightningcss @@ -8617,4 +8617,4 @@ snapshots: zx@8.2.4: optionalDependencies: '@types/fs-extra': 11.0.4 - '@types/node': 22.10.1 + '@types/node': 22.10.2 From c410a2c3bf2d2760d2223e37f74556e309cf9ee0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:52:39 +0000 Subject: [PATCH 46/83] chore(deps): bump @web3-storage/capabilities from 17.4.1 to 18.0.0 Bumps [@web3-storage/capabilities](https://github.com/storacha/w3up/tree/HEAD/packages/capabilities) from 17.4.1 to 18.0.0. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/capabilities/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/access-v18.0.0/packages/capabilities) --- updated-dependencies: - dependency-name: "@web3-storage/capabilities" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2b76f90b..4452f69e 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@ucanto/transport": "^9.1.1", "@ucanto/validator": "^9.0.2", "@web3-storage/access": "^20.1.0", - "@web3-storage/capabilities": "^17.4.1", + "@web3-storage/capabilities": "^18.0.0", "@web3-storage/clock": "^0.4.1", "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca14b4ef..5c5c0100 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^20.1.0 version: 20.1.0 '@web3-storage/capabilities': - specifier: ^17.4.1 - version: 17.4.1 + specifier: ^18.0.0 + version: 18.0.0 '@web3-storage/clock': specifier: ^0.4.1 version: 0.4.1 @@ -1728,6 +1728,9 @@ packages: '@web3-storage/capabilities@17.4.1': resolution: {integrity: sha512-GogLfON8PZabi03CUyncBvMcCi36yQ/0iR5P8kr4pxdnZm7OuAn4sEwbEB8rTKbah5V10Vwgb3O5dh0FBgyjHg==} + '@web3-storage/capabilities@18.0.0': + resolution: {integrity: sha512-sG0GmHrNNR+nT7wB1sIz91FG55PWJvrquMZyY8GD20r0l49kojDTlz/n14bEhof9uKE0T9KinmxitknOx/B+4Q==} + '@web3-storage/clock@0.4.1': resolution: {integrity: sha512-VHAyvbl7ZrNls6yltS5Djuwjz9Rw0rcA8tpv7qQp1WoheY00YBdqa8gjR1V4egVkqV1ZugGA06XH+ug0OhGXDg==} @@ -5869,6 +5872,16 @@ snapshots: '@web3-storage/data-segment': 5.2.0 uint8arrays: 5.1.0 + '@web3-storage/capabilities@18.0.0': + dependencies: + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/transport': 9.1.1 + '@ucanto/validator': 9.0.2 + '@web3-storage/data-segment': 5.2.0 + uint8arrays: 5.1.0 + '@web3-storage/clock@0.4.1': dependencies: '@ipld/dag-cbor': 9.2.2 From 87da04c8f94e4e61a450335412be27329da0e516 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:52:24 +0000 Subject: [PATCH 47/83] chore(deps-dev): bump eslint from 9.16.0 to 9.17.0 Bumps [eslint](https://github.com/eslint/eslint) from 9.16.0 to 9.17.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.16.0...v9.17.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 62 +++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 4452f69e..778bd180 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", - "eslint": "^9.16.0", + "eslint": "^9.17.0", "prettier": "^3.4.2", "semver": "^7.6.3", "std-env": "^3.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c5c0100..6b8834a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,8 +172,8 @@ importers: specifier: ^2.0.0 version: 2.0.0 eslint: - specifier: ^9.16.0 - version: 9.16.0 + specifier: ^9.17.0 + version: 9.17.0 prettier: specifier: ^3.4.2 version: 3.4.2 @@ -194,7 +194,7 @@ importers: version: 5.7.2 typescript-eslint: specifier: ^8.17.0 - version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) + version: 8.17.0(eslint@9.17.0)(typescript@5.7.2) vite: specifier: ^6.0.3 version: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) @@ -1062,6 +1062,10 @@ packages: resolution: {integrity: sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.17.0': + resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.4': resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2228,8 +2232,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.16.0: - resolution: {integrity: sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==} + eslint@9.17.0: + resolution: {integrity: sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -4946,9 +4950,9 @@ snapshots: '@esbuild/win32-x64@0.24.0': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@9.16.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.17.0)': dependencies: - eslint: 9.16.0 + eslint: 9.17.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -4979,6 +4983,8 @@ snapshots: '@eslint/js@9.16.0': {} + '@eslint/js@9.17.0': {} + '@eslint/object-schema@2.1.4': {} '@eslint/plugin-kit@0.2.3': @@ -5660,15 +5666,15 @@ snapshots: dependencies: '@types/node': 22.10.2 - '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.17.0(eslint@9.17.0)(typescript@5.7.2) '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/type-utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.17.0 - eslint: 9.16.0 + eslint: 9.17.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -5678,14 +5684,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@typescript-eslint/scope-manager': 8.17.0 '@typescript-eslint/types': 8.17.0 '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.17.0 debug: 4.3.7 - eslint: 9.16.0 + eslint: 9.17.0 optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -5696,12 +5702,12 @@ snapshots: '@typescript-eslint/types': 8.17.0 '@typescript-eslint/visitor-keys': 8.17.0 - '@typescript-eslint/type-utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.17.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) debug: 4.3.7 - eslint: 9.16.0 + eslint: 9.17.0 ts-api-utils: 1.3.0(typescript@5.7.2) optionalDependencies: typescript: 5.7.2 @@ -5725,13 +5731,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.17.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) '@typescript-eslint/scope-manager': 8.17.0 '@typescript-eslint/types': 8.17.0 '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - eslint: 9.16.0 + eslint: 9.17.0 optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: @@ -6601,14 +6607,14 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.16.0: + eslint@9.17.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.0 '@eslint/core': 0.9.0 '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.16.0 + '@eslint/js': 9.17.0 '@eslint/plugin-kit': 0.2.3 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -8322,12 +8328,12 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): + typescript-eslint@8.17.0(eslint@9.17.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - eslint: 9.16.0 + '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.17.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) + eslint: 9.17.0 optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: From b379722e48579cf171e3b6e4f7c17473e903686d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:52:01 +0000 Subject: [PATCH 48/83] chore(deps-dev): bump wrangler from 3.93.0 to 3.95.0 Bumps [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) from 3.93.0 to 3.95.0. - [Release notes](https://github.com/cloudflare/workers-sdk/releases) - [Changelog](https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/CHANGELOG.md) - [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@3.95.0/packages/wrangler) --- updated-dependencies: - dependency-name: wrangler dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 778bd180..56f28a40 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", "wait-on": "^8.0.1", - "wrangler": "^3.93.0", + "wrangler": "^3.95.0", "ws": "^8.18.0", "vitest": "^2.1.8", "zx": "^8.2.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b8834a3..d82fae8d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,8 +205,8 @@ importers: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.2) wrangler: - specifier: ^3.93.0 - version: 3.93.0(@cloudflare/workers-types@4.20241205.0) + specifier: ^3.95.0 + version: 3.95.0(@cloudflare/workers-types@4.20241205.0) ws: specifier: ^8.18.0 version: 8.18.0 @@ -458,6 +458,10 @@ packages: resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} engines: {node: '>=16.7.0'} + '@cloudflare/workers-shared@0.11.0': + resolution: {integrity: sha512-A+lQ8xp7992qSeMmuQ0ssL6CPmm+ZmAv6Ddikan0n1jjpMAic+97l7xtVIsswSn9iLMFPYQ9uNN/8Fl0AgARIQ==} + engines: {node: '>=16.7.0'} + '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} @@ -4026,6 +4030,16 @@ packages: '@cloudflare/workers-types': optional: true + wrangler@3.95.0: + resolution: {integrity: sha512-3w5852i3FNyDz421K2Qk4v5L8jjwegO5O8E1+VAQmjnm82HFNxpIRUBq0bmM7CTLvOPI/Jjcmj/eAWjQBL7QYg==} + engines: {node: '>=16.17.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20241205.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -4653,6 +4667,11 @@ snapshots: mime: 3.0.0 zod: 3.23.8 + '@cloudflare/workers-shared@0.11.0': + dependencies: + mime: 3.0.0 + zod: 3.23.8 + '@cloudflare/workers-types@4.20240718.0': {} '@cloudflare/workers-types@4.20241205.0': {} @@ -8599,6 +8618,34 @@ snapshots: - supports-color - utf-8-validate + wrangler@3.95.0(@cloudflare/workers-types@4.20241205.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.11.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 4.0.1 + date-fns: 4.1.0 + esbuild: 0.17.19 + itty-time: 1.0.6 + miniflare: 3.20241205.0 + nanoid: 3.3.7 + path-to-regexp: 6.3.0 + resolve: 1.22.8 + selfsigned: 2.4.1 + source-map: 0.6.1 + unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190 + workerd: 1.20241205.0 + xxhash-wasm: 1.0.2 + optionalDependencies: + '@cloudflare/workers-types': 4.20241205.0 + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 From 99b314a868fe383bc382589e2b29179bebbb078b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:51:43 +0000 Subject: [PATCH 49/83] chore(deps-dev): bump @smithy/types from 3.7.1 to 3.7.2 Bumps [@smithy/types](https://github.com/awslabs/smithy-typescript/tree/HEAD/packages/types) from 3.7.1 to 3.7.2. - [Release notes](https://github.com/awslabs/smithy-typescript/releases) - [Changelog](https://github.com/smithy-lang/smithy-typescript/blob/main/packages/types/CHANGELOG.md) - [Commits](https://github.com/awslabs/smithy-typescript/commits/@smithy/types@3.7.2/packages/types) --- updated-dependencies: - dependency-name: "@smithy/types" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 146 ++++++++++++++++++++++++------------------------- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/package.json b/package.json index 56f28a40..021a5efb 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "license": "Apache-2.0 OR MIT", "devDependencies": { "@eslint/js": "^9.16.0", - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "@types/better-sqlite3": "^7.6.12", "@types/eslint__js": "^8.42.3", "@types/node": "^22.10.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d82fae8d..22174a59 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,8 +142,8 @@ importers: specifier: ^9.16.0 version: 9.16.0 '@smithy/types': - specifier: ^3.7.1 - version: 3.7.1 + specifier: ^3.7.2 + version: 3.7.2 '@types/better-sqlite3': specifier: ^7.6.12 version: 7.6.12 @@ -1495,8 +1495,8 @@ packages: resolution: {integrity: sha512-dPGoJuSZqvirBq+yROapBcHHvFjChoAQT8YPWJ820aPHHiowBlB3RL1Q4kPT1hx0qKgJuf+HhyzKi5Gbof4fNA==} engines: {node: '>=16.0.0'} - '@smithy/types@3.7.1': - resolution: {integrity: sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==} + '@smithy/types@3.7.2': + resolution: {integrity: sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==} engines: {node: '>=16.0.0'} '@smithy/url-parser@3.0.10': @@ -4195,7 +4195,7 @@ snapshots: '@smithy/node-http-handler': 3.3.1 '@smithy/protocol-http': 4.1.7 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 @@ -4242,7 +4242,7 @@ snapshots: '@smithy/node-http-handler': 3.3.1 '@smithy/protocol-http': 4.1.7 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 @@ -4285,7 +4285,7 @@ snapshots: '@smithy/node-http-handler': 3.3.1 '@smithy/protocol-http': 4.1.7 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 @@ -4330,7 +4330,7 @@ snapshots: '@smithy/node-http-handler': 3.3.1 '@smithy/protocol-http': 4.1.7 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 @@ -4354,7 +4354,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/signature-v4': 4.2.3 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.10 fast-xml-parser: 4.4.1 tslib: 2.8.1 @@ -4364,7 +4364,7 @@ snapshots: '@aws-sdk/core': 3.696.0 '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.696.0': @@ -4376,7 +4376,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/protocol-http': 4.1.7 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-stream': 3.3.1 tslib: 2.8.1 @@ -4393,7 +4393,7 @@ snapshots: '@smithy/credential-provider-imds': 3.2.7 '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' @@ -4411,7 +4411,7 @@ snapshots: '@smithy/credential-provider-imds': 3.2.7 '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' @@ -4424,7 +4424,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/credential-provider-sso@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': @@ -4435,7 +4435,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' @@ -4447,7 +4447,7 @@ snapshots: '@aws-sdk/core': 3.696.0 '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-bucket-endpoint@3.696.0': @@ -4456,7 +4456,7 @@ snapshots: '@aws-sdk/util-arn-parser': 3.693.0 '@smithy/node-config-provider': 3.1.11 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 tslib: 2.8.1 @@ -4464,7 +4464,7 @@ snapshots: dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-flexible-checksums@3.701.0': @@ -4477,7 +4477,7 @@ snapshots: '@smithy/is-array-buffer': 3.0.0 '@smithy/node-config-provider': 3.1.11 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 @@ -4487,26 +4487,26 @@ snapshots: dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-location-constraint@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-logger@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-sdk-s3@3.696.0': @@ -4519,7 +4519,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/signature-v4': 4.2.3 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 @@ -4529,7 +4529,7 @@ snapshots: '@aws-sdk/middleware-ssec@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.696.0': @@ -4539,14 +4539,14 @@ snapshots: '@aws-sdk/util-endpoints': 3.696.0 '@smithy/core': 2.5.3 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/region-config-resolver@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/node-config-provider': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 tslib: 2.8.1 @@ -4557,7 +4557,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/signature-v4': 4.2.3 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/token-providers@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': @@ -4566,12 +4566,12 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/types@3.696.0': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/util-arn-parser@3.693.0': @@ -4581,7 +4581,7 @@ snapshots: '@aws-sdk/util-endpoints@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-endpoints': 2.1.6 tslib: 2.8.1 @@ -4592,7 +4592,7 @@ snapshots: '@aws-sdk/util-user-agent-browser@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 @@ -4601,12 +4601,12 @@ snapshots: '@aws-sdk/middleware-user-agent': 3.696.0 '@aws-sdk/types': 3.696.0 '@smithy/node-config-provider': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@aws-sdk/xml-builder@3.696.0': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@cloudflare/kv-asset-handler@0.3.4': @@ -5304,7 +5304,7 @@ snapshots: '@smithy/abort-controller@3.1.8': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/chunked-blob-reader-native@3.0.1': @@ -5319,7 +5319,7 @@ snapshots: '@smithy/config-resolver@3.0.12': dependencies: '@smithy/node-config-provider': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 tslib: 2.8.1 @@ -5328,7 +5328,7 @@ snapshots: dependencies: '@smithy/middleware-serde': 3.0.10 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 @@ -5339,45 +5339,45 @@ snapshots: dependencies: '@smithy/node-config-provider': 3.1.11 '@smithy/property-provider': 3.1.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 tslib: 2.8.1 '@smithy/eventstream-codec@3.1.9': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-hex-encoding': 3.0.0 tslib: 2.8.1 '@smithy/eventstream-serde-browser@3.0.13': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/eventstream-serde-config-resolver@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/eventstream-serde-node@3.0.12': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/eventstream-serde-universal@3.0.12': dependencies: '@smithy/eventstream-codec': 3.1.9 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/fetch-http-handler@4.1.1': dependencies: '@smithy/protocol-http': 4.1.7 '@smithy/querystring-builder': 3.0.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 tslib: 2.8.1 @@ -5385,25 +5385,25 @@ snapshots: dependencies: '@smithy/chunked-blob-reader': 4.0.0 '@smithy/chunked-blob-reader-native': 3.0.1 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/hash-node@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 '@smithy/hash-stream-node@3.1.9': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 '@smithy/invalid-dependency@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -5416,14 +5416,14 @@ snapshots: '@smithy/md5-js@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 '@smithy/middleware-content-length@3.0.12': dependencies: '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/middleware-endpoint@3.2.3': @@ -5432,7 +5432,7 @@ snapshots: '@smithy/middleware-serde': 3.0.10 '@smithy/node-config-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.10 '@smithy/util-middleware': 3.0.10 tslib: 2.8.1 @@ -5443,7 +5443,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/service-error-classification': 3.0.10 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 tslib: 2.8.1 @@ -5451,19 +5451,19 @@ snapshots: '@smithy/middleware-serde@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/middleware-stack@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/node-config-provider@3.1.11': dependencies: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/node-http-handler@3.3.1': @@ -5471,44 +5471,44 @@ snapshots: '@smithy/abort-controller': 3.1.8 '@smithy/protocol-http': 4.1.7 '@smithy/querystring-builder': 3.0.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/property-provider@3.1.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/protocol-http@4.1.7': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/querystring-builder@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-uri-escape': 3.0.0 tslib: 2.8.1 '@smithy/querystring-parser@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/service-error-classification@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/shared-ini-file-loader@3.1.11': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/signature-v4@4.2.3': dependencies: '@smithy/is-array-buffer': 3.0.0 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-hex-encoding': 3.0.0 '@smithy/util-middleware': 3.0.10 '@smithy/util-uri-escape': 3.0.0 @@ -5521,18 +5521,18 @@ snapshots: '@smithy/middleware-endpoint': 3.2.3 '@smithy/middleware-stack': 3.0.10 '@smithy/protocol-http': 4.1.7 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-stream': 3.3.1 tslib: 2.8.1 - '@smithy/types@3.7.1': + '@smithy/types@3.7.2': dependencies: tslib: 2.7.0 '@smithy/url-parser@3.0.10': dependencies: '@smithy/querystring-parser': 3.0.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/util-base64@3.0.0': @@ -5567,7 +5567,7 @@ snapshots: dependencies: '@smithy/property-provider': 3.1.10 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 @@ -5578,13 +5578,13 @@ snapshots: '@smithy/node-config-provider': 3.1.11 '@smithy/property-provider': 3.1.10 '@smithy/smithy-client': 3.4.4 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/util-endpoints@2.1.6': dependencies: '@smithy/node-config-provider': 3.1.11 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/util-hex-encoding@3.0.0': @@ -5593,20 +5593,20 @@ snapshots: '@smithy/util-middleware@3.0.10': dependencies: - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/util-retry@3.0.10': dependencies: '@smithy/service-error-classification': 3.0.10 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@smithy/util-stream@3.3.1': dependencies: '@smithy/fetch-http-handler': 4.1.1 '@smithy/node-http-handler': 3.3.1 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 '@smithy/util-buffer-from': 3.0.0 '@smithy/util-hex-encoding': 3.0.0 @@ -5630,7 +5630,7 @@ snapshots: '@smithy/util-waiter@3.1.9': dependencies: '@smithy/abort-controller': 3.1.8 - '@smithy/types': 3.7.1 + '@smithy/types': 3.7.2 tslib: 2.8.1 '@storacha/one-webcrypto@1.0.1': {} From 1da22f3bb55e7537fd6deec858eb51552af6489c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:50:08 +0000 Subject: [PATCH 50/83] chore(deps): bump node-sqlite3-wasm from 0.8.28 to 0.8.29 Bumps [node-sqlite3-wasm](https://github.com/tndrle/node-sqlite3-wasm) from 0.8.28 to 0.8.29. - [Release notes](https://github.com/tndrle/node-sqlite3-wasm/releases) - [Commits](https://github.com/tndrle/node-sqlite3-wasm/compare/v0.8.28...v0.8.29) --- updated-dependencies: - dependency-name: node-sqlite3-wasm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 021a5efb..2245c1fb 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "idb-keyval": "^6.2.1", "is-deep-strict-equal-x": "^1.1.2", "multiformats": "^13.3.1", - "node-sqlite3-wasm": "^0.8.28", + "node-sqlite3-wasm": "^0.8.29", "partykit": "^0.0.111", "partyserver": "^0.0.57", "partysocket": "^1.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22174a59..c9d2ac3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,8 +108,8 @@ importers: specifier: ^13.3.1 version: 13.3.1 node-sqlite3-wasm: - specifier: ^0.8.28 - version: 0.8.28 + specifier: ^0.8.29 + version: 0.8.29 partykit: specifier: ^0.0.111 version: 0.0.111 @@ -3065,8 +3065,8 @@ packages: resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} engines: {node: '>=8'} - node-sqlite3-wasm@0.8.28: - resolution: {integrity: sha512-QK5Q0+sgsHNPWiOPFHiBWrfXuJa9UDXi7nUDHhyIlVgoVzltWKDGqoNOERjga+o+ncr5Od7A7kkB4GEmsoUuSA==} + node-sqlite3-wasm@0.8.29: + resolution: {integrity: sha512-daoT9XIXCjW/Cg6YEGxdfod4wJMoHVuu4xDjHVWE7Zl45eiGkRBOErc73TYcO4rh02dDSFRDK7q7OUQnNXCrTQ==} noop-x@1.2.1: resolution: {integrity: sha512-X+jn3u2YhlAjteZIfrcVxaDLRfnrMvkzQ+jRatOX8UO7PFqU0QKlcyI2DhvLKEK2K4u1cRrZw9QqK3XruvyH2A==} @@ -7563,7 +7563,7 @@ snapshots: dependencies: big-integer: 1.6.52 - node-sqlite3-wasm@0.8.28: {} + node-sqlite3-wasm@0.8.29: {} noop-x@1.2.1: {} From 698291af13261c4f281eddea3f9f478a9011eb45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:50:21 +0000 Subject: [PATCH 51/83] chore(deps): bump partysocket from 1.0.2 to 1.0.3 Bumps [partysocket](https://github.com/partykit/partykit/tree/HEAD/packages/partykit) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/partykit/partykit/releases) - [Changelog](https://github.com/partykit/partykit/blob/main/packages/partykit/CHANGELOG.md) - [Commits](https://github.com/partykit/partykit/commits/partysocket@1.0.3/packages/partykit) --- updated-dependencies: - dependency-name: partysocket dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 2245c1fb..c52c0a24 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "node-sqlite3-wasm": "^0.8.29", "partykit": "^0.0.111", "partyserver": "^0.0.57", - "partysocket": "^1.0.2", + "partysocket": "^1.0.3", "path": "^0.12.7", "smol-toml": "^1.3.1", "util": "^0.12.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c9d2ac3f..8983b8c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -117,8 +117,8 @@ importers: specifier: ^0.0.57 version: 0.0.57(@cloudflare/workers-types@4.20241205.0) partysocket: - specifier: ^1.0.2 - version: 1.0.2 + specifier: ^1.0.3 + version: 1.0.3 path: specifier: ^0.12.7 version: 0.12.7 @@ -3200,8 +3200,8 @@ packages: peerDependencies: '@cloudflare/workers-types': ^4.20240729.0 - partysocket@1.0.2: - resolution: {integrity: sha512-rAFOUKImaq+VBk2B+2RTBsWEvlnarEP53nchoUHzpVs8V6fG2/estihOTslTQUWHVuHEKDL5k8htG8K3TngyFA==} + partysocket@1.0.3: + resolution: {integrity: sha512-7sSojS4oCRK1Fe1h+Sa0Za5dwOf+M9VksQlynD8yqwGpLvnO4oxx9ppmOSeh6CJTMbF5gbnvUQKMK525QSBdBw==} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -7747,7 +7747,7 @@ snapshots: '@cloudflare/workers-types': 4.20241205.0 nanoid: 5.0.9 - partysocket@1.0.2: + partysocket@1.0.3: dependencies: event-target-shim: 6.0.2 From 84bbc709ca90422143832873823b09cc75b905c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:28:10 +0000 Subject: [PATCH 52/83] chore(deps): bump @web3-storage/access from 20.1.0 to 20.1.1 Bumps [@web3-storage/access](https://github.com/storacha/w3up/tree/HEAD/packages/access-client) from 20.1.0 to 20.1.1. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/access-client/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/access-v20.1.1/packages/access-client) --- updated-dependencies: - dependency-name: "@web3-storage/access" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 4 ++-- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c52c0a24..e656fae4 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@types/wait-on": "^5.3.4", "@types/ws": "^8.5.13", "@typescript-eslint/typescript-estree": "^8.17.0", - "@web3-storage/access": "^20.1.0", + "@web3-storage/access": "^20.1.1", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", @@ -112,7 +112,7 @@ "@ucanto/principal": "^9.0.1", "@ucanto/transport": "^9.1.1", "@ucanto/validator": "^9.0.2", - "@web3-storage/access": "^20.1.0", + "@web3-storage/access": "^20.1.1", "@web3-storage/capabilities": "^18.0.0", "@web3-storage/clock": "^0.4.1", "@web3-storage/did-mailto": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8983b8c9..a7bfa847 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,8 +57,8 @@ importers: specifier: ^9.0.2 version: 9.0.2 '@web3-storage/access': - specifier: ^20.1.0 - version: 20.1.0 + specifier: ^20.1.1 + version: 20.1.1 '@web3-storage/capabilities': specifier: ^18.0.0 version: 18.0.0 @@ -1726,8 +1726,8 @@ packages: '@vitest/utils@2.1.8': resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} - '@web3-storage/access@20.1.0': - resolution: {integrity: sha512-IY6ICPRWE8++2jxvy+LzAiFvwAOIHR8cu9eNt+VT5sAFE796o4ma7GSU0eXRCiShmV2n6iSWAwWRT6XD5zIqPA==} + '@web3-storage/access@20.1.1': + resolution: {integrity: sha512-W2C9sn8NTWw7zIUVzEk5MtwWQLFsOREF6Ju6VK+MYcuAkQ6yVll6Q7YtB5zLPwu29xJ7KIR6e5KzbDNSXHSfrA==} '@web3-storage/blob-index@1.0.4': resolution: {integrity: sha512-04+PrmVHFT+xzRhyIPdcvGc8Y2NDffUe8R1gJOyErVzEVz5N1I9Q/BrlFHYt/A4HrjM5JBsxqSrZgTIkjfPmLA==} @@ -5855,9 +5855,9 @@ snapshots: loupe: 3.1.2 tinyrainbow: 1.2.0 - '@web3-storage/access@20.1.0': + '@web3-storage/access@20.1.1': dependencies: - '@ipld/car': 5.3.2 + '@ipld/car': 5.3.3 '@ipld/dag-ucan': 3.4.0 '@scure/bip39': 1.4.0 '@storacha/one-webcrypto': 1.0.1 @@ -5867,7 +5867,7 @@ snapshots: '@ucanto/principal': 9.0.1 '@ucanto/transport': 9.1.1 '@ucanto/validator': 9.0.2 - '@web3-storage/capabilities': 17.4.1 + '@web3-storage/capabilities': 18.0.0 '@web3-storage/did-mailto': 2.1.0 bigint-mod-arith: 3.3.1 conf: 11.0.2 @@ -5983,7 +5983,7 @@ snapshots: '@ucanto/interface': 10.0.1 '@ucanto/principal': 9.0.1 '@ucanto/transport': 9.1.1 - '@web3-storage/access': 20.1.0 + '@web3-storage/access': 20.1.1 '@web3-storage/blob-index': 1.0.4 '@web3-storage/capabilities': 17.4.1 '@web3-storage/did-mailto': 2.1.0 From ab24880aad627be2f1416d58684b4808c33e97dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:28:22 +0000 Subject: [PATCH 53/83] chore(deps-dev): bump @eslint/js from 9.16.0 to 9.17.0 Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.16.0 to 9.17.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/commits/v9.17.0/packages/js) --- updated-dependencies: - dependency-name: "@eslint/js" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index e656fae4..d5153e3a 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ ], "license": "Apache-2.0 OR MIT", "devDependencies": { - "@eslint/js": "^9.16.0", + "@eslint/js": "^9.17.0", "@smithy/types": "^3.7.2", "@types/better-sqlite3": "^7.6.12", "@types/eslint__js": "^8.42.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7bfa847..b303318d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,8 +139,8 @@ importers: version: 8.0.1 devDependencies: '@eslint/js': - specifier: ^9.16.0 - version: 9.16.0 + specifier: ^9.17.0 + version: 9.17.0 '@smithy/types': specifier: ^3.7.2 version: 3.7.2 @@ -1062,10 +1062,6 @@ packages: resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.16.0': - resolution: {integrity: sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.17.0': resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5000,8 +4996,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.16.0': {} - '@eslint/js@9.17.0': {} '@eslint/object-schema@2.1.4': {} From 01a74e8961abd5113fcf669e01ed12cc018b2faa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:29:26 +0000 Subject: [PATCH 54/83] chore(deps-dev): bump typescript-eslint from 8.17.0 to 8.18.0 Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.17.0 to 8.18.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.18.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 143 +++++++++++++++++++++++++++---------------------- 2 files changed, 80 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index d5153e3a..96339a79 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "tsup": "^8.3.5", "tsx": "^4.19.2", "typescript": "^5.7.2", - "typescript-eslint": "^8.17.0", + "typescript-eslint": "^8.18.0", "vite": "^6.0.3", "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b303318d..f8a5ade1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -193,8 +193,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 typescript-eslint: - specifier: ^8.17.0 - version: 8.17.0(eslint@9.17.0)(typescript@5.7.2) + specifier: ^8.18.0 + version: 8.18.0(eslint@9.17.0)(typescript@5.7.2) vite: specifier: ^6.0.3 version: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) @@ -1610,45 +1610,40 @@ packages: '@types/ws@8.5.13': resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@typescript-eslint/eslint-plugin@8.17.0': - resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==} + '@typescript-eslint/eslint-plugin@8.18.0': + resolution: {integrity: sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.17.0': - resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==} + '@typescript-eslint/parser@8.18.0': + resolution: {integrity: sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.17.0': - resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==} + '@typescript-eslint/scope-manager@8.18.0': + resolution: {integrity: sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.17.0': - resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==} + '@typescript-eslint/type-utils@8.18.0': + resolution: {integrity: sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/types@8.17.0': resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.18.0': + resolution: {integrity: sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.17.0': resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1658,20 +1653,27 @@ packages: typescript: optional: true - '@typescript-eslint/utils@8.17.0': - resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==} + '@typescript-eslint/typescript-estree@8.18.0': + resolution: {integrity: sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/utils@8.18.0': + resolution: {integrity: sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/visitor-keys@8.17.0': resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.18.0': + resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ucanto/client@9.0.1': resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} @@ -3774,15 +3776,12 @@ packages: type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - typescript-eslint@8.17.0: - resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} + typescript-eslint@8.18.0: + resolution: {integrity: sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' typescript@5.7.2: resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} @@ -5679,56 +5678,55 @@ snapshots: dependencies: '@types/node': 22.10.2 - '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.17.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/type-utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.17.0 + '@typescript-eslint/parser': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/type-utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.0 eslint: 9.17.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 ts-api-utils: 1.3.0(typescript@5.7.2) - optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.17.0 + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.0 debug: 4.3.7 eslint: 9.17.0 - optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.17.0': + '@typescript-eslint/scope-manager@8.18.0': dependencies: - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/visitor-keys': 8.17.0 + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/visitor-keys': 8.18.0 - '@typescript-eslint/type-utils@8.17.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.18.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) debug: 4.3.7 eslint: 9.17.0 ts-api-utils: 1.3.0(typescript@5.7.2) - optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color '@typescript-eslint/types@8.17.0': {} + '@typescript-eslint/types@8.18.0': {} + '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.17.0 @@ -5744,14 +5742,27 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.17.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/typescript-estree@8.18.0(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/visitor-keys': 8.18.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.7.2) + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.18.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.0 + '@typescript-eslint/types': 8.18.0 + '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) eslint: 9.17.0 - optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -5761,6 +5772,11 @@ snapshots: '@typescript-eslint/types': 8.17.0 eslint-visitor-keys: 4.2.0 + '@typescript-eslint/visitor-keys@8.18.0': + dependencies: + '@typescript-eslint/types': 8.18.0 + eslint-visitor-keys: 4.2.0 + '@ucanto/client@9.0.1': dependencies: '@ucanto/core': 10.0.1 @@ -8341,13 +8357,12 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.17.0(eslint@9.17.0)(typescript@5.7.2): + typescript-eslint@8.18.0(eslint@9.17.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.17.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) eslint: 9.17.0 - optionalDependencies: typescript: 5.7.2 transitivePeerDependencies: - supports-color From 452011516c7880977ca82ec958da47720d1472a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:29:10 +0000 Subject: [PATCH 55/83] chore(deps): bump @aws-sdk/client-s3 from 3.705.0 to 3.712.0 Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.705.0 to 3.712.0. - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.712.0/clients/client-s3) --- updated-dependencies: - dependency-name: "@aws-sdk/client-s3" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 1032 ++++++++++++++++++++++++------------------------ 2 files changed, 517 insertions(+), 517 deletions(-) diff --git a/package.json b/package.json index 96339a79..0f56595e 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@adviser/cement": "^0.2.41", - "@aws-sdk/client-s3": "^3.705.0", + "@aws-sdk/client-s3": "^3.712.0", "@fireproof/core": "0.19.118", "@fireproof/vendor": "1.0.0", "@jspm/core": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8a5ade1..46ccd7b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^0.2.41 version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': - specifier: ^3.705.0 - version: 3.705.0 + specifier: ^3.712.0 + version: 3.712.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) @@ -243,135 +243,135 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.705.0': - resolution: {integrity: sha512-Fm0Cbc4zr0yG0DnNycz7ywlL5tQFdLSb7xCIPfzrxJb3YQiTXWxH5eu61SSsP/Z6RBNRolmRPvst/iNgX0fWvA==} + '@aws-sdk/client-s3@3.712.0': + resolution: {integrity: sha512-Hq1IIwOFutmHtTz3mROR1XhTDL8rxcYbYw3ajjgeMJB5tjcvodpfkfz/L4dxXZMwqylWf6SNQNAiaGh5mlsGGQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/client-sso-oidc@3.699.0': - resolution: {integrity: sha512-u8a1GorY5D1l+4FQAf4XBUC1T10/t7neuwT21r0ymrtMFSK2a9QqVHKMoLkvavAwyhJnARSBM9/UQC797PFOFw==} + '@aws-sdk/client-sso-oidc@3.712.0': + resolution: {integrity: sha512-xNFrG9syrG6pxUP7Ld/nu3afQ9+rbJM9qrE+wDNz4VnNZ3vLiJty4fH85zBFhOQ5OF2DIJTWsFzXGi2FYjsCMA==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.699.0 + '@aws-sdk/client-sts': ^3.712.0 - '@aws-sdk/client-sso@3.696.0': - resolution: {integrity: sha512-q5TTkd08JS0DOkHfUL853tuArf7NrPeqoS5UOvqJho8ibV9Ak/a/HO4kNvy9Nj3cib/toHYHsQIEtecUPSUUrQ==} + '@aws-sdk/client-sso@3.712.0': + resolution: {integrity: sha512-tBo/eW3YpZ9f3Q1qA7aA8uliNFJJX0OP7R2IUJ8t6rqVTk15wWCEPNmXzUZKgruDnKUfCaF4+r9q/Yy4fBc9PA==} engines: {node: '>=16.0.0'} - '@aws-sdk/client-sts@3.699.0': - resolution: {integrity: sha512-++lsn4x2YXsZPIzFVwv3fSUVM55ZT0WRFmPeNilYIhZClxHLmVAWKH4I55cY9ry60/aTKYjzOXkWwyBKGsGvQg==} + '@aws-sdk/client-sts@3.712.0': + resolution: {integrity: sha512-gIO6BD+hkEe3GKQhbiFP0zcNQv0EkP1Cl9SOstxS+X9CeudEgVX/xEPUjyoFVkfkntPBJ1g0I1u5xOzzRExl4g==} engines: {node: '>=16.0.0'} - '@aws-sdk/core@3.696.0': - resolution: {integrity: sha512-3c9III1k03DgvRZWg8vhVmfIXPG6hAciN9MzQTzqGngzWAELZF/WONRTRQuDFixVtarQatmLHYVw/atGeA2Byw==} + '@aws-sdk/core@3.709.0': + resolution: {integrity: sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-env@3.696.0': - resolution: {integrity: sha512-T9iMFnJL7YTlESLpVFT3fg1Lkb1lD+oiaIC8KMpepb01gDUBIpj9+Y+pA/cgRWW0yRxmkDXNazAE2qQTVFGJzA==} + '@aws-sdk/credential-provider-env@3.709.0': + resolution: {integrity: sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-http@3.696.0': - resolution: {integrity: sha512-GV6EbvPi2eq1+WgY/o2RFA3P7HGmnkIzCNmhwtALFlqMroLYWKE7PSeHw66Uh1dFQeVESn0/+hiUNhu1mB0emA==} + '@aws-sdk/credential-provider-http@3.709.0': + resolution: {integrity: sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-ini@3.699.0': - resolution: {integrity: sha512-dXmCqjJnKmG37Q+nLjPVu22mNkrGHY8hYoOt3Jo9R2zr5MYV7s/NHsCHr+7E+BZ+tfZYLRPeB1wkpTeHiEcdRw==} + '@aws-sdk/credential-provider-ini@3.712.0': + resolution: {integrity: sha512-sTsdQ/Fm/suqMdpjhMuss/5uKL18vcuWnNTQVrG9iGNRqZLbq65MXquwbUpgzfoUmIcH+4CrY6H2ebpTIECIag==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.699.0 + '@aws-sdk/client-sts': ^3.712.0 - '@aws-sdk/credential-provider-node@3.699.0': - resolution: {integrity: sha512-MmEmNDo1bBtTgRmdNfdQksXu4uXe66s0p1hi1YPrn1h59Q605eq/xiWbGL6/3KdkViH6eGUuABeV2ODld86ylg==} + '@aws-sdk/credential-provider-node@3.712.0': + resolution: {integrity: sha512-gXrHymW3rMRYORkPVQwL8Gi5Lu92F16SoZR543x03qCi7rm00oL9tRD85ACxkhprS1Wh8lUIUMNoeiwnYWTNuQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-process@3.696.0': - resolution: {integrity: sha512-mL1RcFDe9sfmyU5K1nuFkO8UiJXXxLX4JO1gVaDIOvPqwStpUAwi3A1BoeZhWZZNQsiKI810RnYGo0E0WB/hUA==} + '@aws-sdk/credential-provider-process@3.709.0': + resolution: {integrity: sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-sso@3.699.0': - resolution: {integrity: sha512-Ekp2cZG4pl9D8+uKWm4qO1xcm8/MeiI8f+dnlZm8aQzizeC+aXYy9GyoclSf6daK8KfRPiRfM7ZHBBL5dAfdMA==} + '@aws-sdk/credential-provider-sso@3.712.0': + resolution: {integrity: sha512-8lCMxY7Lb9VK9qdlNXRJXE3W1UDVURnJZ3a4XWYNY6yr1TfQaN40mMyXX1oNlXXJtMV0szRvjM8dZj37E/ESAw==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-web-identity@3.696.0': - resolution: {integrity: sha512-XJ/CVlWChM0VCoc259vWguFUjJDn/QwDqHwbx+K9cg3v6yrqXfK5ai+p/6lx0nQpnk4JzPVeYYxWRpaTsGC9rg==} + '@aws-sdk/credential-provider-web-identity@3.709.0': + resolution: {integrity: sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.696.0 + '@aws-sdk/client-sts': ^3.709.0 - '@aws-sdk/middleware-bucket-endpoint@3.696.0': - resolution: {integrity: sha512-V07jishKHUS5heRNGFpCWCSTjRJyQLynS/ncUeE8ZYtG66StOOQWftTwDfFOSoXlIqrXgb4oT9atryzXq7Z4LQ==} + '@aws-sdk/middleware-bucket-endpoint@3.709.0': + resolution: {integrity: sha512-03+tJOd7KIZOiqWH7Z8BOfQIWkKJgjcpKOJKZ6FR2KjWGUOE1G+bo11wF4UuHQ0RmpKnApt+pQghZmSnE7WEeg==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-expect-continue@3.696.0': - resolution: {integrity: sha512-vpVukqY3U2pb+ULeX0shs6L0aadNep6kKzjme/MyulPjtUDJpD3AekHsXRrCCGLmOqSKqRgQn5zhV9pQhHsb6Q==} + '@aws-sdk/middleware-expect-continue@3.709.0': + resolution: {integrity: sha512-Tbl/DFvE4rHl8lMb9IzetwK4tf5R3VeHZkvEXQalsWoK0tbEQ8kXWi7wAYO4qbE7bFVvaxKX+irjJjTxf3BrCQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.701.0': - resolution: {integrity: sha512-adNaPCyTT+CiVM0ufDiO1Fe7nlRmJdI9Hcgj0M9S6zR7Dw70Ra5z8Lslkd7syAccYvZaqxLklGjPQH/7GNxwTA==} + '@aws-sdk/middleware-flexible-checksums@3.709.0': + resolution: {integrity: sha512-wbYm9tkyCaqMeU82yjaXw7V5BxCSlSLNupENW63LC7Fvyo/aQzj6LjSMHcBpR2QwjBEhXCtF47L7aQ8SPTNhdw==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-host-header@3.696.0': - resolution: {integrity: sha512-zELJp9Ta2zkX7ELggMN9qMCgekqZhFC5V2rOr4hJDEb/Tte7gpfKSObAnw/3AYiVqt36sjHKfdkoTsuwGdEoDg==} + '@aws-sdk/middleware-host-header@3.709.0': + resolution: {integrity: sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-location-constraint@3.696.0': - resolution: {integrity: sha512-FgH12OB0q+DtTrP2aiDBddDKwL4BPOrm7w3VV9BJrSdkqQCNBPz8S1lb0y5eVH4tBG+2j7gKPlOv1wde4jF/iw==} + '@aws-sdk/middleware-location-constraint@3.709.0': + resolution: {integrity: sha512-5YQWPXfZq7OE0jB2G0PP8K10GBod/YPJXb+1CfJS6FbQaglRoIm8KZmVEvJNnptSKyGtE62veeCcCQcfAUfFig==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-logger@3.696.0': - resolution: {integrity: sha512-KhkHt+8AjCxcR/5Zp3++YPJPpFQzxpr+jmONiT/Jw2yqnSngZ0Yspm5wGoRx2hS1HJbyZNuaOWEGuJoxLeBKfA==} + '@aws-sdk/middleware-logger@3.709.0': + resolution: {integrity: sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-recursion-detection@3.696.0': - resolution: {integrity: sha512-si/maV3Z0hH7qa99f9ru2xpS5HlfSVcasRlNUXKSDm611i7jFMWwGNLUOXFAOLhXotPX5G3Z6BLwL34oDeBMug==} + '@aws-sdk/middleware-recursion-detection@3.709.0': + resolution: {integrity: sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-sdk-s3@3.696.0': - resolution: {integrity: sha512-M7fEiAiN7DBMHflzOFzh1I2MNSlLpbiH2ubs87bdRc2wZsDPSbs4l3v6h3WLhxoQK0bq6vcfroudrLBgvCuX3Q==} + '@aws-sdk/middleware-sdk-s3@3.709.0': + resolution: {integrity: sha512-FwtOG9t9xsLoLOQZ6qAdsWOjx9dsO6t28IjIDV1l6Ixiu2oC0Yks7goONjJUH0IDE4pDDDGzmuq0sn1XtHhheA==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-ssec@3.696.0': - resolution: {integrity: sha512-w/d6O7AOZ7Pg3w2d3BxnX5RmGNWb5X4RNxF19rJqcgu/xqxxE/QwZTNd5a7eTsqLXAUIfbbR8hh0czVfC1pJLA==} + '@aws-sdk/middleware-ssec@3.709.0': + resolution: {integrity: sha512-2muiLe7YkmlwZp2SKz+goZrDThGfRq3o0FcJF3Puc0XGmcEPEDjih537mCoTrGgcXNFlBc7YChd84r3t72ySaQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-user-agent@3.696.0': - resolution: {integrity: sha512-Lvyj8CTyxrHI6GHd2YVZKIRI5Fmnugt3cpJo0VrKKEgK5zMySwEZ1n4dqPK6czYRWKd5+WnYHYAuU+Wdk6Jsjw==} + '@aws-sdk/middleware-user-agent@3.709.0': + resolution: {integrity: sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw==} engines: {node: '>=16.0.0'} - '@aws-sdk/region-config-resolver@3.696.0': - resolution: {integrity: sha512-7EuH142lBXjI8yH6dVS/CZeiK/WZsmb/8zP6bQbVYpMrppSTgB3MzZZdxVZGzL5r8zPQOU10wLC4kIMy0qdBVQ==} + '@aws-sdk/region-config-resolver@3.709.0': + resolution: {integrity: sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w==} engines: {node: '>=16.0.0'} - '@aws-sdk/signature-v4-multi-region@3.696.0': - resolution: {integrity: sha512-ijPkoLjXuPtgxAYlDoYls8UaG/VKigROn9ebbvPL/orEY5umedd3iZTcS9T+uAf4Ur3GELLxMQiERZpfDKaz3g==} + '@aws-sdk/signature-v4-multi-region@3.709.0': + resolution: {integrity: sha512-m0vhJEy6SLbjL11K9cHzX/ZhCIj//1GkTbYk2d4tTQFSuPyJEkjmoeHk9dYm2mJy0wH48j29OJadI1JUsR5bOw==} engines: {node: '>=16.0.0'} - '@aws-sdk/token-providers@3.699.0': - resolution: {integrity: sha512-kuiEW9DWs7fNos/SM+y58HCPhcIzm1nEZLhe2/7/6+TvAYLuEWURYsbK48gzsxXlaJ2k/jGY3nIsA7RptbMOwA==} + '@aws-sdk/token-providers@3.709.0': + resolution: {integrity: sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sso-oidc': ^3.699.0 + '@aws-sdk/client-sso-oidc': ^3.709.0 - '@aws-sdk/types@3.696.0': - resolution: {integrity: sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw==} + '@aws-sdk/types@3.709.0': + resolution: {integrity: sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg==} engines: {node: '>=16.0.0'} '@aws-sdk/util-arn-parser@3.693.0': resolution: {integrity: sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/util-endpoints@3.696.0': - resolution: {integrity: sha512-T5s0IlBVX+gkb9g/I6CLt4yAZVzMSiGnbUqWihWsHvQR1WOoIcndQy/Oz/IJXT9T2ipoy7a80gzV6a5mglrioA==} + '@aws-sdk/util-endpoints@3.709.0': + resolution: {integrity: sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q==} engines: {node: '>=16.0.0'} '@aws-sdk/util-locate-window@3.568.0': resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} engines: {node: '>=16.0.0'} - '@aws-sdk/util-user-agent-browser@3.696.0': - resolution: {integrity: sha512-Z5rVNDdmPOe6ELoM5AhF/ja5tSjbe6ctSctDPb0JdDf4dT0v2MfwhJKzXju2RzX8Es/77Glh7MlaXLE0kCB9+Q==} + '@aws-sdk/util-user-agent-browser@3.709.0': + resolution: {integrity: sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg==} - '@aws-sdk/util-user-agent-node@3.696.0': - resolution: {integrity: sha512-KhKqcfyXIB0SCCt+qsu4eJjsfiOrNzK5dCV7RAW2YIpp+msxGUUX0NdRE9rkzjiv+3EMktgJm3eEIS+yxtlVdQ==} + '@aws-sdk/util-user-agent-node@3.712.0': + resolution: {integrity: sha512-26X21bZ4FWsVpqs33uOXiB60TOWQdVlr7T7XONDFL/XN7GEpUJkWuuIB4PTok6VOmh1viYcdxZQqekXPuzXexQ==} engines: {node: '>=16.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -379,8 +379,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.696.0': - resolution: {integrity: sha512-dn1mX+EeqivoLYnY7p2qLrir0waPnCgS/0YdRCAVU2x14FgfUYCH6Im3w3oi2dMwhxfKY5lYVB5NKvZu7uI9lQ==} + '@aws-sdk/xml-builder@3.709.0': + resolution: {integrity: sha512-2GPCwlNxeHspoK/Mc8nbk9cBOkSpp3j2SJUQmFnyQK6V/pR6II2oPRyZkMomug1Rc10hqlBHByMecq4zhV2uUw==} engines: {node: '>=16.0.0'} '@cloudflare/kv-asset-handler@0.3.4': @@ -1362,8 +1362,8 @@ packages: '@sideway/pinpoint@2.0.0': resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - '@smithy/abort-controller@3.1.8': - resolution: {integrity: sha512-+3DOBcUn5/rVjlxGvUPKc416SExarAQ+Qe0bqk30YSUjbepwpS7QN0cyKUSifvLJhdMZ0WPzPP5ymut0oonrpQ==} + '@smithy/abort-controller@3.1.9': + resolution: {integrity: sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==} engines: {node: '>=16.0.0'} '@smithy/chunked-blob-reader-native@3.0.1': @@ -1372,53 +1372,53 @@ packages: '@smithy/chunked-blob-reader@4.0.0': resolution: {integrity: sha512-jSqRnZvkT4egkq/7b6/QRCNXmmYVcHwnJldqJ3IhVpQE2atObVJ137xmGeuGFhjFUr8gCEVAOKwSY79OvpbDaQ==} - '@smithy/config-resolver@3.0.12': - resolution: {integrity: sha512-YAJP9UJFZRZ8N+UruTeq78zkdjUHmzsY62J4qKWZ4SXB4QXJ/+680EfXXgkYA2xj77ooMqtUY9m406zGNqwivQ==} + '@smithy/config-resolver@3.0.13': + resolution: {integrity: sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==} engines: {node: '>=16.0.0'} - '@smithy/core@2.5.3': - resolution: {integrity: sha512-96uW8maifUSmehaeW7uydWn7wBc98NEeNI3zN8vqakGpyCQgzyJaA64Z4FCOUmAdCJkhppd/7SZ798Fo4Xx37g==} + '@smithy/core@2.5.5': + resolution: {integrity: sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==} engines: {node: '>=16.0.0'} - '@smithy/credential-provider-imds@3.2.7': - resolution: {integrity: sha512-cEfbau+rrWF8ylkmmVAObOmjbTIzKyUC5TkBL58SbLywD0RCBC4JAUKbmtSm2w5KUJNRPGgpGFMvE2FKnuNlWQ==} + '@smithy/credential-provider-imds@3.2.8': + resolution: {integrity: sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==} engines: {node: '>=16.0.0'} - '@smithy/eventstream-codec@3.1.9': - resolution: {integrity: sha512-F574nX0hhlNOjBnP+noLtsPFqXnWh2L0+nZKCwcu7P7J8k+k+rdIDs+RMnrMwrzhUE4mwMgyN0cYnEn0G8yrnQ==} + '@smithy/eventstream-codec@3.1.10': + resolution: {integrity: sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ==} - '@smithy/eventstream-serde-browser@3.0.13': - resolution: {integrity: sha512-Nee9m+97o9Qj6/XeLz2g2vANS2SZgAxV4rDBMKGHvFJHU/xz88x2RwCkwsvEwYjSX4BV1NG1JXmxEaDUzZTAtw==} + '@smithy/eventstream-serde-browser@3.0.14': + resolution: {integrity: sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg==} engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-config-resolver@3.0.10': - resolution: {integrity: sha512-K1M0x7P7qbBUKB0UWIL5KOcyi6zqV5mPJoL0/o01HPJr0CSq3A9FYuJC6e11EX6hR8QTIR++DBiGrYveOu6trw==} + '@smithy/eventstream-serde-config-resolver@3.0.11': + resolution: {integrity: sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ==} engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-node@3.0.12': - resolution: {integrity: sha512-kiZymxXvZ4tnuYsPSMUHe+MMfc4FTeFWJIc0Q5wygJoUQM4rVHNghvd48y7ppuulNMbuYt95ah71pYc2+o4JOA==} + '@smithy/eventstream-serde-node@3.0.13': + resolution: {integrity: sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ==} engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-universal@3.0.12': - resolution: {integrity: sha512-1i8ifhLJrOZ+pEifTlF0EfZzMLUGQggYQ6WmZ4d5g77zEKf7oZ0kvh1yKWHPjofvOwqrkwRDVuxuYC8wVd662A==} + '@smithy/eventstream-serde-universal@3.0.13': + resolution: {integrity: sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw==} engines: {node: '>=16.0.0'} - '@smithy/fetch-http-handler@4.1.1': - resolution: {integrity: sha512-bH7QW0+JdX0bPBadXt8GwMof/jz0H28I84hU1Uet9ISpzUqXqRQ3fEZJ+ANPOhzSEczYvANNl3uDQDYArSFDtA==} + '@smithy/fetch-http-handler@4.1.2': + resolution: {integrity: sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==} - '@smithy/hash-blob-browser@3.1.9': - resolution: {integrity: sha512-wOu78omaUuW5DE+PVWXiRKWRZLecARyP3xcq5SmkXUw9+utgN8HnSnBfrjL2B/4ZxgqPjaAJQkC/+JHf1ITVaQ==} + '@smithy/hash-blob-browser@3.1.10': + resolution: {integrity: sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA==} - '@smithy/hash-node@3.0.10': - resolution: {integrity: sha512-3zWGWCHI+FlJ5WJwx73Mw2llYR8aflVyZN5JhoqLxbdPZi6UyKSdCeXAWJw9ja22m6S6Tzz1KZ+kAaSwvydi0g==} + '@smithy/hash-node@3.0.11': + resolution: {integrity: sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==} engines: {node: '>=16.0.0'} - '@smithy/hash-stream-node@3.1.9': - resolution: {integrity: sha512-3XfHBjSP3oDWxLmlxnt+F+FqXpL3WlXs+XXaB6bV9Wo8BBu87fK1dSEsyH7Z4ZHRmwZ4g9lFMdf08m9hoX1iRA==} + '@smithy/hash-stream-node@3.1.10': + resolution: {integrity: sha512-olomK/jZQ93OMayW1zfTHwcbwBdhcZOHsyWyiZ9h9IXvc1mCD/VuvzbLb3Gy/qNJwI4MANPLctTp2BucV2oU/Q==} engines: {node: '>=16.0.0'} - '@smithy/invalid-dependency@3.0.10': - resolution: {integrity: sha512-Lp2L65vFi+cj0vFMu2obpPW69DU+6O5g3086lmI4XcnRCG8PxvpWC7XyaVwJCxsZFzueHjXnrOH/E0pl0zikfA==} + '@smithy/invalid-dependency@3.0.11': + resolution: {integrity: sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==} '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} @@ -1428,75 +1428,75 @@ packages: resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} engines: {node: '>=16.0.0'} - '@smithy/md5-js@3.0.10': - resolution: {integrity: sha512-m3bv6dApflt3fS2Y1PyWPUtRP7iuBlvikEOGwu0HsCZ0vE7zcIX+dBoh3e+31/rddagw8nj92j0kJg2TfV+SJA==} + '@smithy/md5-js@3.0.11': + resolution: {integrity: sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ==} - '@smithy/middleware-content-length@3.0.12': - resolution: {integrity: sha512-1mDEXqzM20yywaMDuf5o9ue8OkJ373lSPbaSjyEvkWdqELhFMyNNgKGWL/rCSf4KME8B+HlHKuR8u9kRj8HzEQ==} + '@smithy/middleware-content-length@3.0.13': + resolution: {integrity: sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-endpoint@3.2.3': - resolution: {integrity: sha512-Hdl9296i/EMptaX7agrSzJZDiz5Y8XPUeBbctTmMtnCguGpqfU3jVsTUan0VLaOhsnquqWLL8Bl5HrlbVGT1og==} + '@smithy/middleware-endpoint@3.2.5': + resolution: {integrity: sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==} engines: {node: '>=16.0.0'} - '@smithy/middleware-retry@3.0.27': - resolution: {integrity: sha512-H3J/PjJpLL7Tt+fxDKiOD25sMc94YetlQhCnYeNmina2LZscAdu0ZEZPas/kwePHABaEtqp7hqa5S4UJgMs1Tg==} + '@smithy/middleware-retry@3.0.30': + resolution: {integrity: sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==} engines: {node: '>=16.0.0'} - '@smithy/middleware-serde@3.0.10': - resolution: {integrity: sha512-MnAuhh+dD14F428ubSJuRnmRsfOpxSzvRhaGVTvd/lrUDE3kxzCCmH8lnVTvoNQnV2BbJ4c15QwZ3UdQBtFNZA==} + '@smithy/middleware-serde@3.0.11': + resolution: {integrity: sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-stack@3.0.10': - resolution: {integrity: sha512-grCHyoiARDBBGPyw2BeicpjgpsDFWZZxptbVKb3CRd/ZA15F/T6rZjCCuBUjJwdck1nwUuIxYtsS4H9DDpbP5w==} + '@smithy/middleware-stack@3.0.11': + resolution: {integrity: sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==} engines: {node: '>=16.0.0'} - '@smithy/node-config-provider@3.1.11': - resolution: {integrity: sha512-URq3gT3RpDikh/8MBJUB+QGZzfS7Bm6TQTqoh4CqE8NBuyPkWa5eUXj0XFcFfeZVgg3WMh1u19iaXn8FvvXxZw==} + '@smithy/node-config-provider@3.1.12': + resolution: {integrity: sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==} engines: {node: '>=16.0.0'} - '@smithy/node-http-handler@3.3.1': - resolution: {integrity: sha512-fr+UAOMGWh6bn4YSEezBCpJn9Ukp9oR4D32sCjCo7U81evE11YePOQ58ogzyfgmjIO79YeOdfXXqr0jyhPQeMg==} + '@smithy/node-http-handler@3.3.2': + resolution: {integrity: sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==} engines: {node: '>=16.0.0'} - '@smithy/property-provider@3.1.10': - resolution: {integrity: sha512-n1MJZGTorTH2DvyTVj+3wXnd4CzjJxyXeOgnTlgNVFxaaMeT4OteEp4QrzF8p9ee2yg42nvyVK6R/awLCakjeQ==} + '@smithy/property-provider@3.1.11': + resolution: {integrity: sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==} engines: {node: '>=16.0.0'} - '@smithy/protocol-http@4.1.7': - resolution: {integrity: sha512-FP2LepWD0eJeOTm0SjssPcgqAlDFzOmRXqXmGhfIM52G7Lrox/pcpQf6RP4F21k0+O12zaqQt5fCDOeBtqY6Cg==} + '@smithy/protocol-http@4.1.8': + resolution: {integrity: sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==} engines: {node: '>=16.0.0'} - '@smithy/querystring-builder@3.0.10': - resolution: {integrity: sha512-nT9CQF3EIJtIUepXQuBFb8dxJi3WVZS3XfuDksxSCSn+/CzZowRLdhDn+2acbBv8R6eaJqPupoI/aRFIImNVPQ==} + '@smithy/querystring-builder@3.0.11': + resolution: {integrity: sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==} engines: {node: '>=16.0.0'} - '@smithy/querystring-parser@3.0.10': - resolution: {integrity: sha512-Oa0XDcpo9SmjhiDD9ua2UyM3uU01ZTuIrNdZvzwUTykW1PM8o2yJvMh1Do1rY5sUQg4NDV70dMi0JhDx4GyxuQ==} + '@smithy/querystring-parser@3.0.11': + resolution: {integrity: sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==} engines: {node: '>=16.0.0'} - '@smithy/service-error-classification@3.0.10': - resolution: {integrity: sha512-zHe642KCqDxXLuhs6xmHVgRwy078RfqxP2wRDpIyiF8EmsWXptMwnMwbVa50lw+WOGNrYm9zbaEg0oDe3PTtvQ==} + '@smithy/service-error-classification@3.0.11': + resolution: {integrity: sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==} engines: {node: '>=16.0.0'} - '@smithy/shared-ini-file-loader@3.1.11': - resolution: {integrity: sha512-AUdrIZHFtUgmfSN4Gq9nHu3IkHMa1YDcN+s061Nfm+6pQ0mJy85YQDB0tZBCmls0Vuj22pLwDPmL92+Hvfwwlg==} + '@smithy/shared-ini-file-loader@3.1.12': + resolution: {integrity: sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==} engines: {node: '>=16.0.0'} - '@smithy/signature-v4@4.2.3': - resolution: {integrity: sha512-pPSQQ2v2vu9vc8iew7sszLd0O09I5TRc5zhY71KA+Ao0xYazIG+uLeHbTJfIWGO3BGVLiXjUr3EEeCcEQLjpWQ==} + '@smithy/signature-v4@4.2.4': + resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} - '@smithy/smithy-client@3.4.4': - resolution: {integrity: sha512-dPGoJuSZqvirBq+yROapBcHHvFjChoAQT8YPWJ820aPHHiowBlB3RL1Q4kPT1hx0qKgJuf+HhyzKi5Gbof4fNA==} + '@smithy/smithy-client@3.5.0': + resolution: {integrity: sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==} engines: {node: '>=16.0.0'} '@smithy/types@3.7.2': resolution: {integrity: sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==} engines: {node: '>=16.0.0'} - '@smithy/url-parser@3.0.10': - resolution: {integrity: sha512-j90NUalTSBR2NaZTuruEgavSdh8MLirf58LoGSk4AtQfyIymogIhgnGUU2Mga2bkMkpSoC9gxb74xBXL5afKAQ==} + '@smithy/url-parser@3.0.11': + resolution: {integrity: sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==} '@smithy/util-base64@3.0.0': resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} @@ -1521,32 +1521,32 @@ packages: resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} engines: {node: '>=16.0.0'} - '@smithy/util-defaults-mode-browser@3.0.27': - resolution: {integrity: sha512-GV8NvPy1vAGp7u5iD/xNKUxCorE4nQzlyl057qRac+KwpH5zq8wVq6rE3lPPeuFLyQXofPN6JwxL1N9ojGapiQ==} + '@smithy/util-defaults-mode-browser@3.0.30': + resolution: {integrity: sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==} engines: {node: '>= 10.0.0'} - '@smithy/util-defaults-mode-node@3.0.27': - resolution: {integrity: sha512-7+4wjWfZqZxZVJvDutO+i1GvL6bgOajEkop4FuR6wudFlqBiqwxw3HoH6M9NgeCd37km8ga8NPp2JacQEtAMPg==} + '@smithy/util-defaults-mode-node@3.0.30': + resolution: {integrity: sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==} engines: {node: '>= 10.0.0'} - '@smithy/util-endpoints@2.1.6': - resolution: {integrity: sha512-mFV1t3ndBh0yZOJgWxO9J/4cHZVn5UG1D8DeCc6/echfNkeEJWu9LD7mgGH5fHrEdR7LDoWw7PQO6QiGpHXhgA==} + '@smithy/util-endpoints@2.1.7': + resolution: {integrity: sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==} engines: {node: '>=16.0.0'} '@smithy/util-hex-encoding@3.0.0': resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} engines: {node: '>=16.0.0'} - '@smithy/util-middleware@3.0.10': - resolution: {integrity: sha512-eJO+/+RsrG2RpmY68jZdwQtnfsxjmPxzMlQpnHKjFPwrYqvlcT+fHdT+ZVwcjlWSrByOhGr9Ff2GG17efc192A==} + '@smithy/util-middleware@3.0.11': + resolution: {integrity: sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==} engines: {node: '>=16.0.0'} - '@smithy/util-retry@3.0.10': - resolution: {integrity: sha512-1l4qatFp4PiU6j7UsbasUHL2VU023NRB/gfaa1M0rDqVrRN4g3mCArLRyH3OuktApA4ye+yjWQHjdziunw2eWA==} + '@smithy/util-retry@3.0.11': + resolution: {integrity: sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==} engines: {node: '>=16.0.0'} - '@smithy/util-stream@3.3.1': - resolution: {integrity: sha512-Ff68R5lJh2zj+AUTvbAU/4yx+6QPRzg7+pI7M1FbtQHcRIp7xvguxVsQBKyB3fwiOwhAKu0lnNyYBaQfSW6TNw==} + '@smithy/util-stream@3.3.2': + resolution: {integrity: sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==} engines: {node: '>=16.0.0'} '@smithy/util-uri-escape@3.0.0': @@ -1561,8 +1561,8 @@ packages: resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} engines: {node: '>=16.0.0'} - '@smithy/util-waiter@3.1.9': - resolution: {integrity: sha512-/aMXPANhMOlMPjfPtSrDfPeVP8l56SJlz93xeiLmhLe5xvlXA5T3abZ2ilEsDEPeY9T/wnN/vNGn9wa1SbufWA==} + '@smithy/util-waiter@3.2.0': + resolution: {integrity: sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==} engines: {node: '>=16.0.0'} '@storacha/one-webcrypto@1.0.1': @@ -4100,20 +4100,20 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4123,7 +4123,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4131,7 +4131,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -4140,272 +4140,272 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.705.0': + '@aws-sdk/client-s3@3.712.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/client-sts': 3.699.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/middleware-bucket-endpoint': 3.696.0 - '@aws-sdk/middleware-expect-continue': 3.696.0 - '@aws-sdk/middleware-flexible-checksums': 3.701.0 - '@aws-sdk/middleware-host-header': 3.696.0 - '@aws-sdk/middleware-location-constraint': 3.696.0 - '@aws-sdk/middleware-logger': 3.696.0 - '@aws-sdk/middleware-recursion-detection': 3.696.0 - '@aws-sdk/middleware-sdk-s3': 3.696.0 - '@aws-sdk/middleware-ssec': 3.696.0 - '@aws-sdk/middleware-user-agent': 3.696.0 - '@aws-sdk/region-config-resolver': 3.696.0 - '@aws-sdk/signature-v4-multi-region': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-endpoints': 3.696.0 - '@aws-sdk/util-user-agent-browser': 3.696.0 - '@aws-sdk/util-user-agent-node': 3.696.0 - '@aws-sdk/xml-builder': 3.696.0 - '@smithy/config-resolver': 3.0.12 - '@smithy/core': 2.5.3 - '@smithy/eventstream-serde-browser': 3.0.13 - '@smithy/eventstream-serde-config-resolver': 3.0.10 - '@smithy/eventstream-serde-node': 3.0.12 - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/hash-blob-browser': 3.1.9 - '@smithy/hash-node': 3.0.10 - '@smithy/hash-stream-node': 3.1.9 - '@smithy/invalid-dependency': 3.0.10 - '@smithy/md5-js': 3.0.10 - '@smithy/middleware-content-length': 3.0.12 - '@smithy/middleware-endpoint': 3.2.3 - '@smithy/middleware-retry': 3.0.27 - '@smithy/middleware-serde': 3.0.10 - '@smithy/middleware-stack': 3.0.10 - '@smithy/node-config-provider': 3.1.11 - '@smithy/node-http-handler': 3.3.1 - '@smithy/protocol-http': 4.1.7 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/client-sts': 3.712.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/middleware-bucket-endpoint': 3.709.0 + '@aws-sdk/middleware-expect-continue': 3.709.0 + '@aws-sdk/middleware-flexible-checksums': 3.709.0 + '@aws-sdk/middleware-host-header': 3.709.0 + '@aws-sdk/middleware-location-constraint': 3.709.0 + '@aws-sdk/middleware-logger': 3.709.0 + '@aws-sdk/middleware-recursion-detection': 3.709.0 + '@aws-sdk/middleware-sdk-s3': 3.709.0 + '@aws-sdk/middleware-ssec': 3.709.0 + '@aws-sdk/middleware-user-agent': 3.709.0 + '@aws-sdk/region-config-resolver': 3.709.0 + '@aws-sdk/signature-v4-multi-region': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@aws-sdk/util-endpoints': 3.709.0 + '@aws-sdk/util-user-agent-browser': 3.709.0 + '@aws-sdk/util-user-agent-node': 3.712.0 + '@aws-sdk/xml-builder': 3.709.0 + '@smithy/config-resolver': 3.0.13 + '@smithy/core': 2.5.5 + '@smithy/eventstream-serde-browser': 3.0.14 + '@smithy/eventstream-serde-config-resolver': 3.0.11 + '@smithy/eventstream-serde-node': 3.0.13 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/hash-blob-browser': 3.1.10 + '@smithy/hash-node': 3.0.11 + '@smithy/hash-stream-node': 3.1.10 + '@smithy/invalid-dependency': 3.0.11 + '@smithy/md5-js': 3.0.11 + '@smithy/middleware-content-length': 3.0.13 + '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-serde': 3.0.11 + '@smithy/middleware-stack': 3.0.11 + '@smithy/node-config-provider': 3.1.12 + '@smithy/node-http-handler': 3.3.2 + '@smithy/protocol-http': 4.1.8 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 + '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.27 - '@smithy/util-defaults-mode-node': 3.0.27 - '@smithy/util-endpoints': 2.1.6 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-retry': 3.0.10 - '@smithy/util-stream': 3.3.1 + '@smithy/util-defaults-mode-browser': 3.0.30 + '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-endpoints': 2.1.7 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-retry': 3.0.11 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 - '@smithy/util-waiter': 3.1.9 + '@smithy/util-waiter': 3.2.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)': + '@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sts': 3.699.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/middleware-host-header': 3.696.0 - '@aws-sdk/middleware-logger': 3.696.0 - '@aws-sdk/middleware-recursion-detection': 3.696.0 - '@aws-sdk/middleware-user-agent': 3.696.0 - '@aws-sdk/region-config-resolver': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-endpoints': 3.696.0 - '@aws-sdk/util-user-agent-browser': 3.696.0 - '@aws-sdk/util-user-agent-node': 3.696.0 - '@smithy/config-resolver': 3.0.12 - '@smithy/core': 2.5.3 - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/hash-node': 3.0.10 - '@smithy/invalid-dependency': 3.0.10 - '@smithy/middleware-content-length': 3.0.12 - '@smithy/middleware-endpoint': 3.2.3 - '@smithy/middleware-retry': 3.0.27 - '@smithy/middleware-serde': 3.0.10 - '@smithy/middleware-stack': 3.0.10 - '@smithy/node-config-provider': 3.1.11 - '@smithy/node-http-handler': 3.3.1 - '@smithy/protocol-http': 4.1.7 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/client-sts': 3.712.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/middleware-host-header': 3.709.0 + '@aws-sdk/middleware-logger': 3.709.0 + '@aws-sdk/middleware-recursion-detection': 3.709.0 + '@aws-sdk/middleware-user-agent': 3.709.0 + '@aws-sdk/region-config-resolver': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@aws-sdk/util-endpoints': 3.709.0 + '@aws-sdk/util-user-agent-browser': 3.709.0 + '@aws-sdk/util-user-agent-node': 3.712.0 + '@smithy/config-resolver': 3.0.13 + '@smithy/core': 2.5.5 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/hash-node': 3.0.11 + '@smithy/invalid-dependency': 3.0.11 + '@smithy/middleware-content-length': 3.0.13 + '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-serde': 3.0.11 + '@smithy/middleware-stack': 3.0.11 + '@smithy/node-config-provider': 3.1.12 + '@smithy/node-http-handler': 3.3.2 + '@smithy/protocol-http': 4.1.8 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 + '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.27 - '@smithy/util-defaults-mode-node': 3.0.27 - '@smithy/util-endpoints': 2.1.6 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-retry': 3.0.10 + '@smithy/util-defaults-mode-browser': 3.0.30 + '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-endpoints': 2.1.7 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-retry': 3.0.11 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.696.0': + '@aws-sdk/client-sso@3.712.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/middleware-host-header': 3.696.0 - '@aws-sdk/middleware-logger': 3.696.0 - '@aws-sdk/middleware-recursion-detection': 3.696.0 - '@aws-sdk/middleware-user-agent': 3.696.0 - '@aws-sdk/region-config-resolver': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-endpoints': 3.696.0 - '@aws-sdk/util-user-agent-browser': 3.696.0 - '@aws-sdk/util-user-agent-node': 3.696.0 - '@smithy/config-resolver': 3.0.12 - '@smithy/core': 2.5.3 - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/hash-node': 3.0.10 - '@smithy/invalid-dependency': 3.0.10 - '@smithy/middleware-content-length': 3.0.12 - '@smithy/middleware-endpoint': 3.2.3 - '@smithy/middleware-retry': 3.0.27 - '@smithy/middleware-serde': 3.0.10 - '@smithy/middleware-stack': 3.0.10 - '@smithy/node-config-provider': 3.1.11 - '@smithy/node-http-handler': 3.3.1 - '@smithy/protocol-http': 4.1.7 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/middleware-host-header': 3.709.0 + '@aws-sdk/middleware-logger': 3.709.0 + '@aws-sdk/middleware-recursion-detection': 3.709.0 + '@aws-sdk/middleware-user-agent': 3.709.0 + '@aws-sdk/region-config-resolver': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@aws-sdk/util-endpoints': 3.709.0 + '@aws-sdk/util-user-agent-browser': 3.709.0 + '@aws-sdk/util-user-agent-node': 3.712.0 + '@smithy/config-resolver': 3.0.13 + '@smithy/core': 2.5.5 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/hash-node': 3.0.11 + '@smithy/invalid-dependency': 3.0.11 + '@smithy/middleware-content-length': 3.0.13 + '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-serde': 3.0.11 + '@smithy/middleware-stack': 3.0.11 + '@smithy/node-config-provider': 3.1.12 + '@smithy/node-http-handler': 3.3.2 + '@smithy/protocol-http': 4.1.8 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 + '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.27 - '@smithy/util-defaults-mode-node': 3.0.27 - '@smithy/util-endpoints': 2.1.6 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-retry': 3.0.10 + '@smithy/util-defaults-mode-browser': 3.0.30 + '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-endpoints': 2.1.7 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-retry': 3.0.11 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sts@3.699.0': + '@aws-sdk/client-sts@3.712.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/core': 3.696.0 - '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/middleware-host-header': 3.696.0 - '@aws-sdk/middleware-logger': 3.696.0 - '@aws-sdk/middleware-recursion-detection': 3.696.0 - '@aws-sdk/middleware-user-agent': 3.696.0 - '@aws-sdk/region-config-resolver': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-endpoints': 3.696.0 - '@aws-sdk/util-user-agent-browser': 3.696.0 - '@aws-sdk/util-user-agent-node': 3.696.0 - '@smithy/config-resolver': 3.0.12 - '@smithy/core': 2.5.3 - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/hash-node': 3.0.10 - '@smithy/invalid-dependency': 3.0.10 - '@smithy/middleware-content-length': 3.0.12 - '@smithy/middleware-endpoint': 3.2.3 - '@smithy/middleware-retry': 3.0.27 - '@smithy/middleware-serde': 3.0.10 - '@smithy/middleware-stack': 3.0.10 - '@smithy/node-config-provider': 3.1.11 - '@smithy/node-http-handler': 3.3.1 - '@smithy/protocol-http': 4.1.7 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/core': 3.709.0 + '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/middleware-host-header': 3.709.0 + '@aws-sdk/middleware-logger': 3.709.0 + '@aws-sdk/middleware-recursion-detection': 3.709.0 + '@aws-sdk/middleware-user-agent': 3.709.0 + '@aws-sdk/region-config-resolver': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@aws-sdk/util-endpoints': 3.709.0 + '@aws-sdk/util-user-agent-browser': 3.709.0 + '@aws-sdk/util-user-agent-node': 3.712.0 + '@smithy/config-resolver': 3.0.13 + '@smithy/core': 2.5.5 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/hash-node': 3.0.11 + '@smithy/invalid-dependency': 3.0.11 + '@smithy/middleware-content-length': 3.0.13 + '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-serde': 3.0.11 + '@smithy/middleware-stack': 3.0.11 + '@smithy/node-config-provider': 3.1.12 + '@smithy/node-http-handler': 3.3.2 + '@smithy/protocol-http': 4.1.8 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 + '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.27 - '@smithy/util-defaults-mode-node': 3.0.27 - '@smithy/util-endpoints': 2.1.6 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-retry': 3.0.10 + '@smithy/util-defaults-mode-browser': 3.0.30 + '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-endpoints': 2.1.7 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-retry': 3.0.11 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.696.0': + '@aws-sdk/core@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 - '@smithy/core': 2.5.3 - '@smithy/node-config-provider': 3.1.11 - '@smithy/property-provider': 3.1.10 - '@smithy/protocol-http': 4.1.7 - '@smithy/signature-v4': 4.2.3 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/types': 3.709.0 + '@smithy/core': 2.5.5 + '@smithy/node-config-provider': 3.1.12 + '@smithy/property-provider': 3.1.11 + '@smithy/protocol-http': 4.1.8 + '@smithy/signature-v4': 4.2.4 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/util-middleware': 3.0.10 + '@smithy/util-middleware': 3.0.11 fast-xml-parser: 4.4.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.696.0': + '@aws-sdk/credential-provider-env@3.709.0': dependencies: - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/property-provider': 3.1.10 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/property-provider': 3.1.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.696.0': + '@aws-sdk/credential-provider-http@3.709.0': dependencies: - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/node-http-handler': 3.3.1 - '@smithy/property-provider': 3.1.10 - '@smithy/protocol-http': 4.1.7 - '@smithy/smithy-client': 3.4.4 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/node-http-handler': 3.3.2 + '@smithy/property-provider': 3.1.11 + '@smithy/protocol-http': 4.1.8 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/util-stream': 3.3.1 + '@smithy/util-stream': 3.3.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0)': - dependencies: - '@aws-sdk/client-sts': 3.699.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/credential-provider-env': 3.696.0 - '@aws-sdk/credential-provider-http': 3.696.0 - '@aws-sdk/credential-provider-process': 3.696.0 - '@aws-sdk/credential-provider-sso': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) - '@aws-sdk/credential-provider-web-identity': 3.696.0(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/types': 3.696.0 - '@smithy/credential-provider-imds': 3.2.7 - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@aws-sdk/credential-provider-ini@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0)': + dependencies: + '@aws-sdk/client-sts': 3.712.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/credential-provider-env': 3.709.0 + '@aws-sdk/credential-provider-http': 3.709.0 + '@aws-sdk/credential-provider-process': 3.709.0 + '@aws-sdk/credential-provider-sso': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) + '@aws-sdk/credential-provider-web-identity': 3.709.0(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/types': 3.709.0 + '@smithy/credential-provider-imds': 3.2.8 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-node@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0)': - dependencies: - '@aws-sdk/credential-provider-env': 3.696.0 - '@aws-sdk/credential-provider-http': 3.696.0 - '@aws-sdk/credential-provider-ini': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/credential-provider-process': 3.696.0 - '@aws-sdk/credential-provider-sso': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) - '@aws-sdk/credential-provider-web-identity': 3.696.0(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/types': 3.696.0 - '@smithy/credential-provider-imds': 3.2.7 - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@aws-sdk/credential-provider-node@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0)': + dependencies: + '@aws-sdk/credential-provider-env': 3.709.0 + '@aws-sdk/credential-provider-http': 3.709.0 + '@aws-sdk/credential-provider-ini': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/credential-provider-process': 3.709.0 + '@aws-sdk/credential-provider-sso': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) + '@aws-sdk/credential-provider-web-identity': 3.709.0(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/types': 3.709.0 + '@smithy/credential-provider-imds': 3.2.8 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: @@ -4413,158 +4413,158 @@ snapshots: - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-process@3.696.0': + '@aws-sdk/credential-provider-process@3.709.0': dependencies: - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': + '@aws-sdk/credential-provider-sso@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))': dependencies: - '@aws-sdk/client-sso': 3.696.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/token-providers': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) - '@aws-sdk/types': 3.696.0 - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@aws-sdk/client-sso': 3.712.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/token-providers': 3.709.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) + '@aws-sdk/types': 3.709.0 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-web-identity@3.696.0(@aws-sdk/client-sts@3.699.0)': + '@aws-sdk/credential-provider-web-identity@3.709.0(@aws-sdk/client-sts@3.712.0)': dependencies: - '@aws-sdk/client-sts': 3.699.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/property-provider': 3.1.10 + '@aws-sdk/client-sts': 3.712.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/property-provider': 3.1.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-bucket-endpoint@3.696.0': + '@aws-sdk/middleware-bucket-endpoint@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@aws-sdk/util-arn-parser': 3.693.0 - '@smithy/node-config-provider': 3.1.11 - '@smithy/protocol-http': 4.1.7 + '@smithy/node-config-provider': 3.1.12 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.696.0': + '@aws-sdk/middleware-expect-continue@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 - '@smithy/protocol-http': 4.1.7 + '@aws-sdk/types': 3.709.0 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.701.0': + '@aws-sdk/middleware-flexible-checksums@3.709.0': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 '@smithy/is-array-buffer': 3.0.0 - '@smithy/node-config-provider': 3.1.11 - '@smithy/protocol-http': 4.1.7 + '@smithy/node-config-provider': 3.1.12 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-stream': 3.3.1 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.696.0': + '@aws-sdk/middleware-host-header@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 - '@smithy/protocol-http': 4.1.7 + '@aws-sdk/types': 3.709.0 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.696.0': + '@aws-sdk/middleware-location-constraint@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.696.0': + '@aws-sdk/middleware-logger@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.696.0': + '@aws-sdk/middleware-recursion-detection@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 - '@smithy/protocol-http': 4.1.7 + '@aws-sdk/types': 3.709.0 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.696.0': + '@aws-sdk/middleware-sdk-s3@3.709.0': dependencies: - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 '@aws-sdk/util-arn-parser': 3.693.0 - '@smithy/core': 2.5.3 - '@smithy/node-config-provider': 3.1.11 - '@smithy/protocol-http': 4.1.7 - '@smithy/signature-v4': 4.2.3 - '@smithy/smithy-client': 3.4.4 + '@smithy/core': 2.5.5 + '@smithy/node-config-provider': 3.1.12 + '@smithy/protocol-http': 4.1.8 + '@smithy/signature-v4': 4.2.4 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-stream': 3.3.1 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.696.0': + '@aws-sdk/middleware-ssec@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.696.0': + '@aws-sdk/middleware-user-agent@3.709.0': dependencies: - '@aws-sdk/core': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-endpoints': 3.696.0 - '@smithy/core': 2.5.3 - '@smithy/protocol-http': 4.1.7 + '@aws-sdk/core': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@aws-sdk/util-endpoints': 3.709.0 + '@smithy/core': 2.5.5 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/region-config-resolver@3.696.0': + '@aws-sdk/region-config-resolver@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 - '@smithy/node-config-provider': 3.1.11 + '@aws-sdk/types': 3.709.0 + '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 - '@smithy/util-middleware': 3.0.10 + '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.696.0': + '@aws-sdk/signature-v4-multi-region@3.709.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/protocol-http': 4.1.7 - '@smithy/signature-v4': 4.2.3 + '@aws-sdk/middleware-sdk-s3': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/protocol-http': 4.1.8 + '@smithy/signature-v4': 4.2.4 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/token-providers@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': + '@aws-sdk/token-providers@3.709.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))': dependencies: - '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) - '@aws-sdk/types': 3.696.0 - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) + '@aws-sdk/types': 3.709.0 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/types@3.696.0': + '@aws-sdk/types@3.709.0': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -4573,33 +4573,33 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.696.0': + '@aws-sdk/util-endpoints@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/types': 3.7.2 - '@smithy/util-endpoints': 2.1.6 + '@smithy/util-endpoints': 2.1.7 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.568.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.696.0': + '@aws-sdk/util-user-agent-browser@3.709.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.709.0 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.696.0': + '@aws-sdk/util-user-agent-node@3.712.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.696.0 - '@aws-sdk/types': 3.696.0 - '@smithy/node-config-provider': 3.1.11 + '@aws-sdk/middleware-user-agent': 3.709.0 + '@aws-sdk/types': 3.709.0 + '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.696.0': + '@aws-sdk/xml-builder@3.709.0': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5295,7 +5295,7 @@ snapshots: '@sideway/pinpoint@2.0.0': {} - '@smithy/abort-controller@3.1.8': + '@smithy/abort-controller@3.1.9': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5309,92 +5309,92 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/config-resolver@3.0.12': + '@smithy/config-resolver@3.0.13': dependencies: - '@smithy/node-config-provider': 3.1.11 + '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 - '@smithy/util-middleware': 3.0.10 + '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/core@2.5.3': + '@smithy/core@2.5.5': dependencies: - '@smithy/middleware-serde': 3.0.10 - '@smithy/protocol-http': 4.1.7 + '@smithy/middleware-serde': 3.0.11 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-body-length-browser': 3.0.0 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-stream': 3.3.1 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@3.2.7': + '@smithy/credential-provider-imds@3.2.8': dependencies: - '@smithy/node-config-provider': 3.1.11 - '@smithy/property-provider': 3.1.10 + '@smithy/node-config-provider': 3.1.12 + '@smithy/property-provider': 3.1.11 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 + '@smithy/url-parser': 3.0.11 tslib: 2.8.1 - '@smithy/eventstream-codec@3.1.9': + '@smithy/eventstream-codec@3.1.10': dependencies: '@aws-crypto/crc32': 5.2.0 '@smithy/types': 3.7.2 '@smithy/util-hex-encoding': 3.0.0 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@3.0.13': + '@smithy/eventstream-serde-browser@3.0.14': dependencies: - '@smithy/eventstream-serde-universal': 3.0.12 + '@smithy/eventstream-serde-universal': 3.0.13 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/eventstream-serde-config-resolver@3.0.10': + '@smithy/eventstream-serde-config-resolver@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/eventstream-serde-node@3.0.12': + '@smithy/eventstream-serde-node@3.0.13': dependencies: - '@smithy/eventstream-serde-universal': 3.0.12 + '@smithy/eventstream-serde-universal': 3.0.13 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@3.0.12': + '@smithy/eventstream-serde-universal@3.0.13': dependencies: - '@smithy/eventstream-codec': 3.1.9 + '@smithy/eventstream-codec': 3.1.10 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/fetch-http-handler@4.1.1': + '@smithy/fetch-http-handler@4.1.2': dependencies: - '@smithy/protocol-http': 4.1.7 - '@smithy/querystring-builder': 3.0.10 + '@smithy/protocol-http': 4.1.8 + '@smithy/querystring-builder': 3.0.11 '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 tslib: 2.8.1 - '@smithy/hash-blob-browser@3.1.9': + '@smithy/hash-blob-browser@3.1.10': dependencies: '@smithy/chunked-blob-reader': 4.0.0 '@smithy/chunked-blob-reader-native': 3.0.1 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/hash-node@3.0.10': + '@smithy/hash-node@3.0.11': dependencies: '@smithy/types': 3.7.2 '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/hash-stream-node@3.1.9': + '@smithy/hash-stream-node@3.1.10': dependencies: '@smithy/types': 3.7.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/invalid-dependency@3.0.10': + '@smithy/invalid-dependency@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5407,124 +5407,124 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/md5-js@3.0.10': + '@smithy/md5-js@3.0.11': dependencies: '@smithy/types': 3.7.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/middleware-content-length@3.0.12': + '@smithy/middleware-content-length@3.0.13': dependencies: - '@smithy/protocol-http': 4.1.7 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/middleware-endpoint@3.2.3': + '@smithy/middleware-endpoint@3.2.5': dependencies: - '@smithy/core': 2.5.3 - '@smithy/middleware-serde': 3.0.10 - '@smithy/node-config-provider': 3.1.11 - '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/core': 2.5.5 + '@smithy/middleware-serde': 3.0.11 + '@smithy/node-config-provider': 3.1.12 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 - '@smithy/url-parser': 3.0.10 - '@smithy/util-middleware': 3.0.10 + '@smithy/url-parser': 3.0.11 + '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/middleware-retry@3.0.27': + '@smithy/middleware-retry@3.0.30': dependencies: - '@smithy/node-config-provider': 3.1.11 - '@smithy/protocol-http': 4.1.7 - '@smithy/service-error-classification': 3.0.10 - '@smithy/smithy-client': 3.4.4 + '@smithy/node-config-provider': 3.1.12 + '@smithy/protocol-http': 4.1.8 + '@smithy/service-error-classification': 3.0.11 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 - '@smithy/util-middleware': 3.0.10 - '@smithy/util-retry': 3.0.10 + '@smithy/util-middleware': 3.0.11 + '@smithy/util-retry': 3.0.11 tslib: 2.8.1 uuid: 9.0.1 - '@smithy/middleware-serde@3.0.10': + '@smithy/middleware-serde@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/middleware-stack@3.0.10': + '@smithy/middleware-stack@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/node-config-provider@3.1.11': + '@smithy/node-config-provider@3.1.12': dependencies: - '@smithy/property-provider': 3.1.10 - '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/property-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/node-http-handler@3.3.1': + '@smithy/node-http-handler@3.3.2': dependencies: - '@smithy/abort-controller': 3.1.8 - '@smithy/protocol-http': 4.1.7 - '@smithy/querystring-builder': 3.0.10 + '@smithy/abort-controller': 3.1.9 + '@smithy/protocol-http': 4.1.8 + '@smithy/querystring-builder': 3.0.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/property-provider@3.1.10': + '@smithy/property-provider@3.1.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/protocol-http@4.1.7': + '@smithy/protocol-http@4.1.8': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/querystring-builder@3.0.10': + '@smithy/querystring-builder@3.0.11': dependencies: '@smithy/types': 3.7.2 '@smithy/util-uri-escape': 3.0.0 tslib: 2.8.1 - '@smithy/querystring-parser@3.0.10': + '@smithy/querystring-parser@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/service-error-classification@3.0.10': + '@smithy/service-error-classification@3.0.11': dependencies: '@smithy/types': 3.7.2 - '@smithy/shared-ini-file-loader@3.1.11': + '@smithy/shared-ini-file-loader@3.1.12': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/signature-v4@4.2.3': + '@smithy/signature-v4@4.2.4': dependencies: '@smithy/is-array-buffer': 3.0.0 - '@smithy/protocol-http': 4.1.7 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-hex-encoding': 3.0.0 - '@smithy/util-middleware': 3.0.10 + '@smithy/util-middleware': 3.0.11 '@smithy/util-uri-escape': 3.0.0 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/smithy-client@3.4.4': + '@smithy/smithy-client@3.5.0': dependencies: - '@smithy/core': 2.5.3 - '@smithy/middleware-endpoint': 3.2.3 - '@smithy/middleware-stack': 3.0.10 - '@smithy/protocol-http': 4.1.7 + '@smithy/core': 2.5.5 + '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-stack': 3.0.11 + '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 - '@smithy/util-stream': 3.3.1 + '@smithy/util-stream': 3.3.2 tslib: 2.8.1 '@smithy/types@3.7.2': dependencies: tslib: 2.7.0 - '@smithy/url-parser@3.0.10': + '@smithy/url-parser@3.0.11': dependencies: - '@smithy/querystring-parser': 3.0.10 + '@smithy/querystring-parser': 3.0.11 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5556,27 +5556,27 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@3.0.27': + '@smithy/util-defaults-mode-browser@3.0.30': dependencies: - '@smithy/property-provider': 3.1.10 - '@smithy/smithy-client': 3.4.4 + '@smithy/property-provider': 3.1.11 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@3.0.27': + '@smithy/util-defaults-mode-node@3.0.30': dependencies: - '@smithy/config-resolver': 3.0.12 - '@smithy/credential-provider-imds': 3.2.7 - '@smithy/node-config-provider': 3.1.11 - '@smithy/property-provider': 3.1.10 - '@smithy/smithy-client': 3.4.4 + '@smithy/config-resolver': 3.0.13 + '@smithy/credential-provider-imds': 3.2.8 + '@smithy/node-config-provider': 3.1.12 + '@smithy/property-provider': 3.1.11 + '@smithy/smithy-client': 3.5.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-endpoints@2.1.6': + '@smithy/util-endpoints@2.1.7': dependencies: - '@smithy/node-config-provider': 3.1.11 + '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5584,21 +5584,21 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-middleware@3.0.10': + '@smithy/util-middleware@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-retry@3.0.10': + '@smithy/util-retry@3.0.11': dependencies: - '@smithy/service-error-classification': 3.0.10 + '@smithy/service-error-classification': 3.0.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-stream@3.3.1': + '@smithy/util-stream@3.3.2': dependencies: - '@smithy/fetch-http-handler': 4.1.1 - '@smithy/node-http-handler': 3.3.1 + '@smithy/fetch-http-handler': 4.1.2 + '@smithy/node-http-handler': 3.3.2 '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 '@smithy/util-buffer-from': 3.0.0 @@ -5620,9 +5620,9 @@ snapshots: '@smithy/util-buffer-from': 3.0.0 tslib: 2.8.1 - '@smithy/util-waiter@3.1.9': + '@smithy/util-waiter@3.2.0': dependencies: - '@smithy/abort-controller': 3.1.8 + '@smithy/abort-controller': 3.1.9 '@smithy/types': 3.7.2 tslib: 2.8.1 From a1dff82d18b660917e715d43d8641a9ddf4c4e97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:36:06 +0000 Subject: [PATCH 56/83] chore(deps-dev): bump @typescript-eslint/typescript-estree Bumps [@typescript-eslint/typescript-estree](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-estree) from 8.17.0 to 8.18.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-estree/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.18.0/packages/typescript-estree) --- updated-dependencies: - dependency-name: "@typescript-eslint/typescript-estree" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 43 ++----------------------------------------- 2 files changed, 3 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 0f56595e..18978677 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@types/node": "^22.10.2", "@types/wait-on": "^5.3.4", "@types/ws": "^8.5.13", - "@typescript-eslint/typescript-estree": "^8.17.0", + "@typescript-eslint/typescript-estree": "^8.18.0", "@web3-storage/access": "^20.1.1", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46ccd7b7..f1baf516 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,8 +160,8 @@ importers: specifier: ^8.5.13 version: 8.5.13 '@typescript-eslint/typescript-estree': - specifier: ^8.17.0 - version: 8.17.0(typescript@5.7.2) + specifier: ^8.18.0 + version: 8.18.0(typescript@5.7.2) esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -1636,23 +1636,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.17.0': - resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.18.0': resolution: {integrity: sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.17.0': - resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/typescript-estree@8.18.0': resolution: {integrity: sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1666,10 +1653,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@8.17.0': - resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.18.0': resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5723,25 +5706,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.17.0': {} - '@typescript-eslint/types@8.18.0': {} - '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': - dependencies: - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/visitor-keys': 8.17.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.18.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.18.0 @@ -5767,11 +5733,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.17.0': - dependencies: - '@typescript-eslint/types': 8.17.0 - eslint-visitor-keys: 4.2.0 - '@typescript-eslint/visitor-keys@8.18.0': dependencies: '@typescript-eslint/types': 8.18.0 From bff090e86502a136021a3356f9c702d7f22caa3d Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Thu, 21 Nov 2024 20:00:02 +0100 Subject: [PATCH 57/83] feat: Add sharing, fix sync & finish ucan examples --- examples/ucan/browser/package.json | 3 +- examples/ucan/browser/pnpm-lock.yaml | 616 +- examples/ucan/browser/src/index.html | 2 - examples/ucan/browser/src/state.js | 270 +- examples/ucan/browser/src/types.d.ts | 33 +- examples/ucan/browser/src/view.js | 362 +- examples/ucan/node/package.json | 2 +- .../ucan/workshop/participants/.gitignore | 1 - examples/ucan/workshop/participants/db.js | 8 - .../ucan/workshop/participants/delegate.js | 6 +- .../ucan/workshop/participants/package.json | 4 +- .../ucan/workshop/participants/pnpm-lock.yaml | 737 +- .../ucan/workshop/participants/start-here.js | 2 +- examples/ucan/workshop/team/README.md | 4 + examples/ucan/workshop/team/package.json | 3 +- examples/ucan/workshop/team/pnpm-lock.yaml | 681 +- examples/ucan/workshop/team/src/state.js | 2 +- package.json | 1 + pnpm-lock.yaml | 3 + pnpm-lock.yaml.orig | 8448 +++++++++++++++++ src/ucan/clock/capabilities.ts | 2 - src/ucan/common.ts | 28 +- src/ucan/index.ts | 213 +- src/ucan/types.ts | 6 +- src/ucan/ucan-gateway.ts | 77 +- 25 files changed, 10006 insertions(+), 1508 deletions(-) create mode 100644 examples/ucan/workshop/team/README.md create mode 100644 pnpm-lock.yaml.orig diff --git a/examples/ucan/browser/package.json b/examples/ucan/browser/package.json index 431959a5..457e7b6e 100644 --- a/examples/ucan/browser/package.json +++ b/examples/ucan/browser/package.json @@ -7,7 +7,8 @@ "preview": "rsbuild preview" }, "dependencies": { - "@fireproof/connect": "../../../", + "@fireproof/core": "0.19.113", + "@fireproof/ucan": "../../../dist/ucan", "@picocss/pico": "^2.0.6", "spellcaster": "^5.0.2" }, diff --git a/examples/ucan/browser/pnpm-lock.yaml b/examples/ucan/browser/pnpm-lock.yaml index d188dea1..85ad35c4 100644 --- a/examples/ucan/browser/pnpm-lock.yaml +++ b/examples/ucan/browser/pnpm-lock.yaml @@ -8,9 +8,12 @@ importers: .: dependencies: - '@fireproof/connect': - specifier: ../../../ - version: link:../../.. + '@fireproof/core': + specifier: 0.19.113 + version: 0.19.113(react@18.3.1)(typescript@5.6.3) + '@fireproof/ucan': + specifier: ../../../dist/ucan + version: link:../../../dist/ucan '@picocss/pico': specifier: ^2.0.6 version: 2.0.6 @@ -39,6 +42,10 @@ importers: packages: + '@adviser/cement@0.2.36': + resolution: {integrity: sha512-Zhmr4f0/UohFh3O/6H63DoBenYjh72uGZOcEnDZ/VxmBvZelACkCR4g06c8rbZbJTu20f3gRSNnJZbmtdMOFgQ==} + engines: {node: '>=16'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -81,6 +88,11 @@ packages: resolution: {integrity: sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fireproof/core@0.19.113': + resolution: {integrity: sha512-LGAgDBd8MePZ2QUaBav2Wd1pa37SvYfngNAaDh00WGCL9skF+y4ZhcVmhUGNcIKG3xcANsyxouFu7h0rgBoNeA==} + peerDependencies: + react: ^18.3.1 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -101,6 +113,43 @@ packages: resolution: {integrity: sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==} engines: {node: '>=18.18'} + '@ipld/car@5.3.3': + resolution: {integrity: sha512-4vgV5Ml4HCJ2iTx7vYhu0ui+Xxo1HQTtVeYgD+JKd5Wij8TlOFZnxOSickqpLcuf1fdGEStgqVItx15UWfzDYA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-cbor@9.2.2': + resolution: {integrity: sha512-uIEOuruCqKTP50OBWwgz4Js2+LhiBQaxc57cnP71f45b1mHEAo1OCR1Zn/TbvSW/mV1x+JqhacIktkKyaYqhCw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-json@10.2.3': + resolution: {integrity: sha512-itacv1j1hvYgLox2B42Msn70QLzcr0MEo5yGIENuw2SM/lQzq9bmBiMky+kDsIrsqqblKTXcHBZnnmK7D4a6ZQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-pb@4.1.3': + resolution: {integrity: sha512-ueULCaaSCcD+dQga6nKiRr+RSeVgdiYiEPKVUu5iQMNYDN+9osd0KpR3UDd9uQQ+6RWuv9L34SchfEwj7YIbOA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/unixfs@3.0.0': + resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} + + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.1.0': + resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.5.0': + resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@module-federation/runtime-tools@0.5.1': resolution: {integrity: sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==} @@ -113,6 +162,10 @@ packages: '@module-federation/webpack-bundler-runtime@0.5.1': resolution: {integrity: sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==} + '@multiformats/murmur3@2.1.8': + resolution: {integrity: sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -125,10 +178,43 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@perma/map@1.0.3': + resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} + '@picocss/pico@2.0.6': resolution: {integrity: sha512-/d8qsykowelD6g8k8JYgmCagOIulCPHMEc2NC4u7OjmpQLmtSetLhEbt0j1n3fPNJVcrT84dRp0RfJBn3wJROA==} engines: {node: '>=18.19.0'} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@rsbuild/core@1.0.19': resolution: {integrity: sha512-63DAPvYfRBoUrb51BUPb4Xoqx48MHQ0yLcmnCiqZGpMeKYtTWzD+lyx5va4cr9qvdnIFTAX2BMuYC/j5iSrtTA==} engines: {node: '>=16.7.0'} @@ -212,9 +298,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@22.9.1': + resolution: {integrity: sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==} + '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@typescript-eslint/eslint-plugin@8.12.2': resolution: {integrity: sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -272,6 +364,10 @@ packages: resolution: {integrity: sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@web3-storage/pail@0.6.0': + resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} + hasBin: true + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -286,6 +382,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + actor@2.3.1: + resolution: {integrity: sha512-ST/3wnvcP2tKDXnum7nLCLXm+/rsf8vPocXH2Fre6D8FQwNkGDd4JEitBlXj007VQJfiGYRQvXqwOBZVi+JtRg==} + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -312,6 +411,13 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} @@ -383,10 +489,17 @@ packages: caniuse-lite@1.0.30001676: resolution: {integrity: sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==} + cborg@4.2.6: + resolution: {integrity: sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==} + hasBin: true + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + charwise@3.0.1: + resolution: {integrity: sha512-RcdumNsM6fJZ5HHbYunqj2bpurVRGsXour3OR+SlLEHFhG6ALm54i6Osnh+OvO7kEoSBzwExpblYFH8zKQiEPw==} + ci-info@4.0.0: resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} engines: {node: '>=8'} @@ -551,6 +664,9 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -634,6 +750,9 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + hamt-sharding@3.0.6: + resolution: {integrity: sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -673,6 +792,13 @@ packages: https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + idb@8.0.0: + resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -695,6 +821,18 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + interface-blockstore@5.3.1: + resolution: {integrity: sha512-nhgrQnz6yUQEqxTFLhlOBurQOy5lWlwCpgFmZ3GTObTVTQS9RZjK/JTozY6ty9uz2lZs7VFJSqwjWAltorJ4Vw==} + + interface-store@6.0.2: + resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} + + ipfs-unixfs-exporter@13.6.1: + resolution: {integrity: sha512-pYPI4oBTWao2//sFzAL0pURyojn79q/u5BuK6L5/nVbVUQVw6DcVP5uB1ySdWlTM2H+0Zlhp9+OL9aJBRIICpg==} + + ipfs-unixfs@11.2.0: + resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} + is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -730,6 +868,10 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-network-error@1.1.0: + resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} + engines: {node: '>=16'} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -744,6 +886,34 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + it-filter@3.1.1: + resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} + + it-last@3.0.6: + resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} + + it-map@3.1.1: + resolution: {integrity: sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==} + + it-merge@3.0.5: + resolution: {integrity: sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==} + + it-parallel@3.0.8: + resolution: {integrity: sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==} + + it-peekable@3.0.5: + resolution: {integrity: sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==} + + it-pipe@3.0.1: + resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + it-pushable@3.2.3: + resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} + + it-stream-types@2.0.2: + resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -793,9 +963,20 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + memfs@4.14.0: + resolution: {integrity: sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==} + engines: {node: '>= 4.0.0'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -828,12 +1009,23 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multiformats@13.3.1: + resolution: {integrity: sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==} + + murmurhash3js-revisited@3.0.0: + resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} + engines: {node: '>=8.0.0'} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-sql-parser@3.9.4: + resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} + engines: {node: '>=8'} + normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -860,6 +1052,10 @@ packages: os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + p-defer@4.0.1: + resolution: {integrity: sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==} + engines: {node: '>=12'} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -868,6 +1064,10 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -876,6 +1076,22 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + + p-timeout@6.1.3: + resolution: {integrity: sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==} + engines: {node: '>=14.16'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -939,6 +1155,19 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + progress-events@1.0.1: + resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} + + prolly-trees@1.0.4: + resolution: {integrity: sha512-vtnxfw5wnUHbGa0IIIk9B9DRztJWZw+t9d0s0iGxY/VzEGCg2EMl8GgGU3EhSquFLWapwbGjFTL1ipbezaXR3g==} + + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + + protons-runtime@5.5.0: + resolution: {integrity: sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==} + public-encrypt@4.0.3: resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} @@ -960,12 +1189,19 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + rabin-rs@2.1.0: + resolution: {integrity: sha512-5y72gAXPzIBsAMHcpxZP8eMDuDT98qMP1BqSDHRbHkJJXEgWIN1lA47LxUqzsK6jknOJtgfkQr9v+7qMlFDm6g==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} randomfill@1.0.4: resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -1001,6 +1237,10 @@ packages: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1052,6 +1292,9 @@ packages: signal-polyfill@0.1.2: resolution: {integrity: sha512-HT9d+L9NMiTzMxb/tU2Baym6129ROyRETSjvchvSkQa7wN0+SrG/IUlsaBLqKn2c+4mlze6CgQBEvgBjxOpiaQ==} + sparse-array@1.3.2: + resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} + spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -1098,6 +1341,12 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + timers-browserify@2.0.12: resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} engines: {node: '>=0.6.0'} @@ -1106,12 +1355,26 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + ts-api-utils@1.4.0: resolution: {integrity: sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' + ts-essentials@10.0.3: + resolution: {integrity: sha512-/FrVAZ76JLTWxJOERk04fm8hYENDo0PWSP3YLQKxevLwWtxemGcl5JJEzN4iqfDlRve0ckyfFaOBu4xbNH/wZw==} + peerDependencies: + typescript: '>=4.5.0' + peerDependenciesMeta: + typescript: + optional: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -1144,6 +1407,18 @@ packages: engines: {node: '>=14.17'} hasBin: true + uint8-varint@2.0.4: + resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} + + uint8arraylist@2.4.8: + resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} + + uint8arrays@5.1.0: + resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true @@ -1166,6 +1441,9 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + vm-browserify@1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} @@ -1186,12 +1464,28 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} + engines: {node: '>= 14'} + hasBin: true + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + snapshots: + '@adviser/cement@0.2.36(typescript@5.6.3)': + dependencies: + ts-essentials: 10.0.3(typescript@5.6.3) + yaml: 2.6.1 + transitivePeerDependencies: + - typescript + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -1239,6 +1533,28 @@ snapshots: dependencies: levn: 0.4.1 + '@fireproof/core@0.19.113(react@18.3.1)(typescript@5.6.3)': + dependencies: + '@adviser/cement': 0.2.36(typescript@5.6.3) + '@ipld/car': 5.3.3 + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.3 + '@ipld/unixfs': 3.0.0 + '@web3-storage/pail': 0.6.0 + cborg: 4.2.6 + charwise: 3.0.1 + idb: 8.0.0 + ipfs-unixfs-exporter: 13.6.1 + memfs: 4.14.0 + multiformats: 13.3.1 + p-limit: 6.1.0 + p-map: 7.0.2 + p-retry: 6.2.1 + prolly-trees: 1.0.4 + react: 18.3.1 + transitivePeerDependencies: + - typescript + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -1252,6 +1568,53 @@ snapshots: '@humanwhocodes/retry@0.4.0': {} + '@ipld/car@5.3.3': + dependencies: + '@ipld/dag-cbor': 9.2.2 + cborg: 4.2.6 + multiformats: 13.3.1 + varint: 6.0.0 + + '@ipld/dag-cbor@9.2.2': + dependencies: + cborg: 4.2.6 + multiformats: 13.3.1 + + '@ipld/dag-json@10.2.3': + dependencies: + cborg: 4.2.6 + multiformats: 13.3.1 + + '@ipld/dag-pb@4.1.3': + dependencies: + multiformats: 13.3.1 + + '@ipld/unixfs@3.0.0': + dependencies: + '@ipld/dag-pb': 4.1.3 + '@multiformats/murmur3': 2.1.8 + '@perma/map': 1.0.3 + actor: 2.3.1 + multiformats: 13.3.1 + protobufjs: 7.4.0 + rabin-rs: 2.1.0 + + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.1.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.5.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + '@module-federation/runtime-tools@0.5.1': dependencies: '@module-federation/runtime': 0.5.1 @@ -1268,6 +1631,11 @@ snapshots: '@module-federation/runtime': 0.5.1 '@module-federation/sdk': 0.5.1 + '@multiformats/murmur3@2.1.8': + dependencies: + multiformats: 13.3.1 + murmurhash3js-revisited: 3.0.0 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1280,8 +1648,36 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@perma/map@1.0.3': + dependencies: + '@multiformats/murmur3': 2.1.8 + murmurhash3js-revisited: 3.0.0 + '@picocss/pico@2.0.6': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@rsbuild/core@1.0.19': dependencies: '@rspack/core': 1.0.14(@swc/helpers@0.5.13) @@ -1377,8 +1773,14 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/node@22.9.1': + dependencies: + undici-types: 6.19.8 + '@types/normalize-package-data@2.4.4': {} + '@types/retry@0.12.2': {} + '@typescript-eslint/eslint-plugin@8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -1460,6 +1862,11 @@ snapshots: '@typescript-eslint/types': 8.12.2 eslint-visitor-keys: 3.4.3 + '@web3-storage/pail@0.6.0': + dependencies: + '@ipld/dag-cbor': 9.2.2 + multiformats: 13.3.1 + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -1470,6 +1877,8 @@ snapshots: acorn@8.14.0: {} + actor@2.3.1: {} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -1505,6 +1914,14 @@ snapshots: base64-js@1.5.1: {} + big-integer@1.6.52: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + bn.js@4.12.0: {} bn.js@5.2.1: {} @@ -1604,11 +2021,15 @@ snapshots: caniuse-lite@1.0.30001676: {} + cborg@4.2.6: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + charwise@3.0.1: {} + ci-info@4.0.0: {} cipher-base@1.0.4: @@ -1831,6 +2252,8 @@ snapshots: event-target-shim@5.0.1: {} + eventemitter3@5.0.1: {} + events@3.3.0: {} evp_bytestokey@1.0.3: @@ -1916,6 +2339,11 @@ snapshots: graphemer@1.4.0: {} + hamt-sharding@3.0.6: + dependencies: + sparse-array: 1.3.2 + uint8arrays: 5.1.0 + has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -1954,6 +2382,10 @@ snapshots: https-browserify@1.0.0: {} + hyperdyperid@1.2.0: {} + + idb@8.0.0: {} + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -1969,6 +2401,37 @@ snapshots: inherits@2.0.4: {} + interface-blockstore@5.3.1: + dependencies: + interface-store: 6.0.2 + multiformats: 13.3.1 + + interface-store@6.0.2: {} + + ipfs-unixfs-exporter@13.6.1: + dependencies: + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.3 + '@ipld/dag-pb': 4.1.3 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + + ipfs-unixfs@11.2.0: + dependencies: + protons-runtime: 5.5.0 + uint8arraylist: 2.4.8 + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 @@ -2001,6 +2464,8 @@ snapshots: call-bind: 1.0.7 define-properties: 1.2.1 + is-network-error@1.1.0: {} + is-number@7.0.0: {} is-typed-array@1.1.13: @@ -2011,6 +2476,38 @@ snapshots: isexe@2.0.0: {} + it-filter@3.1.1: + dependencies: + it-peekable: 3.0.5 + + it-last@3.0.6: {} + + it-map@3.1.1: + dependencies: + it-peekable: 3.0.5 + + it-merge@3.0.5: + dependencies: + it-pushable: 3.2.3 + + it-parallel@3.0.8: + dependencies: + p-defer: 4.0.1 + + it-peekable@3.0.5: {} + + it-pipe@3.0.1: + dependencies: + it-merge: 3.0.5 + it-pushable: 3.2.3 + it-stream-types: 2.0.2 + + it-pushable@3.2.3: + dependencies: + p-defer: 4.0.1 + + it-stream-types@2.0.2: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -2050,12 +2547,25 @@ snapshots: lodash.merge@4.6.2: {} + long@5.2.3: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + md5.js@1.3.5: dependencies: hash-base: 3.0.4 inherits: 2.0.4 safe-buffer: 5.2.1 + memfs@4.14.0: + dependencies: + '@jsonjoy.com/json-pack': 1.1.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) + tslib: 2.8.1 + merge2@1.4.1: {} micromatch@4.0.8: @@ -2084,10 +2594,18 @@ snapshots: ms@2.1.3: {} + multiformats@13.3.1: {} + + murmurhash3js-revisited@3.0.0: {} + natural-compare@1.4.0: {} node-releases@2.0.18: {} + node-sql-parser@3.9.4: + dependencies: + big-integer: 1.6.52 + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -2122,6 +2640,8 @@ snapshots: os-browserify@0.3.0: {} + p-defer@4.0.1: {} + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -2130,6 +2650,10 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-limit@6.1.0: + dependencies: + yocto-queue: 1.1.1 + p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -2138,6 +2662,21 @@ snapshots: dependencies: p-limit: 3.1.0 + p-map@7.0.2: {} + + p-queue@8.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.3 + + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + + p-timeout@6.1.3: {} + p-try@2.2.0: {} pako@1.0.11: {} @@ -2192,6 +2731,34 @@ snapshots: process@0.11.10: {} + progress-events@1.0.1: {} + + prolly-trees@1.0.4: + dependencies: + bl: 4.1.0 + node-sql-parser: 3.9.4 + + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.9.1 + long: 5.2.3 + + protons-runtime@5.5.0: + dependencies: + uint8-varint: 2.0.4 + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + public-encrypt@4.0.3: dependencies: bn.js: 4.12.0 @@ -2213,6 +2780,8 @@ snapshots: queue-microtask@1.2.3: {} + rabin-rs@2.1.0: {} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 @@ -2222,6 +2791,10 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 @@ -2273,6 +2846,8 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + retry@0.13.1: {} + reusify@1.0.4: {} ripemd160@2.0.2: @@ -2323,6 +2898,8 @@ snapshots: signal-polyfill@0.1.2: {} + sparse-array@1.3.2: {} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 @@ -2375,6 +2952,10 @@ snapshots: text-table@0.2.0: {} + thingies@1.21.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + timers-browserify@2.0.12: dependencies: setimmediate: 1.0.5 @@ -2383,10 +2964,18 @@ snapshots: dependencies: is-number: 7.0.0 + tree-dump@1.0.2(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + ts-api-utils@1.4.0(typescript@5.6.3): dependencies: typescript: 5.6.3 + ts-essentials@10.0.3(typescript@5.6.3): + optionalDependencies: + typescript: 5.6.3 + tslib@2.8.1: {} tty-browserify@0.0.1: {} @@ -2412,6 +3001,21 @@ snapshots: typescript@5.6.3: {} + uint8-varint@2.0.4: + dependencies: + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + + uint8arraylist@2.4.8: + dependencies: + uint8arrays: 5.1.0 + + uint8arrays@5.1.0: + dependencies: + multiformats: 13.3.1 + + undici-types@6.19.8: {} + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: browserslist: 4.24.2 @@ -2442,6 +3046,8 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + varint@6.0.0: {} + vm-browserify@1.1.2: {} which-typed-array@1.1.15: @@ -2460,4 +3066,8 @@ snapshots: xtend@4.0.2: {} + yaml@2.6.1: {} + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} diff --git a/examples/ucan/browser/src/index.html b/examples/ucan/browser/src/index.html index da30efcb..abc86651 100644 --- a/examples/ucan/browser/src/index.html +++ b/examples/ucan/browser/src/index.html @@ -5,8 +5,6 @@ Fireproof Cloud - - diff --git a/examples/ucan/browser/src/state.js b/examples/ucan/browser/src/state.js index 5f7ea2d2..c87c9edf 100644 --- a/examples/ucan/browser/src/state.js +++ b/examples/ucan/browser/src/state.js @@ -1,12 +1,23 @@ -import * as UCAN from "@fireproof/connect/ucan"; +import { fireproof } from "@fireproof/core"; +import * as UCAN from "@fireproof/ucan"; import { fxware, store } from "spellcaster/spellcaster.js"; /** - & @template T + * @typedef {import("@fireproof/core").DocTypes} DocTypes + */ + +/** + * @template T * @typedef {import("spellcaster/spellcaster.js").Effect} Effect */ /** + * @template V + * @typedef {import("@fireproof/core").AllDocsResponse} AllDocsResponse + */ + +/** + * @typedef {import("@fireproof/ucan").Server} Server * @typedef {import("./types").Msg} Msg * @typedef {import("./types").State} State */ @@ -16,15 +27,56 @@ const DEFAULT_DB_NAME = "my-fireproof-db"; /** * @param state {State} * @param msg {Msg} - * @returns State + * @returns {State} */ const update = (state, msg) => { + console.log(msg.type) switch (msg.type) { - case "SET_CLOCK": - return { ...state, clock: msg.clock }; - case "SET_DATABASE_NAME": - const databaseName = msg.name.length ? msg.name : DEFAULT_DB_NAME; - return { ...state, databaseName }; + case "CLAIM_ALL_SHARES": return { ...state, shareClaims: "loading" } + case "CLAIMED_SHARES": return { ...state, shareClaims: msg.delegations } + + case "CONNECT": return { ...state, databaseContents: "loading", shareStatus: undefined } + case "CONNECTED": return { ...state, database: msg.database } + case "SET_CLOCK": return { ...state, clock: msg.clock } + + case "SET_CLOCK_ID_INPUT": { + const val = msg.clockId.trim(); + const clockIdInput = val.match(/did\:key\:.+/) ? /** @type {`did:key:${string}`} */ (val) : undefined + + return { ...state, clockIdInput }; + } + + case "SET_DATABASE_CONTENTS": { + return { ...state, databaseContents: msg.contents }; + } + + case "SET_EMAIL": { + const val = msg.email.trim() + const email = val.length && val.includes("@") ? /** @type {`${string}@${string}`} */ (val) : undefined + + return { ...state, email } + } + + case "SET_LOGGED_IN": return { ...state, loggedIn: msg.loggedIn } + case "SET_SERVER": return { ...state, server: msg.server } + + case "SET_SERVER_INPUT": { + const val = msg.server.trim() + const serverInput = val.length && val.match(/https?\:\/\//) ? val : undefined + + return { ...state, serverInput } + } + + case "SHARE_WITH_EMAIL": { + return { ...state, shareStatus: { type: "LOADING" } } + } + + case "SHARED_WITH_EMAIL": { + return { ...state, shareStatus: { type: "SHARED", cid: msg.cid, email: msg.email } } + } + + case "WAIT_FOR_LOGIN": return { ...state, loggedIn: "in-progress" } + default: return state; } @@ -36,8 +88,34 @@ const update = (state, msg) => { */ const fx = (msg) => { switch (msg.type) { - case "SET_DATABASE_NAME": + case "CLAIM_ALL_SHARES": + return [claimAllShares]; + case "CONNECT": + return [connect] + case "CONNECTED": + return [fetchDbContents] + case "DATABASE_CONTENTS_CHANGED": + return [fetchDbContents] + case "LOGIN": + return [login]; + case "SET_AGENT": + return [determineClock]; + case "SET_CLOCK": + return [connect, saveConfig] + case "SET_CLOCK_ID_INPUT": + return [determineClock]; + case "SET_EMAIL": return [determineClock, saveConfig]; + case "SET_LOGGED_IN": + return [connect]; + case "SET_SERVER": + return [checkLoginStatusIfServerChanged(msg.server), determineAgent, saveConfig]; + case "SET_SERVER_INPUT": + return [determineServer]; + case "SHARE_WITH_EMAIL": + return [shareWithEmail(msg.email)] + case "WAIT_FOR_LOGIN": + return [waitForLogin(msg.promise)] default: return []; } @@ -46,22 +124,122 @@ const fx = (msg) => { // Effects // ======= +/** @param {Server} server */ +function checkLoginStatusIfServerChanged(server) { + /** @returns Promise */ + return async () => { + const s = state() + + if (server.id.did() === s.server.id.did()) { + return /** @type {Msg} */({ type: "-" }) + } + + const loggedIn = s.email + ? await UCAN.isLoggedIn({ agent: s.agent, email: UCAN.email(s.email) }) + : false + + return /** @type {Msg} */({ type: "SET_LOGGED_IN", loggedIn }) + } +} + +/** @returns {Promise} */ +async function claimAllShares() { + const email = state().email + if (!email) throw new Error("Cannot claim shares if not logged in") + + const { agent, server } = state() + const delegations = await UCAN.claimShares({ email: UCAN.email(email) }, { agent, server }) + + return { type: "CLAIMED_SHARES", delegations } +} + +/** @returns {Promise} */ +async function connect() { + const { agent, clock, email, loggedIn, server } = state() + + const database = fireproof(clock.id.did()) + + if (!email || (email && loggedIn)) { + await UCAN.connect(database, { + agent, + clock, + server, + email: email && loggedIn ? UCAN.email(email) : undefined + }) + } + + return { type: "CONNECTED", database } +} + +/** @returns {Promise} */ +async function determineAgent() { + const { server } = state() + const agent = await UCAN.agent({ server }); + + return { type: "SET_AGENT", agent }; +} + /** @returns {Promise} */ async function determineClock() { - const { agent, databaseName } = state(); - const clock = await UCAN.clock({ audience: agent.agent, databaseName }); + const { agent, clockIdInput, email, server } = state(); + + const clock = clockIdInput + ? UCAN.clockId(clockIdInput) + : await UCAN.clock({ audience: email ? UCAN.email(email) : agent.agent }); + + if (clock.isNew && email) { + await UCAN.registerClock({ clock, server }) + } + return { type: "SET_CLOCK", clock }; } +/** @returns {Promise} */ +async function determineServer() { + const { serverInput } = state() + const server = await UCAN.server(serverInput) + + return { type: "SET_SERVER", server }; +} + +/** @returns {Promise} */ +async function fetchDbContents() { + const db = state().database + if (!db) return { type: "-" } + + /** @type {AllDocsResponse<{ text: string }>} */ + const docs = await db.allDocs(); + + /** @type {[string, string][]} */ + const contents = docs.rows.map(row => { + return [row.value._id, row.value.text] + }) + + return { type: "SET_DATABASE_CONTENTS", contents: new Map(contents) } +} + +/** @returns {Promise} */ +async function login() { + const { agent, email } = state() + + if (!email) return { type: "-" } + + const promise = UCAN.login({ + agent, + email: UCAN.email(email) + }) + + return { type: "WAIT_FOR_LOGIN", promise } +} + /** @returns {Msg} */ function saveConfig() { - const { clock, databaseName, email, server } = state(); + const { clock, email, server } = state(); localStorage.setItem( "config", JSON.stringify({ clockId: "storeName" in clock ? undefined : clock.id.did(), - databaseName, email, server: server.uri.toString(), }) @@ -70,6 +248,35 @@ function saveConfig() { return { type: "-" }; } +/** @param {`${string}@${string}`} toEmail */ +function shareWithEmail(toEmail) { + /** @returns {Promise} */ + return async () => { + const { agent, clock, email, server } = state() + + if (!email) throw new Error("Expected `state.email` to be defined.") + if (!("storeName" in clock)) throw new Error("Expected a clock delegation to be present.") + + const { cid } = await UCAN.share({ + from: UCAN.email(email), + to: UCAN.email(toEmail) + }, { + agent, clock, server, + }) + + return { type: "SHARED_WITH_EMAIL", cid, email: toEmail }; + } +} + +/** @param {Promise} promise */ +function waitForLogin(promise) { + /** @returns {Promise} */ + return async () => { + await promise + return { type: "SET_LOGGED_IN", loggedIn: true } + } +} + // Setup // ===== @@ -78,19 +285,38 @@ const storedState = localStorage.getItem("config"); /** @type {Record | undefined} */ const config = storedState ? JSON.parse(storedState) : undefined; -const databaseName = config?.databaseName || DEFAULT_DB_NAME; -const server = await UCAN.server(config?.server); -const agent = await UCAN.agent({ server }); -const email = config?.email ? UCAN.email(config.email) : undefined; -const clock = await UCAN.clock({ audience: email || agent.agent, databaseName }); +/** @type {State} */ +const initialState = await (async () => { + const server = await UCAN.server(config?.server).catch(async () => { + return await UCAN.server() + }); -export const [state, send] = store({ - state: { + const agent = await UCAN.agent({ server }); + const email = config?.email ? UCAN.email(config.email) : undefined; + const clock = config?.clockId ? UCAN.clockId(config.clockId) : await UCAN.clock({ audience: email || agent.agent }); + + if (clock.isNew && email) { + await UCAN.registerClock({ clock, server }) + } + + return { agent, clock, - databaseName, + clockIdInput: config?.clockId, + databaseContents: "loading", + loggedIn: email ? await UCAN.isLoggedIn({ agent, email }) : false, server, - }, + serverInput: server.id.did() !== (await UCAN.server()).id.did() ? server.uri.toString() : undefined, + email: config?.email + } +})() + +// Setup & export store +export const [state, send] = store({ + state: initialState, update, middleware: fxware(fx), }); + +// Setup database & connect +send({ type: "CONNECT" }) diff --git a/examples/ucan/browser/src/types.d.ts b/examples/ucan/browser/src/types.d.ts index ce87e0c1..d8bf5b50 100644 --- a/examples/ucan/browser/src/types.d.ts +++ b/examples/ucan/browser/src/types.d.ts @@ -1,18 +1,41 @@ -import { AgentWithStoreName, Clock, ClockWithoutDelegation, Server } from "@fireproof/connect/ucan"; +import { Database } from "@fireproof/core"; +import { AgentWithStoreName, Clock, ClockWithoutDelegation, Server } from "@fireproof/ucan"; +import { Delegation } from "@ucanto/interface"; // 🪄 export type State = { agent: AgentWithStoreName; clock: Clock | ClockWithoutDelegation; - databaseName: string; - email?: string; - server: Server; + clockIdInput?: `did:key:${string}` + database?: Database + databaseContents: Map | "loading" + email?: `${string}@${string}` + loggedIn: boolean | "in-progress" + server: Server + serverInput?: string + shareClaims?: Delegation[] | "loading" + shareStatus?: { type: "SHARED"; cid: string; email: `${string}@${string}` } | { type: "LOADING" } }; // 📣 export type Msg = | { type: "-" } + | { type: "CLAIM_ALL_SHARES" } + | { type: "CLAIMED_SHARES", delegations: Delegation[] } + | { type: "CONNECT" } + | { type: "CONNECTED"; database: Database } + | { type: "LOGIN" } + | { type: "DATABASE_CONTENTS_CHANGED" } + | { type: "SET_AGENT"; agent: AgentWithStoreName } | { type: "SET_CLOCK"; clock: Clock | ClockWithoutDelegation } - | { type: "SET_DATABASE_NAME"; name: string }; + | { type: "SET_CLOCK_ID_INPUT"; clockId: string } + | { type: "SET_DATABASE_CONTENTS"; contents: Map } + | { type: "SET_EMAIL"; email: string } + | { type: "SET_LOGGED_IN"; loggedIn: State["loggedIn"] } + | { type: "SET_SERVER"; server: Server } + | { type: "SET_SERVER_INPUT"; server: string } + | { type: "SHARE_WITH_EMAIL"; email: `${string}@${string}` } + | { type: "SHARED_WITH_EMAIL"; cid: string; email: `${string}@${string}` } + | { type: "WAIT_FOR_LOGIN"; promise: Promise }; diff --git a/examples/ucan/browser/src/view.js b/examples/ucan/browser/src/view.js index c4f283ea..077d1d1b 100644 --- a/examples/ucan/browser/src/view.js +++ b/examples/ucan/browser/src/view.js @@ -1,8 +1,8 @@ -import { tags, text } from "spellcaster/hyperscript.js"; +import { repeat, tags, text } from "spellcaster/hyperscript.js"; import "./index.css"; import { state, send } from "./state.js"; -import { computed } from "spellcaster/spellcaster.js"; +import { computed, effect } from "spellcaster/spellcaster.js"; /** * @typedef {import("spellcaster/hyperscript.js").Props} Props @@ -13,8 +13,10 @@ import { computed } from "spellcaster/spellcaster.js"; const { a, + br, button, div, + em, fieldset, footer, form, @@ -26,6 +28,7 @@ const { hr, input, label, + li, main, mark, p, @@ -33,6 +36,7 @@ const { small, span, strong, + ul, } = tags; // 🛠️ @@ -70,7 +74,7 @@ const Clock = () => hgroup({}, [h2({}, text("Clock"))]), // Form - form({}, [ + form({ onsubmit: preventDefault }, [ fieldset({}, [ Label({ for: "clock" }, "Custom clock ID"), input( @@ -79,7 +83,13 @@ const Clock = () => name: "clock", type: "text", - value: "storeName" in state().clock ? "" : state().clock.id.did(), + value: state().clockIdInput || "", + + /** + * @param event {object} + * @param event.target {HTMLInputElement} + */ + onchange: (event) => send({ type: "SET_CLOCK_ID_INPUT", clockId: event.target.value }), }, [] ), @@ -91,38 +101,173 @@ const Clock = () => p({}, [mark({}, text(computed(() => state().clock.id.did())))]), ]); -// DATABASE NAME +// CLAIM SHARE -const Database = () => +const ClaimShare = () => section({}, [ + + // Header + hgroup({}, [ + h2({}, text("Claim share")), + p({}, [ + small({}, [ + span({}, text("Retrieve the UCAN delegation for a share.")), + ]), + ]), + ]), + + // Buttons + p({}, [ + button({ + onclick: () => { + const { loggedIn } = state() + + if (loggedIn !== true) { + alert("Need to be logged in first before you can claim shares.") + return + } + + send({ type: "CLAIM_ALL_SHARES" }) + } + }, text("Claim all shares")) + ]), + + // Delegations + div({}, element => { + const signal = computed(() => { + const { shareClaims } = state() + if (!shareClaims) return span({}, []) + if (shareClaims === "loading") return p({}, [ + small({ ariaBusy: "true" }, text("Loading delegations")) + ]) + + console.log(shareClaims.map(d => { + return { + iss: d.issuer.did(), + aud: d.audience.did(), + caps: JSON.stringify(d.capabilities) + } + })) + + const clockDIDs = shareClaims.flatMap(d => { + const cap = d.capabilities[0] + if (cap.can === "clock/*") return [ cap.with ] + return [] + }) + + if (clockDIDs.length === 0) return p({}, text("No shares found.")) + const activeClock = state().clock.id.did() + + return div({}, [ + p({}, text("Available databases:")), + ul({}, clockDIDs.map(did => { + return li({}, [ + a({ + style: "cursor: pointer; word-break: break-all;", + title: "Click to use database", + onclick: () => { + send({ type: "SET_CLOCK_ID_INPUT", clockId: did }) + } + }, text( + did === activeClock + ? `⚡ ${did} (active)` + : did + )) + ]) + })) + ]) + }) + + return effect(() => { + element.replaceChildren(signal()) + }) + }) + +]) + +// DATABASE DATA + +const Data = () => section({}, [ // Header - hgroup({}, [h2({}, text("Database name"))]), + hgroup({}, [h2({}, text("Database contents"))]), - // Form - form({ onsubmit: preventDefault }, [ - fieldset({}, [ - Label({ for: "database" }, "Database name"), + // Add data + form({ + + /** + * @param event {Event & { target: HTMLElement }} + */ + onsubmit: async (event) => { + event.preventDefault() + + const db = state().database + const form = event.target + + if (!db || !form) return + + const input = /** @type {HTMLInputElement | null} */ (event.target.querySelector('input[name="data"]')) + const val = input && input.value.trim() + if (val && val.length) await db.put({ text: val }) + + send({ type: "DATABASE_CONTENTS_CHANGED" }) + if (input) input.value = "" + } + + }, [ + Label({ for: "data" }, "Add data"), + fieldset({ role: "group" }, [ input( { - "aria-label": "Database name", - - /** - * @param event {object} - * @param event.target {HTMLInputElement} - */ - onchange: (event) => send({ type: "SET_DATABASE_NAME", name: event.target.value }), - name: "database", + "aria-label": "Add data", + name: "data", type: "text", - value: state().databaseName, + required: true + }, + [] + ), + input( + { + value: "Add", + type: "submit" }, [] ), ]), ]), + // Contents + div({}, element => { + const signal = computed(() => { + const contents = state().databaseContents + + if (contents === "loading") { + return p({}, [ + small({ ariaBusy: "true" }, text("Loading database contents")) + ]) + } + + return ul({}, repeat( + computed(() => contents), + row => li({}, text(row)) + )) + }) + + return effect(() => { + element.replaceChildren(signal()) + }) + }) + ]) + +// DATABASE NAME + +const Database = () => + section({}, [ + // Header + hgroup({}, [h2({}, text("Database name"))]), + // Using Label({}, "Utilised database name"), - p({}, [mark({}, text(computed(() => state().databaseName)))]), + p({}, text("Using the clock DID as the database name.")), ]); // EMAIL @@ -138,13 +283,65 @@ const Email = () => ]), // Form - form({}, [ + form({ onsubmit: preventDefault }, [ fieldset({}, [ Label({ for: "email" }, "Email address"), - input({ "aria-label": "Email address", autocomplete: "email", name: "email", type: "email" }, []), + input({ + "aria-label": "Email address", + autocomplete: "email", + name: "email", + type: "email", + + value: state().email || "", + + /** + * @param event {object} + * @param event.target {HTMLInputElement} + */ + onchange: (event) => send({ type: "SET_EMAIL", email: event.target.value }), + }, []), ]), ]), + // Logged in + div({}, element => { + const signal = computed(() => { + const { email, loggedIn } = state() + + if (email === undefined) { + return div({}, [ + Label({}, "No login needed when not using an email address"), + p({}, [ span({}, text("☑️")) ]) + ]) + } + + if (loggedIn === true) { + return div({}, [ + Label({}, "Logged in successfully"), + p({}, [ span({}, text("☑️")) ]) + ]) + } + + if (loggedIn === "in-progress") { + return div({}, [ + Label({}, "Logging in ..."), + p({}, [ span({}, text("Check your email inbox ⚡")) ]) + ]) + } + + return div({}, [ + Label({}, "Login required"), + p({}, [ + button({ onclick: () => send({ type: "LOGIN" }) }, text("Log in")) + ]) + ]) + }) + + return effect(() => { + element.replaceChildren(signal()) + }) + }), + // Using Label({}, "Utilised clock delegation"), p({}, [ @@ -170,10 +367,23 @@ const Server = () => ]), // Form - form({}, [ + form({ onsubmit: preventDefault }, [ fieldset({}, [ Label({ for: "server" }, "Custom server URL"), - input({ "aria-label": "Custom server URL", autocomplete: "url", name: "server", type: "text" }, []), + input({ + "aria-label": "Custom server URL", + autocomplete: "url", + name: "server", + type: "text", + + value: state().serverInput || "", + + /** + * @param event {object} + * @param event.target {HTMLInputElement} + */ + onchange: (event) => send({ type: "SET_SERVER_INPUT", server: event.target.value }), + }, []), ]), ]), @@ -182,6 +392,106 @@ const Server = () => p({}, [mark({}, text(computed(() => state().server.uri.toString())))]), ]); +// SHARE + +export const Share = () => + section({}, [ + + // Header + hgroup({}, [ + h2({}, text("Share")), + p({}, [ + small({}, [ + span({}, text("Share the database with an email address. Note that sharing with a specific agent is possible too, but not enabled here.")), + ]), + ]), + ]), + + // Form + form({ + + /** + * @param event {Event & { target: HTMLElement }} + */ + onsubmit: async (event) => { + event.preventDefault() + + const { loggedIn } = state() + + if (loggedIn !== true) { + alert("Need to be logged in first before you can share.") + return + } + + const form = event.target + if (!form) return + + const input = /** @type {HTMLInputElement | null} */ (event.target.querySelector('input[name="shareTarget"]')) + const val = input?.value?.trim() + if (val && val.length) { + send({ type: "SHARE_WITH_EMAIL", email: /** @type {`${string}@${string}`} */ (val) }) + if (input) input.value = "" + } + } + + }, [ + Label({ for: "shareTarget" }, "Email address"), + fieldset({ role: "group" }, [ + input( + { + "aria-label": "Email address", + name: "shareTarget", + type: "email", + required: true + }, + [] + ), + input( + { + value: "Share", + type: "submit" + }, + [] + ), + ]), + ]), + + // Status + p({}, element => { + const signal = computed(() => { + const {email, shareStatus} = state() + if (shareStatus === undefined) return span({}, []) + + switch (shareStatus.type) { + + case "LOADING": + return p({}, [ + small({ ariaBusy: "true" }, text("Creating share delegation and invoking share authorization")) + ]) + + case "SHARED": + return p({}, [ + small({}, [ + span({}, text(`Shared database with: `)), + mark({}, text(shareStatus.email)), + br({}), + span({}, text(`Share CID: `)), + mark({}, text(shareStatus.cid)), + br({}), + span({}, text(`Check your email inbox (${email}) to confirm the share.`)), + ]) + ]) + + } + }) + + return effect(() => { + element.replaceChildren(signal()) + }) + }) + + ]); + // 🔮 export const Header = () => @@ -193,4 +503,4 @@ export const Header = () => ]); export const Main = () => - main({ className: "container" }, [Database(), hr(), Server(), hr(), Agent(), hr(), Email(), hr(), Clock()]); + main({ className: "container" }, [Data(), hr(), ClaimShare(), hr(), Share(), hr(), Clock(), hr(), Email(), hr(), Agent(), hr(), Server(), hr(), Database()]); diff --git a/examples/ucan/node/package.json b/examples/ucan/node/package.json index a06b63b8..39f60562 100644 --- a/examples/ucan/node/package.json +++ b/examples/ucan/node/package.json @@ -3,7 +3,7 @@ "type": "module", "dependencies": { "@fireproof/connect": "../../../", - "@fireproof/core": "0.19.111", + "@fireproof/core": "0.19.113", "meow": "^13.2.0" } } diff --git a/examples/ucan/workshop/participants/.gitignore b/examples/ucan/workshop/participants/.gitignore index 970aa870..e13ecfc8 100644 --- a/examples/ucan/workshop/participants/.gitignore +++ b/examples/ucan/workshop/participants/.gitignore @@ -1,2 +1 @@ -delegate.js .my diff --git a/examples/ucan/workshop/participants/db.js b/examples/ucan/workshop/participants/db.js index 25719ff4..1cb7ed9d 100644 --- a/examples/ucan/workshop/participants/db.js +++ b/examples/ucan/workshop/participants/db.js @@ -17,14 +17,6 @@ import { isNotFoundError } from "@fireproof/core"; export async function addImage(db, did, image) { let images = [image]; - try { - /** @type {DocWithId<{ images: Uint8Array[] }>} */ - const existing = await db.get("images"); - images = [...existing.images, ...images]; - } catch (err) { - if (!isNotFoundError(err)) throw err; - } - await db.put({ did, images, diff --git a/examples/ucan/workshop/participants/delegate.js b/examples/ucan/workshop/participants/delegate.js index 0627a6ec..d1fa2fd8 100644 --- a/examples/ucan/workshop/participants/delegate.js +++ b/examples/ucan/workshop/participants/delegate.js @@ -20,7 +20,7 @@ const dbName = "my-db"; const agent = await FP_UCAN.agent(); const delegation = await FP_UCAN.delegation.extract( base64pad.baseDecode( - "OqJlcm9vdHOB2CpYJQABcRIgMONvy395DjCxwwV9M2AWpaupV5tkGiz1nHmgP8jNqMpndmVyc2lvbgGgAgFxEiDgbzFAsk09dCPqq3iKotq52FnNhUeRwHyR5PS4IjsGDqdhc1hE7aEDQJLgk41xXGwlz1m2xyPbyI19MJmLNz/iQ1JyrssyVpMW/ouOQsRk78xjgRvzyTc9J+GsVnHU9bTx69bpir3DGAxhdmUwLjkuMWNhdHSBomNjYW5nY2xvY2svKmR3aXRoeDhkaWQ6a2V5Ono2TWtmWndNNlh2WWJhQWkyWUY0QmNETVh1VU5RaFBidm9VMjlOendNZ050UTV2bWNhdWRYIu0BrNT3zi6/YUh3ABUiWZ6+4Cj/sHOE9n/f4FGPt1oX5f5jZXhw9mNpc3NYIu0BEJGcSFMh9yKb403zbg8HAY+wHuuDAlHXBOf7bNQ3hGZjcHJmgMkCAXESIHfLtChi5rBexOEFOHiZwe001mu/zapwvz6oavN1wUAFp2FzWETtoQNAcW2OJvOqLhGAo96u4uXXSfJV/MXQ2Vl3Lk1kKniGy647dGPoYNsrCBtESaihdiFilzEGQC2k1jX4pKXQmlvuBGF2ZTAuOS4xY2F0dIGiY2NhbmdjbG9jay8qZHdpdGh4OGRpZDprZXk6ejZNa2Zad002WHZZYmFBaTJZRjRCY0RNWHVVTlFoUGJ2b1UyOU56d01nTnRRNXZtY2F1ZFgi7QGr9nJuLwp0nEDgRD++xMEevJxeidIR77e76vGnnmmJyWNleHD2Y2lzc1gi7QGs1PfOLr9hSHcAFSJZnr7gKP+wc4T2f9/gUY+3Whfl/mNwcmaB2CpYJQABcRIg4G8xQLJNPXQj6qt4iqLaudhZzYVHkcB8keT0uCI7Bg5ZAXESIDDjb8t/eQ4wscMFfTNgFqWrqVebZBos9Zx5oD/IzajKoWp1Y2FuQDAuOS4x2CpYJQABcRIgd8u0KGLmsF7E4QU4eJnB7TTWa7/NqnC/Pqhq83XBQAU=" + "OqJlcm9vdHOB2CpYJQABcRIgak1f/Nl35ehXXk1mwrklbjxGGFE5FcGOamNHOpXa8PhndmVyc2lvbgGgAgFxEiAXetZ5fTs5dFd1hkd3uY+D6R78iNXdV6LPId7oV44KLqdhc1hE7aEDQNr8nFBFbSlZdAYeaWNnkLB/PN8zHSQxR4QusHtYUGnmRSFDeG84pgxUr0SKXrphgBJ57MhfF+PWBaATlZgkEw1hdmUwLjkuMWNhdHSBomNjYW5nY2xvY2svKmR3aXRoeDhkaWQ6a2V5Ono2TWtoVkJkc2taNG5DNXc1QWYyY0dVS2lDNTdXa1RQbzRiNXlRNHk3VUNROURQdWNhdWRYIu0B8zvGpkbGLiEUyG1YAlZM3axkYRujDuzvYG0mYXZkZeBjZXhw9mNpc3NYIu0BLRE8vJ9xkSiDAwcj8rK51vXi6iE9UEP0ZGpczLz5uDBjcHJmgMkCAXESIPJ4dolMIjVMKtpPSLs1mwr5xnExO9LTFEqchUgEoYoVp2FzWETtoQNAXc3f4sur0/Kbi7UXmr7g0q4L+OgNB5w/59GHV3UNAz21nsyg8JyjzFSecjNLnNINNHWhZUB632Cd+ywhTokqDWF2ZTAuOS4xY2F0dIGiY2NhbmdjbG9jay8qZHdpdGh4OGRpZDprZXk6ejZNa2hWQmRza1o0bkM1dzVBZjJjR1VLaUM1N1drVFBvNGI1eVE0eTdVQ1E5RFB1Y2F1ZFgi7QGr9nJuLwp0nEDgRD++xMEevJxeidIR77e76vGnnmmJyWNleHD2Y2lzc1gi7QHzO8amRsYuIRTIbVgCVkzdrGRhG6MO7O9gbSZhdmRl4GNwcmaB2CpYJQABcRIgF3rWeX07OXRXdYZHd7mPg+ke/IjV3VeizyHe6FeOCi5ZAXESIGpNX/zZd+XoV15NZsK5JW48RhhRORXBjmpjRzqV2vD4oWp1Y2FuQDAuOS4x2CpYJQABcRIg8nh2iUwiNUwq2k9IuzWbCvnGcTE70tMUSpyFSAShihU=" ) ); @@ -49,5 +49,5 @@ await addImage(db, agent.id.did(), img); console.log("Added"); -await db.close(); -process.exit(0); +// await db.close(); +// process.exit(0); diff --git a/examples/ucan/workshop/participants/package.json b/examples/ucan/workshop/participants/package.json index 672f5f5c..45740c7a 100644 --- a/examples/ucan/workshop/participants/package.json +++ b/examples/ucan/workshop/participants/package.json @@ -2,8 +2,8 @@ "private": true, "type": "module", "dependencies": { - "@fireproof/core": "0.19.111", - "@fireproof/ucan": "0.19.112-dev-nf1", + "@fireproof/core": "0.19.113", + "@fireproof/ucan": "../../../../dist/ucan", "multiformats": "^13.3.1" } } diff --git a/examples/ucan/workshop/participants/pnpm-lock.yaml b/examples/ucan/workshop/participants/pnpm-lock.yaml index e9b1de81..1d93aed5 100644 --- a/examples/ucan/workshop/participants/pnpm-lock.yaml +++ b/examples/ucan/workshop/participants/pnpm-lock.yaml @@ -9,11 +9,11 @@ importers: .: dependencies: '@fireproof/core': - specifier: 0.19.111 - version: 0.19.111(react@18.3.1) + specifier: 0.19.113 + version: 0.19.113(react@18.3.1) '@fireproof/ucan': - specifier: 0.19.112-dev-nf1 - version: 0.19.112-dev-nf1(encoding@0.1.13)(react@18.3.1) + specifier: ../../../../dist/ucan + version: link:../../../../dist/ucan multiformats: specifier: ^13.3.1 version: 13.3.1 @@ -24,13 +24,10 @@ packages: resolution: {integrity: sha512-Zhmr4f0/UohFh3O/6H63DoBenYjh72uGZOcEnDZ/VxmBvZelACkCR4g06c8rbZbJTu20f3gRSNnJZbmtdMOFgQ==} engines: {node: '>=16'} - '@fireproof/core@0.19.111': - resolution: {integrity: sha512-LJsXkGpMtDIvabX8YU24x33BV/oL1o6XdDAfbC2TpoRyNZ8pkqohibzHor+LFriMdRLtO2yqPkad2XnKgRZOqw==} + '@fireproof/core@0.19.113': + resolution: {integrity: sha512-LGAgDBd8MePZ2QUaBav2Wd1pa37SvYfngNAaDh00WGCL9skF+y4ZhcVmhUGNcIKG3xcANsyxouFu7h0rgBoNeA==} peerDependencies: - react: '>=18.0.0' - - '@fireproof/ucan@0.19.112-dev-nf1': - resolution: {integrity: sha512-D1lDMHuNT2T0d9rSWz53TS2bZM2FKWnKOW6ORpiPJ2sl2YEgOaNURBNUjkDXVGnwShMIfxUylcYMs0MWsBXRWg==} + react: ^18.3.1 '@ipld/car@5.3.3': resolution: {integrity: sha512-4vgV5Ml4HCJ2iTx7vYhu0ui+Xxo1HQTtVeYgD+JKd5Wij8TlOFZnxOSickqpLcuf1fdGEStgqVItx15UWfzDYA==} @@ -48,12 +45,6 @@ packages: resolution: {integrity: sha512-ueULCaaSCcD+dQga6nKiRr+RSeVgdiYiEPKVUu5iQMNYDN+9osd0KpR3UDd9uQQ+6RWuv9L34SchfEwj7YIbOA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@ipld/dag-ucan@3.4.0': - resolution: {integrity: sha512-sW4R43w3DbEdoGWWJZCwsblwXa600HCanG9p2w1MJPVBNTNjhvqc3XI0uEqKhT2oqKWrND7uInVtcPmZme7hhA==} - - '@ipld/unixfs@2.2.0': - resolution: {integrity: sha512-lDQ2eRhJlbFaBoO3bhOmDVCLmpOnhwtwbilqUgAAhbhoPSmLrnv7gsBuToZjXOdPaEGSL7apkmm6nFrcU6zh4Q==} - '@ipld/unixfs@3.0.0': resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} @@ -79,17 +70,6 @@ packages: resolution: {integrity: sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@noble/curves@1.6.0': - resolution: {integrity: sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==} - engines: {node: ^14.21.3 || >=16} - - '@noble/ed25519@1.7.3': - resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} - - '@noble/hashes@1.5.0': - resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} - engines: {node: ^14.21.3 || >=16} - '@perma/map@1.0.3': resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} @@ -123,99 +103,19 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@scure/base@1.1.9': - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - - '@scure/bip39@1.4.0': - resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} - - '@storacha/one-webcrypto@1.0.1': - resolution: {integrity: sha512-bD+vWmcgsEBqU0Dz04BR43SA03bBoLTAY29vaKasY9Oe8cb6XIP0/vkm0OS2UwKC13c8uRgFW4rjJUgDCNLejQ==} - - '@types/minimatch@3.0.5': - resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - '@types/node@22.8.7': resolution: {integrity: sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==} - '@types/retry@0.12.1': - resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} - '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} - '@ucanto/client@9.0.1': - resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} - - '@ucanto/core@10.0.1': - resolution: {integrity: sha512-1BfUaJu0/c9Rl/WdZSDbScJJLsPsPe1g4ynl5kubUj3xDD/lyp/Q12PQVQ2X7hDiWwkpwmxCkRMkOxwc70iNKQ==} - - '@ucanto/interface@10.0.1': - resolution: {integrity: sha512-+Vr/N4mLsdynV9/bqtdFiq7WsUf3265/Qx2aHJmPtXo9/QvWKthJtpe0g8U4NWkWpVfqIFvyAO2db6D9zWQfQw==} - - '@ucanto/principal@9.0.1': - resolution: {integrity: sha512-8eAvaZHW1vyET4X90rkJv6pmW1IOdEYlZYwO3wDgTkC5m9VytBEywCvpzP57cavdYIbbPse5QS9nMEGvk87zhw==} - - '@ucanto/transport@9.1.1': - resolution: {integrity: sha512-3CR17nEemOVaTuMZa6waWgVL4sLxSPcxYvpaNeJ6NZo1rfsqdyRXOtbVV/RcI2BtUL0Cao6JM6P9+gdghfc5ng==} - - '@ucanto/validator@9.0.2': - resolution: {integrity: sha512-LxhRbDMIoLt9LYHq/Rz1WCEH8AtmdsBTS/it28Ij/A3W0zyoSwUpAUxBtXaKRh/gpbxdWmjxX+nVfFJYL//b4g==} - - '@web3-storage/access@20.1.0': - resolution: {integrity: sha512-IY6ICPRWE8++2jxvy+LzAiFvwAOIHR8cu9eNt+VT5sAFE796o4ma7GSU0eXRCiShmV2n6iSWAwWRT6XD5zIqPA==} - - '@web3-storage/blob-index@1.0.4': - resolution: {integrity: sha512-04+PrmVHFT+xzRhyIPdcvGc8Y2NDffUe8R1gJOyErVzEVz5N1I9Q/BrlFHYt/A4HrjM5JBsxqSrZgTIkjfPmLA==} - engines: {node: '>=16.15'} - - '@web3-storage/capabilities@17.4.0': - resolution: {integrity: sha512-2VNLTTvv9qVewtXiek2Fb6W7WTQgOonq+FcNV9PyXAEgcXsQWsm8dOmbeB83W9bAuiwe9uIOzC1rftDHY3+uYA==} - - '@web3-storage/data-segment@5.3.0': - resolution: {integrity: sha512-zFJ4m+pEKqtKatJNsFrk/2lHeFSbkXZ6KKXjBe7/2ayA9wAar7T/unewnOcZrrZTnCWmaxKsXWqdMFy9bXK9dw==} - - '@web3-storage/did-mailto@2.1.0': - resolution: {integrity: sha512-TRmfSXj1IhtX3ESurSNOylZSBKi0z/VJNoMLpof+AVRdovgZjjocpiePQTs2pfHKqHTHfJXc9AboWyK4IKTWMw==} - engines: {node: '>=16.15'} - - '@web3-storage/filecoin-client@3.3.4': - resolution: {integrity: sha512-T2xur1NPvuH09yajyjCWEl7MBH712nqHERj51w4nDp6f8libMCKY6lca0frCrm4OC5s8oy0ZtoRFhsRYxgTzSg==} - '@web3-storage/pail@0.6.0': resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} hasBin: true - '@web3-storage/upload-client@17.1.0': - resolution: {integrity: sha512-0tUMe4Ez9gmUZjgn1Nrl6HYdGEsYyeLa6JrpoXcCGTQDBW2FehALc+GZZeoIjYQexRpw+qt9JstuJNN9dUNETw==} - - '@web3-storage/w3up-client@16.4.0': - resolution: {integrity: sha512-ndHXVufBt6bVyZHHxpe+bgS9bnOtpREsYFtL/C2h/AL8O5LZ1QBM91wFHVvLhFOJcKVcbW2WagyivCr+NOp9WA==} - engines: {node: '>=18'} - actor@2.3.1: resolution: {integrity: sha512-ST/3wnvcP2tKDXnum7nLCLXm+/rsf8vPocXH2Fre6D8FQwNkGDd4JEitBlXj007VQJfiGYRQvXqwOBZVi+JtRg==} - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - - any-signal@3.0.1: - resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} - - atomically@2.0.3: - resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -223,28 +123,12 @@ packages: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} - bigint-mod-arith@3.3.1: - resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} - engines: {node: '>=10.4.0'} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - browser-readablestream-to-it@1.0.3: - resolution: {integrity: sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - carstream@2.2.0: - resolution: {integrity: sha512-/gHkK0lQjmGM45fhdx8JD+x7a1XS1qUk3T9xWWSt3oZiWPLq4u/lnDstp+N55K7hqTKKlb0CCr43EHTrlbmJSQ==} - cborg@4.2.6: resolution: {integrity: sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==} hasBin: true @@ -252,50 +136,9 @@ packages: charwise@3.0.1: resolution: {integrity: sha512-RcdumNsM6fJZ5HHbYunqj2bpurVRGsXour3OR+SlLEHFhG6ALm54i6Osnh+OvO7kEoSBzwExpblYFH8zKQiEPw==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - conf@11.0.2: - resolution: {integrity: sha512-jjyhlQ0ew/iwmtwsS2RaB6s8DBifcE2GYBEaw2SJDUY/slJJbNfY4GlDVzOs/ff8cM/Wua5CikqXgbFl5eu85A==} - engines: {node: '>=14.16'} - - debounce-fn@5.1.2: - resolution: {integrity: sha512-Sr4SdOZ4vw6eQDvPYNxHogvrxmCIld/VenC5JbNrFwMiwd7lY/Z18ZFfo+EWNG4DD9nFlAujWAo/wGuOPHmy5A==} - engines: {node: '>=12'} - - dot-prop@7.2.0: - resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - electron-fetch@1.9.1: - resolution: {integrity: sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==} - engines: {node: '>=6'} - - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - - env-paths@3.0.0: - resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - err-code@3.0.1: - resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} - eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - - fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - - get-iterator@1.0.2: - resolution: {integrity: sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==} - hamt-sharding@3.0.6: resolution: {integrity: sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==} @@ -303,10 +146,6 @@ packages: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - idb@8.0.0: resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} @@ -328,34 +167,13 @@ packages: ipfs-unixfs@11.2.0: resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} - ipfs-utils@9.0.14: - resolution: {integrity: sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - is-electron@2.2.2: - resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} - is-network-error@1.1.0: resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} engines: {node: '>=16'} - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - iso-url@1.2.1: - resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} - engines: {node: '>=12'} - - it-all@1.0.6: - resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} - it-filter@3.1.1: resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} - it-glob@1.0.2: - resolution: {integrity: sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==} - it-last@3.0.6: resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} @@ -381,18 +199,9 @@ packages: it-stream-types@2.0.2: resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} - it-to-stream@1.0.0: - resolution: {integrity: sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-schema-typed@8.0.1: - resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} - long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -404,25 +213,6 @@ packages: resolution: {integrity: sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==} engines: {node: '>= 4.0.0'} - merge-options@3.0.4: - resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} - engines: {node: '>=10'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - multiformats@11.0.2: - resolution: {integrity: sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - multiformats@12.1.3: - resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - multiformats@13.3.1: resolution: {integrity: sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==} @@ -430,43 +220,14 @@ packages: resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} engines: {node: '>=8.0.0'} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - native-fetch@3.0.0: - resolution: {integrity: sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==} - peerDependencies: - node-fetch: '*' - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-sql-parser@3.9.4: resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} engines: {node: '>=8'} - one-webcrypto@1.0.3: - resolution: {integrity: sha512-fu9ywBVBPx0gS9K0etIROTiCkvI5S1TDjFsYFb3rC1ewFxeOqsbzq7aIMBHsYfrTHBcGXJaONXXjTl8B01cW1Q==} - - p-defer@3.0.0: - resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} - engines: {node: '>=8'} - p-defer@4.0.1: resolution: {integrity: sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==} engines: {node: '>=12'} - p-fifo@1.0.0: - resolution: {integrity: sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A==} - p-limit@6.1.0: resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} engines: {node: '>=18'} @@ -479,10 +240,6 @@ packages: resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} engines: {node: '>=18'} - p-retry@5.1.2: - resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-retry@6.2.0: resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} engines: {node: '>=16.17'} @@ -507,9 +264,6 @@ packages: rabin-rs@2.1.0: resolution: {integrity: sha512-5y72gAXPzIBsAMHcpxZP8eMDuDT98qMP1BqSDHRbHkJJXEgWIN1lA47LxUqzsK6jknOJtgfkQr9v+7qMlFDm6g==} - react-native-fetch-api@3.0.0: - resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} - react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -518,10 +272,6 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -529,38 +279,18 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - sparse-array@1.3.2: resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} - stream-to-it@0.2.4: - resolution: {integrity: sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - stubborn-fs@1.2.5: - resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} - - sync-multihash-sha2@1.0.0: - resolution: {integrity: sha512-A5gVpmtKF0ov+/XID0M0QRJqF2QxAsj3x/LlDC8yivzgoYCoWkV+XaZPfVu7Vj1T/hYzYS1tfjwboSbXjqocug==} - thingies@1.21.0: resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} engines: {node: '>=10.18'} peerDependencies: tslib: ^2 - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tree-dump@1.0.2: resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} engines: {node: '>=10.0'} @@ -578,49 +308,24 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - - type-fest@4.26.1: - resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} - engines: {node: '>=16'} - uint8-varint@2.0.4: resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} uint8arraylist@2.4.8: resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} - uint8arrays@4.0.10: - resolution: {integrity: sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==} - uint8arrays@5.1.0: resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - use-fireproof@0.19.111: - resolution: {integrity: sha512-bmRWaYrtyq0+2ewDj0cLJ8FQL3osUe0j7p89DT2dQ13sji5Td2oTXWgXZVfTPCbC8LF6qW4zXVQ4Cks4SToEaw==} - peerDependencies: - react: '>=18.0.0' - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} varint@6.0.0: resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - when-exit@2.1.3: - resolution: {integrity: sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==} - yaml@2.6.0: resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} engines: {node: '>= 14'} @@ -639,7 +344,7 @@ snapshots: transitivePeerDependencies: - typescript - '@fireproof/core@0.19.111(react@18.3.1)': + '@fireproof/core@0.19.113(react@18.3.1)': dependencies: '@adviser/cement': 0.2.36 '@ipld/car': 5.3.3 @@ -661,27 +366,6 @@ snapshots: transitivePeerDependencies: - typescript - '@fireproof/ucan@0.19.112-dev-nf1(encoding@0.1.13)(react@18.3.1)': - dependencies: - '@fireproof/core': 0.19.111(react@18.3.1) - '@ipld/dag-cbor': 9.2.2 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/access': 20.1.0 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - '@web3-storage/w3up-client': 16.4.0(encoding@0.1.13) - multiformats: 13.3.1 - use-fireproof: 0.19.111(react@18.3.1) - transitivePeerDependencies: - - encoding - - react - - typescript - '@ipld/car@5.3.3': dependencies: '@ipld/dag-cbor': 9.2.2 @@ -703,22 +387,6 @@ snapshots: dependencies: multiformats: 13.3.1 - '@ipld/dag-ucan@3.4.0': - dependencies: - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 - multiformats: 11.0.2 - - '@ipld/unixfs@2.2.0': - dependencies: - '@ipld/dag-pb': 4.1.3 - '@multiformats/murmur3': 2.1.8 - '@perma/map': 1.0.3 - actor: 2.3.1 - multiformats: 11.0.2 - protobufjs: 7.4.0 - rabin-rs: 2.1.0 - '@ipld/unixfs@3.0.0': dependencies: '@ipld/dag-pb': 4.1.3 @@ -750,14 +418,6 @@ snapshots: multiformats: 13.3.1 murmurhash3js-revisited: 3.0.0 - '@noble/curves@1.6.0': - dependencies: - '@noble/hashes': 1.5.0 - - '@noble/ed25519@1.7.3': {} - - '@noble/hashes@1.5.0': {} - '@perma/map@1.0.3': dependencies: '@multiformats/murmur3': 2.1.8 @@ -786,272 +446,40 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@scure/base@1.1.9': {} - - '@scure/bip39@1.4.0': - dependencies: - '@noble/hashes': 1.5.0 - '@scure/base': 1.1.9 - - '@storacha/one-webcrypto@1.0.1': {} - - '@types/minimatch@3.0.5': {} - '@types/node@22.8.7': dependencies: undici-types: 6.19.8 - '@types/retry@0.12.1': {} - '@types/retry@0.12.2': {} - '@ucanto/client@9.0.1': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - - '@ucanto/core@10.0.1': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-ucan': 3.4.0 - '@ucanto/interface': 10.0.1 - multiformats: 11.0.2 - - '@ucanto/interface@10.0.1': - dependencies: - '@ipld/dag-ucan': 3.4.0 - multiformats: 11.0.2 - - '@ucanto/principal@9.0.1': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@noble/curves': 1.6.0 - '@noble/ed25519': 1.7.3 - '@noble/hashes': 1.5.0 - '@ucanto/interface': 10.0.1 - multiformats: 11.0.2 - one-webcrypto: 1.0.3 - - '@ucanto/transport@9.1.1': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - - '@ucanto/validator@9.0.2': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - multiformats: 11.0.2 - - '@web3-storage/access@20.1.0': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-ucan': 3.4.0 - '@scure/bip39': 1.4.0 - '@storacha/one-webcrypto': 1.0.1 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - bigint-mod-arith: 3.3.1 - conf: 11.0.2 - multiformats: 12.1.3 - p-defer: 4.0.1 - type-fest: 4.26.1 - uint8arrays: 4.0.10 - - '@web3-storage/blob-index@1.0.4': - dependencies: - '@ipld/dag-cbor': 9.2.2 - '@storacha/one-webcrypto': 1.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@web3-storage/capabilities': 17.4.0 - carstream: 2.2.0 - multiformats: 13.3.1 - uint8arrays: 5.1.0 - - '@web3-storage/capabilities@17.4.0': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/data-segment': 5.3.0 - uint8arrays: 5.1.0 - - '@web3-storage/data-segment@5.3.0': - dependencies: - '@ipld/dag-cbor': 9.2.2 - multiformats: 13.3.1 - sync-multihash-sha2: 1.0.0 - - '@web3-storage/did-mailto@2.1.0': {} - - '@web3-storage/filecoin-client@3.3.4': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/pail@0.6.0': dependencies: '@ipld/dag-cbor': 9.2.2 multiformats: 13.3.1 - '@web3-storage/upload-client@17.1.0(encoding@0.1.13)': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-ucan': 3.4.0 - '@ipld/unixfs': 2.2.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/data-segment': 5.3.0 - '@web3-storage/filecoin-client': 3.3.4 - ipfs-utils: 9.0.14(encoding@0.1.13) - multiformats: 12.1.3 - p-retry: 5.1.2 - varint: 6.0.0 - transitivePeerDependencies: - - encoding - - '@web3-storage/w3up-client@16.4.0(encoding@0.1.13)': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/access': 20.1.0 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - '@web3-storage/filecoin-client': 3.3.4 - '@web3-storage/upload-client': 17.1.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - actor@2.3.1: {} - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - any-signal@3.0.1: {} - - atomically@2.0.3: - dependencies: - stubborn-fs: 1.2.5 - when-exit: 2.1.3 - - balanced-match@1.0.2: {} - base64-js@1.5.1: {} big-integer@1.6.52: {} - bigint-mod-arith@3.3.1: {} - bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - browser-readablestream-to-it@1.0.3: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - carstream@2.2.0: - dependencies: - '@ipld/dag-cbor': 9.2.2 - multiformats: 13.3.1 - uint8arraylist: 2.4.8 - cborg@4.2.6: {} charwise@3.0.1: {} - concat-map@0.0.1: {} - - conf@11.0.2: - dependencies: - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - atomically: 2.0.3 - debounce-fn: 5.1.2 - dot-prop: 7.2.0 - env-paths: 3.0.0 - json-schema-typed: 8.0.1 - semver: 7.6.3 - - debounce-fn@5.1.2: - dependencies: - mimic-fn: 4.0.0 - - dot-prop@7.2.0: - dependencies: - type-fest: 2.19.0 - - electron-fetch@1.9.1: - dependencies: - encoding: 0.1.13 - - encoding@0.1.13: - dependencies: - iconv-lite: 0.6.3 - - env-paths@3.0.0: {} - - err-code@3.0.1: {} - eventemitter3@5.0.1: {} - fast-deep-equal@3.1.3: {} - - fast-fifo@1.3.2: {} - - fast-uri@3.0.3: {} - - get-iterator@1.0.2: {} - hamt-sharding@3.0.6: dependencies: sparse-array: 1.3.2 @@ -1059,10 +487,6 @@ snapshots: hyperdyperid@1.2.0: {} - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - idb@8.0.0: {} ieee754@1.2.1: {} @@ -1100,46 +524,12 @@ snapshots: protons-runtime: 5.5.0 uint8arraylist: 2.4.8 - ipfs-utils@9.0.14(encoding@0.1.13): - dependencies: - any-signal: 3.0.1 - browser-readablestream-to-it: 1.0.3 - buffer: 6.0.3 - electron-fetch: 1.9.1 - err-code: 3.0.1 - is-electron: 2.2.2 - iso-url: 1.2.1 - it-all: 1.0.6 - it-glob: 1.0.2 - it-to-stream: 1.0.0 - merge-options: 3.0.4 - nanoid: 3.3.7 - native-fetch: 3.0.0(node-fetch@2.7.0(encoding@0.1.13)) - node-fetch: 2.7.0(encoding@0.1.13) - react-native-fetch-api: 3.0.0 - stream-to-it: 0.2.4 - transitivePeerDependencies: - - encoding - - is-electron@2.2.2: {} - is-network-error@1.1.0: {} - is-plain-obj@2.1.0: {} - - iso-url@1.2.1: {} - - it-all@1.0.6: {} - it-filter@3.1.1: dependencies: it-peekable: 3.0.5 - it-glob@1.0.2: - dependencies: - '@types/minimatch': 3.0.5 - minimatch: 3.1.2 - it-last@3.0.6: {} it-map@3.1.1: @@ -1168,21 +558,8 @@ snapshots: it-stream-types@2.0.2: {} - it-to-stream@1.0.0: - dependencies: - buffer: 6.0.3 - fast-fifo: 1.3.2 - get-iterator: 1.0.2 - p-defer: 3.0.0 - p-fifo: 1.0.0 - readable-stream: 3.6.2 - js-tokens@4.0.0: {} - json-schema-traverse@1.0.0: {} - - json-schema-typed@8.0.1: {} - long@5.2.3: {} loose-envify@1.4.0: @@ -1196,51 +573,16 @@ snapshots: tree-dump: 1.0.2(tslib@2.8.1) tslib: 2.8.1 - merge-options@3.0.4: - dependencies: - is-plain-obj: 2.1.0 - - mimic-fn@4.0.0: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - multiformats@11.0.2: {} - - multiformats@12.1.3: {} - multiformats@13.3.1: {} murmurhash3js-revisited@3.0.0: {} - nanoid@3.3.7: {} - - native-fetch@3.0.0(node-fetch@2.7.0(encoding@0.1.13)): - dependencies: - node-fetch: 2.7.0(encoding@0.1.13) - - node-fetch@2.7.0(encoding@0.1.13): - dependencies: - whatwg-url: 5.0.0 - optionalDependencies: - encoding: 0.1.13 - node-sql-parser@3.9.4: dependencies: big-integer: 1.6.52 - one-webcrypto@1.0.3: {} - - p-defer@3.0.0: {} - p-defer@4.0.1: {} - p-fifo@1.0.0: - dependencies: - fast-fifo: 1.3.2 - p-defer: 3.0.0 - p-limit@6.1.0: dependencies: yocto-queue: 1.1.1 @@ -1252,11 +594,6 @@ snapshots: eventemitter3: 5.0.1 p-timeout: 6.1.3 - p-retry@5.1.2: - dependencies: - '@types/retry': 0.12.1 - retry: 0.13.1 - p-retry@6.2.0: dependencies: '@types/retry': 0.12.2 @@ -1295,10 +632,6 @@ snapshots: rabin-rs@2.1.0: {} - react-native-fetch-api@3.0.0: - dependencies: - p-defer: 3.0.0 - react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -1309,38 +642,20 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 - require-from-string@2.0.2: {} - retry@0.13.1: {} safe-buffer@5.2.1: {} - safer-buffer@2.1.2: {} - - semver@7.6.3: {} - sparse-array@1.3.2: {} - stream-to-it@0.2.4: - dependencies: - get-iterator: 1.0.2 - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - stubborn-fs@1.2.5: {} - - sync-multihash-sha2@1.0.0: - dependencies: - '@noble/hashes': 1.5.0 - thingies@1.21.0(tslib@2.8.1): dependencies: tslib: 2.8.1 - tr46@0.0.3: {} - tree-dump@1.0.2(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -1349,10 +664,6 @@ snapshots: tslib@2.8.1: {} - type-fest@2.19.0: {} - - type-fest@4.26.1: {} - uint8-varint@2.0.4: dependencies: uint8arraylist: 2.4.8 @@ -1362,48 +673,16 @@ snapshots: dependencies: uint8arrays: 5.1.0 - uint8arrays@4.0.10: - dependencies: - multiformats: 12.1.3 - uint8arrays@5.1.0: dependencies: multiformats: 13.3.1 undici-types@6.19.8: {} - use-fireproof@0.19.111(react@18.3.1): - dependencies: - '@adviser/cement': 0.2.36 - '@ipld/car': 5.3.3 - '@ipld/unixfs': 3.0.0 - '@web3-storage/pail': 0.6.0 - cborg: 4.2.6 - charwise: 3.0.1 - idb: 8.0.0 - ipfs-unixfs-exporter: 13.6.1 - multiformats: 13.3.1 - p-limit: 6.1.0 - p-map: 7.0.2 - p-retry: 6.2.0 - prolly-trees: 1.0.4 - react: 18.3.1 - transitivePeerDependencies: - - typescript - util-deprecate@1.0.2: {} varint@6.0.0: {} - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - when-exit@2.1.3: {} - yaml@2.6.0: {} yocto-queue@1.1.1: {} diff --git a/examples/ucan/workshop/participants/start-here.js b/examples/ucan/workshop/participants/start-here.js index 12763417..ebc3b87d 100644 --- a/examples/ucan/workshop/participants/start-here.js +++ b/examples/ucan/workshop/participants/start-here.js @@ -17,6 +17,6 @@ import { addImage } from "./db.js"; const dbName = "my-db"; const agent = await FP_UCAN.agent(); -const clock = FP_UCAN.clockId("did:key:z6MkfZwM6XvYbaAi2YF4BcDMXuUNQhPbvoU29NzwMgNtQ5vm"); +const clock = FP_UCAN.clockId("did:key:z6MkhVBdskZ4nC5w5Af2cGUKiC57WkTPo4b5yQ4y7UCQ9DPu"); console.log("Agent DID:", agent.id.did()); diff --git a/examples/ucan/workshop/team/README.md b/examples/ucan/workshop/team/README.md new file mode 100644 index 00000000..477dbf25 --- /dev/null +++ b/examples/ucan/workshop/team/README.md @@ -0,0 +1,4 @@ +```shell +pnpm i +pnpm run dev +``` diff --git a/examples/ucan/workshop/team/package.json b/examples/ucan/workshop/team/package.json index a27a83c4..35744adf 100644 --- a/examples/ucan/workshop/team/package.json +++ b/examples/ucan/workshop/team/package.json @@ -7,7 +7,8 @@ "preview": "rsbuild preview" }, "dependencies": { - "@fireproof/ucan": "0.19.112-dev-nf1", + "@fireproof/core": "0.19.113", + "@fireproof/ucan": "../../../../dist/ucan", "@picocss/pico": "^2.0.6", "@ucanto/core": "^10.0.1", "multiformats": "^13.3.1", diff --git a/examples/ucan/workshop/team/pnpm-lock.yaml b/examples/ucan/workshop/team/pnpm-lock.yaml index 9ad4f7ec..1f28b841 100644 --- a/examples/ucan/workshop/team/pnpm-lock.yaml +++ b/examples/ucan/workshop/team/pnpm-lock.yaml @@ -8,9 +8,12 @@ importers: .: dependencies: + '@fireproof/core': + specifier: 0.19.113 + version: 0.19.113(react@18.3.1)(typescript@5.6.3) '@fireproof/ucan': - specifier: 0.19.112-dev-nf1 - version: 0.19.112-dev-nf1(encoding@0.1.13)(react@18.3.1)(typescript@5.6.3) + specifier: ../../../../dist/ucan + version: link:../../../../dist/ucan '@picocss/pico': specifier: ^2.0.6 version: 2.0.6 @@ -91,13 +94,10 @@ packages: resolution: {integrity: sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@fireproof/core@0.19.111': - resolution: {integrity: sha512-LJsXkGpMtDIvabX8YU24x33BV/oL1o6XdDAfbC2TpoRyNZ8pkqohibzHor+LFriMdRLtO2yqPkad2XnKgRZOqw==} + '@fireproof/core@0.19.113': + resolution: {integrity: sha512-LGAgDBd8MePZ2QUaBav2Wd1pa37SvYfngNAaDh00WGCL9skF+y4ZhcVmhUGNcIKG3xcANsyxouFu7h0rgBoNeA==} peerDependencies: - react: '>=18.0.0' - - '@fireproof/ucan@0.19.112-dev-nf1': - resolution: {integrity: sha512-D1lDMHuNT2T0d9rSWz53TS2bZM2FKWnKOW6ORpiPJ2sl2YEgOaNURBNUjkDXVGnwShMIfxUylcYMs0MWsBXRWg==} + react: ^18.3.1 '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -138,9 +138,6 @@ packages: '@ipld/dag-ucan@3.4.0': resolution: {integrity: sha512-sW4R43w3DbEdoGWWJZCwsblwXa600HCanG9p2w1MJPVBNTNjhvqc3XI0uEqKhT2oqKWrND7uInVtcPmZme7hhA==} - '@ipld/unixfs@2.2.0': - resolution: {integrity: sha512-lDQ2eRhJlbFaBoO3bhOmDVCLmpOnhwtwbilqUgAAhbhoPSmLrnv7gsBuToZjXOdPaEGSL7apkmm6nFrcU6zh4Q==} - '@ipld/unixfs@3.0.0': resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} @@ -178,17 +175,6 @@ packages: resolution: {integrity: sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@noble/curves@1.6.0': - resolution: {integrity: sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==} - engines: {node: ^14.21.3 || >=16} - - '@noble/ed25519@1.7.3': - resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} - - '@noble/hashes@1.5.0': - resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} - engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -312,15 +298,6 @@ packages: resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} - '@scure/base@1.1.9': - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - - '@scure/bip39@1.4.0': - resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} - - '@storacha/one-webcrypto@1.0.1': - resolution: {integrity: sha512-bD+vWmcgsEBqU0Dz04BR43SA03bBoLTAY29vaKasY9Oe8cb6XIP0/vkm0OS2UwKC13c8uRgFW4rjJUgDCNLejQ==} - '@swc/helpers@0.5.13': resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} @@ -330,18 +307,12 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/minimatch@3.0.5': - resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - - '@types/node@22.8.7': - resolution: {integrity: sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==} + '@types/node@22.9.1': + resolution: {integrity: sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/retry@0.12.1': - resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} - '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -402,55 +373,16 @@ packages: resolution: {integrity: sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ucanto/client@9.0.1': - resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} - '@ucanto/core@10.0.1': resolution: {integrity: sha512-1BfUaJu0/c9Rl/WdZSDbScJJLsPsPe1g4ynl5kubUj3xDD/lyp/Q12PQVQ2X7hDiWwkpwmxCkRMkOxwc70iNKQ==} '@ucanto/interface@10.0.1': resolution: {integrity: sha512-+Vr/N4mLsdynV9/bqtdFiq7WsUf3265/Qx2aHJmPtXo9/QvWKthJtpe0g8U4NWkWpVfqIFvyAO2db6D9zWQfQw==} - '@ucanto/principal@9.0.1': - resolution: {integrity: sha512-8eAvaZHW1vyET4X90rkJv6pmW1IOdEYlZYwO3wDgTkC5m9VytBEywCvpzP57cavdYIbbPse5QS9nMEGvk87zhw==} - - '@ucanto/transport@9.1.1': - resolution: {integrity: sha512-3CR17nEemOVaTuMZa6waWgVL4sLxSPcxYvpaNeJ6NZo1rfsqdyRXOtbVV/RcI2BtUL0Cao6JM6P9+gdghfc5ng==} - - '@ucanto/validator@9.0.2': - resolution: {integrity: sha512-LxhRbDMIoLt9LYHq/Rz1WCEH8AtmdsBTS/it28Ij/A3W0zyoSwUpAUxBtXaKRh/gpbxdWmjxX+nVfFJYL//b4g==} - - '@web3-storage/access@20.1.0': - resolution: {integrity: sha512-IY6ICPRWE8++2jxvy+LzAiFvwAOIHR8cu9eNt+VT5sAFE796o4ma7GSU0eXRCiShmV2n6iSWAwWRT6XD5zIqPA==} - - '@web3-storage/blob-index@1.0.4': - resolution: {integrity: sha512-04+PrmVHFT+xzRhyIPdcvGc8Y2NDffUe8R1gJOyErVzEVz5N1I9Q/BrlFHYt/A4HrjM5JBsxqSrZgTIkjfPmLA==} - engines: {node: '>=16.15'} - - '@web3-storage/capabilities@17.4.0': - resolution: {integrity: sha512-2VNLTTvv9qVewtXiek2Fb6W7WTQgOonq+FcNV9PyXAEgcXsQWsm8dOmbeB83W9bAuiwe9uIOzC1rftDHY3+uYA==} - - '@web3-storage/data-segment@5.3.0': - resolution: {integrity: sha512-zFJ4m+pEKqtKatJNsFrk/2lHeFSbkXZ6KKXjBe7/2ayA9wAar7T/unewnOcZrrZTnCWmaxKsXWqdMFy9bXK9dw==} - - '@web3-storage/did-mailto@2.1.0': - resolution: {integrity: sha512-TRmfSXj1IhtX3ESurSNOylZSBKi0z/VJNoMLpof+AVRdovgZjjocpiePQTs2pfHKqHTHfJXc9AboWyK4IKTWMw==} - engines: {node: '>=16.15'} - - '@web3-storage/filecoin-client@3.3.4': - resolution: {integrity: sha512-T2xur1NPvuH09yajyjCWEl7MBH712nqHERj51w4nDp6f8libMCKY6lca0frCrm4OC5s8oy0ZtoRFhsRYxgTzSg==} - '@web3-storage/pail@0.6.0': resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} hasBin: true - '@web3-storage/upload-client@17.1.0': - resolution: {integrity: sha512-0tUMe4Ez9gmUZjgn1Nrl6HYdGEsYyeLa6JrpoXcCGTQDBW2FehALc+GZZeoIjYQexRpw+qt9JstuJNN9dUNETw==} - - '@web3-storage/w3up-client@16.4.0': - resolution: {integrity: sha512-ndHXVufBt6bVyZHHxpe+bgS9bnOtpREsYFtL/C2h/AL8O5LZ1QBM91wFHVvLhFOJcKVcbW2WagyivCr+NOp9WA==} - engines: {node: '>=18'} - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -468,27 +400,13 @@ packages: actor@2.3.1: resolution: {integrity: sha512-ST/3wnvcP2tKDXnum7nLCLXm+/rsf8vPocXH2Fre6D8FQwNkGDd4JEitBlXj007VQJfiGYRQvXqwOBZVi+JtRg==} - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - any-signal@3.0.1: - resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -498,9 +416,6 @@ packages: assert@2.1.0: resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} - atomically@2.0.3: - resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} - available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -515,10 +430,6 @@ packages: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} - bigint-mod-arith@3.3.1: - resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} - engines: {node: '>=10.4.0'} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -541,9 +452,6 @@ packages: brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - browser-readablestream-to-it@1.0.3: - resolution: {integrity: sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==} - browserify-aes@1.2.0: resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} @@ -596,9 +504,6 @@ packages: caniuse-lite@1.0.30001677: resolution: {integrity: sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==} - carstream@2.2.0: - resolution: {integrity: sha512-/gHkK0lQjmGM45fhdx8JD+x7a1XS1qUk3T9xWWSt3oZiWPLq4u/lnDstp+N55K7hqTKKlb0CCr43EHTrlbmJSQ==} - cborg@4.2.6: resolution: {integrity: sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==} hasBin: true @@ -631,10 +536,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - conf@11.0.2: - resolution: {integrity: sha512-jjyhlQ0ew/iwmtwsS2RaB6s8DBifcE2GYBEaw2SJDUY/slJJbNfY4GlDVzOs/ff8cM/Wua5CikqXgbFl5eu85A==} - engines: {node: '>=14.16'} - console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} @@ -667,10 +568,6 @@ packages: resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} engines: {node: '>= 0.10'} - debounce-fn@5.1.2: - resolution: {integrity: sha512-Sr4SdOZ4vw6eQDvPYNxHogvrxmCIld/VenC5JbNrFwMiwd7lY/Z18ZFfo+EWNG4DD9nFlAujWAo/wGuOPHmy5A==} - engines: {node: '>=12'} - debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -701,30 +598,12 @@ packages: resolution: {integrity: sha512-edTFu0M/7wO1pXY6GDxVNVW086uqwWYIHP98txhcPyV995X21JIH2DtYp33sQJOupYoXKe9RwTw2Ya2vWaquTQ==} engines: {node: '>=4'} - dot-prop@7.2.0: - resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - electron-fetch@1.9.1: - resolution: {integrity: sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==} - engines: {node: '>=6'} - electron-to-chromium@1.5.50: resolution: {integrity: sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==} elliptic@6.6.0: resolution: {integrity: sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==} - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - - env-paths@3.0.0: - resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - err-code@3.0.1: - resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -813,9 +692,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -826,9 +702,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -870,9 +743,6 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} - get-iterator@1.0.2: - resolution: {integrity: sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -941,10 +811,6 @@ packages: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - idb@8.0.0: resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} @@ -982,10 +848,6 @@ packages: ipfs-unixfs@11.2.0: resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} - ipfs-utils@9.0.14: - resolution: {integrity: sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -1005,9 +867,6 @@ packages: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} - is-electron@2.2.2: - resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1032,10 +891,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - is-typed-array@1.1.13: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} @@ -1046,19 +901,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - iso-url@1.2.1: - resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} - engines: {node: '>=12'} - - it-all@1.0.6: - resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} - it-filter@3.1.1: resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} - it-glob@1.0.2: - resolution: {integrity: sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==} - it-last@3.0.6: resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} @@ -1084,9 +929,6 @@ packages: it-stream-types@2.0.2: resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} - it-to-stream@1.0.0: - resolution: {integrity: sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1112,12 +954,6 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-schema-typed@8.0.1: - resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -1156,10 +992,6 @@ packages: resolution: {integrity: sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==} engines: {node: '>= 4.0.0'} - merge-options@3.0.4: - resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} - engines: {node: '>=10'} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1172,10 +1004,6 @@ packages: resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} hasBin: true - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -1200,10 +1028,6 @@ packages: resolution: {integrity: sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - multiformats@12.1.3: - resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - multiformats@13.3.1: resolution: {integrity: sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==} @@ -1211,28 +1035,9 @@ packages: resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} engines: {node: '>=8.0.0'} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - native-fetch@3.0.0: - resolution: {integrity: sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==} - peerDependencies: - node-fetch: '*' - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} @@ -1259,9 +1064,6 @@ packages: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} - one-webcrypto@1.0.3: - resolution: {integrity: sha512-fu9ywBVBPx0gS9K0etIROTiCkvI5S1TDjFsYFb3rC1ewFxeOqsbzq7aIMBHsYfrTHBcGXJaONXXjTl8B01cW1Q==} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1269,17 +1071,10 @@ packages: os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - p-defer@3.0.0: - resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} - engines: {node: '>=8'} - p-defer@4.0.1: resolution: {integrity: sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==} engines: {node: '>=12'} - p-fifo@1.0.0: - resolution: {integrity: sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A==} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -1308,12 +1103,8 @@ packages: resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} engines: {node: '>=18'} - p-retry@5.1.2: - resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - p-retry@6.2.0: - resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} p-timeout@6.1.3: @@ -1426,9 +1217,6 @@ packages: randomfill@1.0.4: resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} - react-native-fetch-api@3.0.0: - resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} - react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -1460,10 +1248,6 @@ packages: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1492,9 +1276,6 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -1554,9 +1335,6 @@ packages: stream-http@3.2.0: resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} - stream-to-it@0.2.4: - resolution: {integrity: sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -1571,9 +1349,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - stubborn-fs@1.2.5: - resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1582,9 +1357,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - sync-multihash-sha2@1.0.0: - resolution: {integrity: sha512-A5gVpmtKF0ov+/XID0M0QRJqF2QxAsj3x/LlDC8yivzgoYCoWkV+XaZPfVu7Vj1T/hYzYS1tfjwboSbXjqocug==} - text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -1602,9 +1374,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tree-dump@1.0.2: resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} engines: {node: '>=10.0'} @@ -1643,14 +1412,6 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - - type-fest@4.26.1: - resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} - engines: {node: '>=16'} - typescript-eslint@8.12.2: resolution: {integrity: sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1671,9 +1432,6 @@ packages: uint8arraylist@2.4.8: resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} - uint8arrays@4.0.10: - resolution: {integrity: sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==} - uint8arrays@5.1.0: resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} @@ -1693,11 +1451,6 @@ packages: resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} engines: {node: '>= 0.4'} - use-fireproof@0.19.111: - resolution: {integrity: sha512-bmRWaYrtyq0+2ewDj0cLJ8FQL3osUe0j7p89DT2dQ13sji5Td2oTXWgXZVfTPCbC8LF6qW4zXVQ4Cks4SToEaw==} - peerDependencies: - react: '>=18.0.0' - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1713,15 +1466,6 @@ packages: vm-browserify@1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - when-exit@2.1.3: - resolution: {integrity: sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==} - which-typed-array@1.1.15: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} @@ -1739,8 +1483,8 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - yaml@2.6.0: - resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} engines: {node: '>= 14'} hasBin: true @@ -1757,7 +1501,7 @@ snapshots: '@adviser/cement@0.2.36(typescript@5.6.3)': dependencies: ts-essentials: 10.0.3(typescript@5.6.3) - yaml: 2.6.0 + yaml: 2.6.1 transitivePeerDependencies: - typescript @@ -1808,7 +1552,7 @@ snapshots: dependencies: levn: 0.4.1 - '@fireproof/core@0.19.111(react@18.3.1)(typescript@5.6.3)': + '@fireproof/core@0.19.113(react@18.3.1)(typescript@5.6.3)': dependencies: '@adviser/cement': 0.2.36(typescript@5.6.3) '@ipld/car': 5.3.3 @@ -1824,33 +1568,12 @@ snapshots: multiformats: 13.3.1 p-limit: 6.1.0 p-map: 7.0.2 - p-retry: 6.2.0 + p-retry: 6.2.1 prolly-trees: 1.0.4 react: 18.3.1 transitivePeerDependencies: - typescript - '@fireproof/ucan@0.19.112-dev-nf1(encoding@0.1.13)(react@18.3.1)(typescript@5.6.3)': - dependencies: - '@fireproof/core': 0.19.111(react@18.3.1)(typescript@5.6.3) - '@ipld/dag-cbor': 9.2.2 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/access': 20.1.0 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - '@web3-storage/w3up-client': 16.4.0(encoding@0.1.13) - multiformats: 13.3.1 - use-fireproof: 0.19.111(react@18.3.1)(typescript@5.6.3) - transitivePeerDependencies: - - encoding - - react - - typescript - '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -1891,16 +1614,6 @@ snapshots: '@ipld/dag-json': 10.2.3 multiformats: 11.0.2 - '@ipld/unixfs@2.2.0': - dependencies: - '@ipld/dag-pb': 4.1.3 - '@multiformats/murmur3': 2.1.8 - '@perma/map': 1.0.3 - actor: 2.3.1 - multiformats: 11.0.2 - protobufjs: 7.4.0 - rabin-rs: 2.1.0 - '@ipld/unixfs@3.0.0': dependencies: '@ipld/dag-pb': 4.1.3 @@ -1948,14 +1661,6 @@ snapshots: multiformats: 13.3.1 murmurhash3js-revisited: 3.0.0 - '@noble/curves@1.6.0': - dependencies: - '@noble/hashes': 1.5.0 - - '@noble/ed25519@1.7.3': {} - - '@noble/hashes@1.5.0': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2085,15 +1790,6 @@ snapshots: '@rspack/lite-tapable@1.0.1': {} - '@scure/base@1.1.9': {} - - '@scure/bip39@1.4.0': - dependencies: - '@noble/hashes': 1.5.0 - '@scure/base': 1.1.9 - - '@storacha/one-webcrypto@1.0.1': {} - '@swc/helpers@0.5.13': dependencies: tslib: 2.8.1 @@ -2102,16 +1798,12 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/minimatch@3.0.5': {} - - '@types/node@22.8.7': + '@types/node@22.9.1': dependencies: undici-types: 6.19.8 '@types/normalize-package-data@2.4.4': {} - '@types/retry@0.12.1': {} - '@types/retry@0.12.2': {} '@typescript-eslint/eslint-plugin@8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)': @@ -2195,11 +1887,6 @@ snapshots: '@typescript-eslint/types': 8.12.2 eslint-visitor-keys: 3.4.3 - '@ucanto/client@9.0.1': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/core@10.0.1': dependencies: '@ipld/car': 5.3.3 @@ -2213,131 +1900,11 @@ snapshots: '@ipld/dag-ucan': 3.4.0 multiformats: 11.0.2 - '@ucanto/principal@9.0.1': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@noble/curves': 1.6.0 - '@noble/ed25519': 1.7.3 - '@noble/hashes': 1.5.0 - '@ucanto/interface': 10.0.1 - multiformats: 11.0.2 - one-webcrypto: 1.0.3 - - '@ucanto/transport@9.1.1': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - - '@ucanto/validator@9.0.2': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - multiformats: 11.0.2 - - '@web3-storage/access@20.1.0': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-ucan': 3.4.0 - '@scure/bip39': 1.4.0 - '@storacha/one-webcrypto': 1.0.1 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - bigint-mod-arith: 3.3.1 - conf: 11.0.2 - multiformats: 12.1.3 - p-defer: 4.0.1 - type-fest: 4.26.1 - uint8arrays: 4.0.10 - - '@web3-storage/blob-index@1.0.4': - dependencies: - '@ipld/dag-cbor': 9.2.2 - '@storacha/one-webcrypto': 1.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@web3-storage/capabilities': 17.4.0 - carstream: 2.2.0 - multiformats: 13.3.1 - uint8arrays: 5.1.0 - - '@web3-storage/capabilities@17.4.0': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/data-segment': 5.3.0 - uint8arrays: 5.1.0 - - '@web3-storage/data-segment@5.3.0': - dependencies: - '@ipld/dag-cbor': 9.2.2 - multiformats: 13.3.1 - sync-multihash-sha2: 1.0.0 - - '@web3-storage/did-mailto@2.1.0': {} - - '@web3-storage/filecoin-client@3.3.4': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/pail@0.6.0': dependencies: '@ipld/dag-cbor': 9.2.2 multiformats: 13.3.1 - '@web3-storage/upload-client@17.1.0(encoding@0.1.13)': - dependencies: - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-ucan': 3.4.0 - '@ipld/unixfs': 2.2.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/data-segment': 5.3.0 - '@web3-storage/filecoin-client': 3.3.4 - ipfs-utils: 9.0.14(encoding@0.1.13) - multiformats: 12.1.3 - p-retry: 5.1.2 - varint: 6.0.0 - transitivePeerDependencies: - - encoding - - '@web3-storage/w3up-client@16.4.0(encoding@0.1.13)': - dependencies: - '@ipld/dag-ucan': 3.4.0 - '@ucanto/client': 9.0.1 - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@web3-storage/access': 20.1.0 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.0 - '@web3-storage/did-mailto': 2.1.0 - '@web3-storage/filecoin-client': 3.3.4 - '@web3-storage/upload-client': 17.1.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -2350,10 +1917,6 @@ snapshots: actor@2.3.1: {} - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -2361,19 +1924,10 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - any-signal@3.0.1: {} - argparse@2.0.1: {} asn1.js@4.10.1: @@ -2390,11 +1944,6 @@ snapshots: object.assign: 4.1.5 util: 0.12.5 - atomically@2.0.3: - dependencies: - stubborn-fs: 1.2.5 - when-exit: 2.1.3 - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -2405,8 +1954,6 @@ snapshots: big-integer@1.6.52: {} - bigint-mod-arith@3.3.1: {} - bl@4.1.0: dependencies: buffer: 5.7.1 @@ -2432,8 +1979,6 @@ snapshots: brorand@1.1.0: {} - browser-readablestream-to-it@1.0.3: {} - browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 @@ -2514,12 +2059,6 @@ snapshots: caniuse-lite@1.0.30001677: {} - carstream@2.2.0: - dependencies: - '@ipld/dag-cbor': 9.2.2 - multiformats: 13.3.1 - uint8arraylist: 2.4.8 - cborg@4.2.6: {} chalk@4.1.2: @@ -2548,17 +2087,6 @@ snapshots: concat-map@0.0.1: {} - conf@11.0.2: - dependencies: - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - atomically: 2.0.3 - debounce-fn: 5.1.2 - dot-prop: 7.2.0 - env-paths: 3.0.0 - json-schema-typed: 8.0.1 - semver: 7.6.3 - console-browserify@1.2.0: {} constants-browserify@1.0.0: {} @@ -2614,10 +2142,6 @@ snapshots: randombytes: 2.1.0 randomfill: 1.0.4 - debounce-fn@5.1.2: - dependencies: - mimic-fn: 4.0.0 - debug@4.3.7: dependencies: ms: 2.1.3 @@ -2649,14 +2173,6 @@ snapshots: domain-browser@5.7.0: {} - dot-prop@7.2.0: - dependencies: - type-fest: 2.19.0 - - electron-fetch@1.9.1: - dependencies: - encoding: 0.1.13 - electron-to-chromium@1.5.50: {} elliptic@6.6.0: @@ -2669,14 +2185,6 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - encoding@0.1.13: - dependencies: - iconv-lite: 0.6.3 - - env-paths@3.0.0: {} - - err-code@3.0.1: {} - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -2793,8 +2301,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-fifo@1.3.2: {} - fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2807,8 +2313,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.0.3: {} - fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -2855,8 +2359,6 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 - get-iterator@1.0.2: {} - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2920,10 +2422,6 @@ snapshots: hyperdyperid@1.2.0: {} - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - idb@8.0.0: {} ieee754@1.2.1: {} @@ -2972,27 +2470,6 @@ snapshots: protons-runtime: 5.5.0 uint8arraylist: 2.4.8 - ipfs-utils@9.0.14(encoding@0.1.13): - dependencies: - any-signal: 3.0.1 - browser-readablestream-to-it: 1.0.3 - buffer: 6.0.3 - electron-fetch: 1.9.1 - err-code: 3.0.1 - is-electron: 2.2.2 - iso-url: 1.2.1 - it-all: 1.0.6 - it-glob: 1.0.2 - it-to-stream: 1.0.0 - merge-options: 3.0.4 - nanoid: 3.3.7 - native-fetch: 3.0.0(node-fetch@2.7.0(encoding@0.1.13)) - node-fetch: 2.7.0(encoding@0.1.13) - react-native-fetch-api: 3.0.0 - stream-to-it: 0.2.4 - transitivePeerDependencies: - - encoding - is-arguments@1.1.1: dependencies: call-bind: 1.0.7 @@ -3010,8 +2487,6 @@ snapshots: dependencies: hasown: 2.0.2 - is-electron@2.2.2: {} - is-extglob@2.1.1: {} is-generator-function@1.0.10: @@ -3031,8 +2506,6 @@ snapshots: is-number@7.0.0: {} - is-plain-obj@2.1.0: {} - is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 @@ -3041,19 +2514,10 @@ snapshots: isexe@2.0.0: {} - iso-url@1.2.1: {} - - it-all@1.0.6: {} - it-filter@3.1.1: dependencies: it-peekable: 3.0.5 - it-glob@1.0.2: - dependencies: - '@types/minimatch': 3.0.5 - minimatch: 3.1.2 - it-last@3.0.6: {} it-map@3.1.1: @@ -3082,15 +2546,6 @@ snapshots: it-stream-types@2.0.2: {} - it-to-stream@1.0.0: - dependencies: - buffer: 6.0.3 - fast-fifo: 1.3.2 - get-iterator: 1.0.2 - p-defer: 3.0.0 - p-fifo: 1.0.0 - readable-stream: 3.6.2 - js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -3107,10 +2562,6 @@ snapshots: json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - - json-schema-typed@8.0.1: {} - json-stable-stringify-without-jsonify@1.0.1: {} keyv@4.5.4: @@ -3153,10 +2604,6 @@ snapshots: tree-dump: 1.0.2(tslib@2.8.1) tslib: 2.8.1 - merge-options@3.0.4: - dependencies: - is-plain-obj: 2.1.0 - merge2@1.4.1: {} micromatch@4.0.8: @@ -3169,8 +2616,6 @@ snapshots: bn.js: 4.12.0 brorand: 1.1.0 - mimic-fn@4.0.0: {} - min-indent@1.0.1: {} minimalistic-assert@1.0.1: {} @@ -3189,26 +2634,12 @@ snapshots: multiformats@11.0.2: {} - multiformats@12.1.3: {} - multiformats@13.3.1: {} murmurhash3js-revisited@3.0.0: {} - nanoid@3.3.7: {} - - native-fetch@3.0.0(node-fetch@2.7.0(encoding@0.1.13)): - dependencies: - node-fetch: 2.7.0(encoding@0.1.13) - natural-compare@1.4.0: {} - node-fetch@2.7.0(encoding@0.1.13): - dependencies: - whatwg-url: 5.0.0 - optionalDependencies: - encoding: 0.1.13 - node-releases@2.0.18: {} node-sql-parser@3.9.4: @@ -3238,8 +2669,6 @@ snapshots: has-symbols: 1.0.3 object-keys: 1.1.1 - one-webcrypto@1.0.3: {} - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3251,15 +2680,8 @@ snapshots: os-browserify@0.3.0: {} - p-defer@3.0.0: {} - p-defer@4.0.1: {} - p-fifo@1.0.0: - dependencies: - fast-fifo: 1.3.2 - p-defer: 3.0.0 - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -3287,12 +2709,7 @@ snapshots: eventemitter3: 5.0.1 p-timeout: 6.1.3 - p-retry@5.1.2: - dependencies: - '@types/retry': 0.12.1 - retry: 0.13.1 - - p-retry@6.2.0: + p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 is-network-error: 1.1.0 @@ -3373,7 +2790,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.8.7 + '@types/node': 22.9.1 long: 5.2.3 protons-runtime@5.5.0: @@ -3414,10 +2831,6 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 - react-native-fetch-api@3.0.0: - dependencies: - p-defer: 3.0.0 - react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -3465,8 +2878,6 @@ snapshots: dependencies: jsesc: 0.5.0 - require-from-string@2.0.2: {} - resolve-from@4.0.0: {} resolve@1.22.8: @@ -3492,8 +2903,6 @@ snapshots: safe-buffer@5.2.1: {} - safer-buffer@2.1.2: {} - semver@5.7.2: {} semver@7.6.3: {} @@ -3561,10 +2970,6 @@ snapshots: readable-stream: 3.6.2 xtend: 4.0.2 - stream-to-it@0.2.4: - dependencies: - get-iterator: 1.0.2 - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -3579,18 +2984,12 @@ snapshots: strip-json-comments@3.1.1: {} - stubborn-fs@1.2.5: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 supports-preserve-symlinks-flag@1.0.0: {} - sync-multihash-sha2@1.0.0: - dependencies: - '@noble/hashes': 1.5.0 - text-table@0.2.0: {} thingies@1.21.0(tslib@2.8.1): @@ -3605,8 +3004,6 @@ snapshots: dependencies: is-number: 7.0.0 - tr46@0.0.3: {} - tree-dump@1.0.2(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -3631,10 +3028,6 @@ snapshots: type-fest@0.8.1: {} - type-fest@2.19.0: {} - - type-fest@4.26.1: {} - typescript-eslint@8.12.2(eslint@9.14.0)(typescript@5.6.3): dependencies: '@typescript-eslint/eslint-plugin': 8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3) @@ -3657,10 +3050,6 @@ snapshots: dependencies: uint8arrays: 5.1.0 - uint8arrays@4.0.10: - dependencies: - multiformats: 12.1.3 - uint8arrays@5.1.0: dependencies: multiformats: 13.3.1 @@ -3682,25 +3071,6 @@ snapshots: punycode: 1.4.1 qs: 6.13.0 - use-fireproof@0.19.111(react@18.3.1)(typescript@5.6.3): - dependencies: - '@adviser/cement': 0.2.36(typescript@5.6.3) - '@ipld/car': 5.3.3 - '@ipld/unixfs': 3.0.0 - '@web3-storage/pail': 0.6.0 - cborg: 4.2.6 - charwise: 3.0.1 - idb: 8.0.0 - ipfs-unixfs-exporter: 13.6.1 - multiformats: 13.3.1 - p-limit: 6.1.0 - p-map: 7.0.2 - p-retry: 6.2.0 - prolly-trees: 1.0.4 - react: 18.3.1 - transitivePeerDependencies: - - typescript - util-deprecate@1.0.2: {} util@0.12.5: @@ -3720,15 +3090,6 @@ snapshots: vm-browserify@1.1.2: {} - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - when-exit@2.1.3: {} - which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 @@ -3745,7 +3106,7 @@ snapshots: xtend@4.0.2: {} - yaml@2.6.0: {} + yaml@2.6.1: {} yocto-queue@0.1.0: {} diff --git a/examples/ucan/workshop/team/src/state.js b/examples/ucan/workshop/team/src/state.js index b64825ef..566de610 100644 --- a/examples/ucan/workshop/team/src/state.js +++ b/examples/ucan/workshop/team/src/state.js @@ -50,7 +50,7 @@ const fx = (msg) => { const db = fireproof("workshop-db"); const clock = await UCAN.clock({ audience: await UCAN.agent(), databaseName: "workshop-db" }); -const context = await UCAN.connect(db, { clock }); +const context = await UCAN.connect(db, { clock, poll: true }); // await addImage(db, byteArray); diff --git a/package.json b/package.json index 18978677..8492b1f1 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "@aws-sdk/client-s3": "^3.712.0", "@fireproof/core": "0.19.118", "@fireproof/vendor": "1.0.0", + "@ipld/dag-ucan": "^3.4.0", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1baf516..b944a3a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: '@hono/node-ws': specifier: ^1.0.4 version: 1.0.4(@hono/node-server@1.13.7(hono@4.6.13)) + '@ipld/dag-ucan': + specifier: ^3.4.0 + version: 3.4.0 '@jspm/core': specifier: ^2.1.0 version: 2.1.0 diff --git a/pnpm-lock.yaml.orig b/pnpm-lock.yaml.orig new file mode 100644 index 00000000..0d3fb0af --- /dev/null +++ b/pnpm-lock.yaml.orig @@ -0,0 +1,8448 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@adviser/cement': + specifier: ^0.2.41 + version: 0.2.41(typescript@5.7.2) + '@aws-sdk/client-s3': + specifier: ^3.705.0 + version: 3.705.0 + '@fireproof/core': +<<<<<<< HEAD + specifier: 0.19.116 + version: 0.19.116(react@18.3.1)(typescript@5.7.2) + '@fireproof/vendor': + specifier: 1.0.0 + version: 1.0.0 +======= + specifier: 0.19.113 + version: 0.19.113(react@18.3.1)(typescript@5.7.2) + '@ipld/dag-cbor': + specifier: ^9.2.1 + version: 9.2.2 + '@ipld/dag-ucan': + specifier: ^3.4.0 + version: 3.4.0 +>>>>>>> 7ae4cc0 (feat: Add sharing, fix sync & finish ucan examples) + '@jspm/core': + specifier: ^2.1.0 + version: 2.1.0 + '@netlify/blobs': + specifier: ^8.1.0 + version: 8.1.0 + '@ucanto/client': + specifier: ^9.0.1 + version: 9.0.1 + '@ucanto/core': + specifier: ^10.0.1 + version: 10.0.1 + '@ucanto/interface': + specifier: ^10.0.1 + version: 10.0.1 + '@ucanto/principal': + specifier: ^9.0.1 + version: 9.0.1 + '@ucanto/transport': + specifier: ^9.1.1 + version: 9.1.1 + '@ucanto/validator': + specifier: ^9.0.2 + version: 9.0.2 + '@web3-storage/access': + specifier: ^20.1.0 + version: 20.1.0 + '@web3-storage/capabilities': + specifier: ^17.4.1 + version: 17.4.1 + '@web3-storage/clock': + specifier: ^0.4.1 + version: 0.4.1 + '@web3-storage/did-mailto': + specifier: ^2.1.0 + version: 2.1.0 + '@web3-storage/pail': + specifier: ^0.6.0 + version: 0.6.0 + '@web3-storage/w3up-client': + specifier: ^16.5.2 + version: 16.5.2(encoding@0.1.13) + assert: + specifier: ^2.1.0 + version: 2.1.0 + better-sqlite3: + specifier: ^11.7.0 + version: 11.7.0 + cborg: + specifier: ^4.2.7 + version: 4.2.7 + cross-fetch: + specifier: ^4.0.0 + version: 4.0.0(encoding@0.1.13) + events: + specifier: ^3.3.0 + version: 3.3.0 + idb-keyval: + specifier: ^6.2.1 + version: 6.2.1 + is-deep-strict-equal-x: + specifier: ^1.1.2 + version: 1.1.2 + multiformats: + specifier: ^13.3.1 + version: 13.3.1 + node-sqlite3-wasm: + specifier: ^0.8.28 + version: 0.8.28 + partykit: + specifier: ^0.0.111 + version: 0.0.111 + partysocket: + specifier: ^1.0.2 + version: 1.0.2 + path: + specifier: ^0.12.7 + version: 0.12.7 + util: + specifier: ^0.12.5 + version: 0.12.5 + wait-on: + specifier: ^8.0.1 + version: 8.0.1 + ws: + specifier: ^8.18.0 + version: 8.18.0 + devDependencies: + '@eslint/js': + specifier: ^9.16.0 + version: 9.16.0 + '@smithy/types': + specifier: ^3.7.1 + version: 3.7.1 + '@types/better-sqlite3': + specifier: ^7.6.12 + version: 7.6.12 + '@types/eslint__js': + specifier: ^8.42.3 + version: 8.42.3 + '@types/node': + specifier: ^22.10.1 + version: 22.10.1 + '@types/wait-on': + specifier: ^5.3.4 + version: 5.3.4 + '@types/ws': + specifier: ^8.5.13 + version: 8.5.13 + '@typescript-eslint/typescript-estree': + specifier: ^8.17.0 + version: 8.17.0(typescript@5.7.2) + esbuild: + specifier: ^0.24.0 + version: 0.24.0 + esbuild-plugin-replace: + specifier: ^1.4.0 + version: 1.4.0 + esbuild-plugin-resolve: + specifier: ^2.0.0 + version: 2.0.0 + eslint: + specifier: ^9.16.0 + version: 9.16.0 + prettier: + specifier: ^3.4.2 + version: 3.4.2 + semver: + specifier: ^7.6.3 + version: 7.6.3 + std-env: + specifier: ^3.8.0 + version: 3.8.0 + tsup: + specifier: ^8.3.5 + version: 8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.5.1) + tsx: + specifier: ^4.19.2 + version: 4.19.2 + typescript: + specifier: ^5.7.2 + version: 5.7.2 + typescript-eslint: + specifier: ^8.17.0 + version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) + vite: + specifier: ^6.0.3 + version: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)) + vitest: + specifier: ^2.1.8 + version: 2.1.8(@types/node@22.10.1) + wrangler: + specifier: ^3.93.0 + version: 3.93.0 + zx: + specifier: ^8.2.4 + version: 8.2.4 + +packages: + + '@adviser/cement@0.2.41': + resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} + engines: {node: '>=16'} + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.705.0': + resolution: {integrity: sha512-Fm0Cbc4zr0yG0DnNycz7ywlL5tQFdLSb7xCIPfzrxJb3YQiTXWxH5eu61SSsP/Z6RBNRolmRPvst/iNgX0fWvA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sso-oidc@3.699.0': + resolution: {integrity: sha512-u8a1GorY5D1l+4FQAf4XBUC1T10/t7neuwT21r0ymrtMFSK2a9QqVHKMoLkvavAwyhJnARSBM9/UQC797PFOFw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.699.0 + + '@aws-sdk/client-sso@3.696.0': + resolution: {integrity: sha512-q5TTkd08JS0DOkHfUL853tuArf7NrPeqoS5UOvqJho8ibV9Ak/a/HO4kNvy9Nj3cib/toHYHsQIEtecUPSUUrQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sts@3.699.0': + resolution: {integrity: sha512-++lsn4x2YXsZPIzFVwv3fSUVM55ZT0WRFmPeNilYIhZClxHLmVAWKH4I55cY9ry60/aTKYjzOXkWwyBKGsGvQg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/core@3.696.0': + resolution: {integrity: sha512-3c9III1k03DgvRZWg8vhVmfIXPG6hAciN9MzQTzqGngzWAELZF/WONRTRQuDFixVtarQatmLHYVw/atGeA2Byw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-env@3.696.0': + resolution: {integrity: sha512-T9iMFnJL7YTlESLpVFT3fg1Lkb1lD+oiaIC8KMpepb01gDUBIpj9+Y+pA/cgRWW0yRxmkDXNazAE2qQTVFGJzA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-http@3.696.0': + resolution: {integrity: sha512-GV6EbvPi2eq1+WgY/o2RFA3P7HGmnkIzCNmhwtALFlqMroLYWKE7PSeHw66Uh1dFQeVESn0/+hiUNhu1mB0emA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-ini@3.699.0': + resolution: {integrity: sha512-dXmCqjJnKmG37Q+nLjPVu22mNkrGHY8hYoOt3Jo9R2zr5MYV7s/NHsCHr+7E+BZ+tfZYLRPeB1wkpTeHiEcdRw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.699.0 + + '@aws-sdk/credential-provider-node@3.699.0': + resolution: {integrity: sha512-MmEmNDo1bBtTgRmdNfdQksXu4uXe66s0p1hi1YPrn1h59Q605eq/xiWbGL6/3KdkViH6eGUuABeV2ODld86ylg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-process@3.696.0': + resolution: {integrity: sha512-mL1RcFDe9sfmyU5K1nuFkO8UiJXXxLX4JO1gVaDIOvPqwStpUAwi3A1BoeZhWZZNQsiKI810RnYGo0E0WB/hUA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-sso@3.699.0': + resolution: {integrity: sha512-Ekp2cZG4pl9D8+uKWm4qO1xcm8/MeiI8f+dnlZm8aQzizeC+aXYy9GyoclSf6daK8KfRPiRfM7ZHBBL5dAfdMA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.696.0': + resolution: {integrity: sha512-XJ/CVlWChM0VCoc259vWguFUjJDn/QwDqHwbx+K9cg3v6yrqXfK5ai+p/6lx0nQpnk4JzPVeYYxWRpaTsGC9rg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.696.0 + + '@aws-sdk/middleware-bucket-endpoint@3.696.0': + resolution: {integrity: sha512-V07jishKHUS5heRNGFpCWCSTjRJyQLynS/ncUeE8ZYtG66StOOQWftTwDfFOSoXlIqrXgb4oT9atryzXq7Z4LQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-expect-continue@3.696.0': + resolution: {integrity: sha512-vpVukqY3U2pb+ULeX0shs6L0aadNep6kKzjme/MyulPjtUDJpD3AekHsXRrCCGLmOqSKqRgQn5zhV9pQhHsb6Q==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.701.0': + resolution: {integrity: sha512-adNaPCyTT+CiVM0ufDiO1Fe7nlRmJdI9Hcgj0M9S6zR7Dw70Ra5z8Lslkd7syAccYvZaqxLklGjPQH/7GNxwTA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-host-header@3.696.0': + resolution: {integrity: sha512-zELJp9Ta2zkX7ELggMN9qMCgekqZhFC5V2rOr4hJDEb/Tte7gpfKSObAnw/3AYiVqt36sjHKfdkoTsuwGdEoDg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-location-constraint@3.696.0': + resolution: {integrity: sha512-FgH12OB0q+DtTrP2aiDBddDKwL4BPOrm7w3VV9BJrSdkqQCNBPz8S1lb0y5eVH4tBG+2j7gKPlOv1wde4jF/iw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-logger@3.696.0': + resolution: {integrity: sha512-KhkHt+8AjCxcR/5Zp3++YPJPpFQzxpr+jmONiT/Jw2yqnSngZ0Yspm5wGoRx2hS1HJbyZNuaOWEGuJoxLeBKfA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.696.0': + resolution: {integrity: sha512-si/maV3Z0hH7qa99f9ru2xpS5HlfSVcasRlNUXKSDm611i7jFMWwGNLUOXFAOLhXotPX5G3Z6BLwL34oDeBMug==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.696.0': + resolution: {integrity: sha512-M7fEiAiN7DBMHflzOFzh1I2MNSlLpbiH2ubs87bdRc2wZsDPSbs4l3v6h3WLhxoQK0bq6vcfroudrLBgvCuX3Q==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-ssec@3.696.0': + resolution: {integrity: sha512-w/d6O7AOZ7Pg3w2d3BxnX5RmGNWb5X4RNxF19rJqcgu/xqxxE/QwZTNd5a7eTsqLXAUIfbbR8hh0czVfC1pJLA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-user-agent@3.696.0': + resolution: {integrity: sha512-Lvyj8CTyxrHI6GHd2YVZKIRI5Fmnugt3cpJo0VrKKEgK5zMySwEZ1n4dqPK6czYRWKd5+WnYHYAuU+Wdk6Jsjw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/region-config-resolver@3.696.0': + resolution: {integrity: sha512-7EuH142lBXjI8yH6dVS/CZeiK/WZsmb/8zP6bQbVYpMrppSTgB3MzZZdxVZGzL5r8zPQOU10wLC4kIMy0qdBVQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.696.0': + resolution: {integrity: sha512-ijPkoLjXuPtgxAYlDoYls8UaG/VKigROn9ebbvPL/orEY5umedd3iZTcS9T+uAf4Ur3GELLxMQiERZpfDKaz3g==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/token-providers@3.699.0': + resolution: {integrity: sha512-kuiEW9DWs7fNos/SM+y58HCPhcIzm1nEZLhe2/7/6+TvAYLuEWURYsbK48gzsxXlaJ2k/jGY3nIsA7RptbMOwA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sso-oidc': ^3.699.0 + + '@aws-sdk/types@3.696.0': + resolution: {integrity: sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-arn-parser@3.693.0': + resolution: {integrity: sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-endpoints@3.696.0': + resolution: {integrity: sha512-T5s0IlBVX+gkb9g/I6CLt4yAZVzMSiGnbUqWihWsHvQR1WOoIcndQy/Oz/IJXT9T2ipoy7a80gzV6a5mglrioA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-locate-window@3.568.0': + resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-user-agent-browser@3.696.0': + resolution: {integrity: sha512-Z5rVNDdmPOe6ELoM5AhF/ja5tSjbe6ctSctDPb0JdDf4dT0v2MfwhJKzXju2RzX8Es/77Glh7MlaXLE0kCB9+Q==} + + '@aws-sdk/util-user-agent-node@3.696.0': + resolution: {integrity: sha512-KhKqcfyXIB0SCCt+qsu4eJjsfiOrNzK5dCV7RAW2YIpp+msxGUUX0NdRE9rkzjiv+3EMktgJm3eEIS+yxtlVdQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.696.0': + resolution: {integrity: sha512-dn1mX+EeqivoLYnY7p2qLrir0waPnCgS/0YdRCAVU2x14FgfUYCH6Im3w3oi2dMwhxfKY5lYVB5NKvZu7uI9lQ==} + engines: {node: '>=16.0.0'} + + '@cloudflare/kv-asset-handler@0.3.4': + resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} + engines: {node: '>=16.13'} + + '@cloudflare/workerd-darwin-64@1.20240718.0': + resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-64@1.20241205.0': + resolution: {integrity: sha512-TArEZkSZkHJyEwnlWWkSpCI99cF6lJ14OVeEoI9Um/+cD9CKZLM9vCmsLeKglKheJ0KcdCnkA+DbeD15t3VaWg==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20240718.0': + resolution: {integrity: sha512-nlr4gaOO5gcJerILJQph3+2rnas/nx/lYsuaot1ntHu4LAPBoQo1q/Pucj2cSIav4UiMzTbDmoDwPlls4Kteog==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20241205.0': + resolution: {integrity: sha512-u5eqKa9QRdA8MugfgCoD+ADDjY6EpKbv3hSYJETmmUh17l7WXjWBzv4pUvOKIX67C0UzMUy4jZYwC53MymhX3w==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20240718.0': + resolution: {integrity: sha512-LJ/k3y47pBcjax0ee4K+6ZRrSsqWlfU4lbU8Dn6u5tSC9yzwI4YFNXDrKWInB0vd7RT3w4Yqq1S6ZEbfRrqVUg==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-64@1.20241205.0': + resolution: {integrity: sha512-OYA7S5zpumMamWEW+IhhBU6YojIEocyE5X/YFPiTOCrDE3dsfr9t6oqNE7hxGm1VAAu+Irtl+a/5LwmBOU681w==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20240718.0': + resolution: {integrity: sha512-zBEZvy88EcAMGRGfuVtS00Yl7lJdUM9sH7i651OoL+q0Plv9kphlCC0REQPwzxrEYT1qibSYtWcD9IxQGgx2/g==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20241205.0': + resolution: {integrity: sha512-qAzecONjFJGIAVJZKExQ5dlbic0f3d4A+GdKa+H6SoUJtPaWiE3K6WuePo4JOT7W3/Zfh25McmX+MmpMUUcM5Q==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20240718.0': + resolution: {integrity: sha512-YpCRvvT47XanFum7C3SedOZKK6BfVhqmwdAAVAQFyc4gsCdegZo0JkUkdloC/jwuWlbCACOG2HTADHOqyeolzQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cloudflare/workerd-windows-64@1.20241205.0': + resolution: {integrity: sha512-BEab+HiUgCdl6GXAT7EI2yaRtDPiRJlB94XLvRvXi1ZcmQqsrq6awGo6apctFo4WUL29V7c09LxmN4HQ3X2Tvg==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cloudflare/workers-shared@0.10.0': + resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} + engines: {node: '>=16.7.0'} + + '@cloudflare/workers-types@4.20240718.0': + resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@esbuild-plugins/node-globals-polyfill@0.2.3': + resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} + peerDependencies: + esbuild: '*' + + '@esbuild-plugins/node-modules-polyfill@0.2.2': + resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} + peerDependencies: + esbuild: '*' + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.17.19': + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.17.19': + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.17.19': + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.17.19': + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.17.19': + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.17.19': + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.17.19': + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.17.19': + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.17.19': + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.17.19': + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.17.19': + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.17.19': + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.17.19': + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.17.19': + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.17.19': + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.17.19': + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.17.19': + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.17.19': + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.17.19': + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.17.19': + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.17.19': + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.17.19': + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.19.0': + resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.9.0': + resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.16.0': + resolution: {integrity: sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.3': + resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@fireproof/core@0.19.116': + resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} + peerDependencies: + react: ^18.3.1 + + '@fireproof/vendor@1.0.0': + resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} + + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + engines: {node: '>=18.18'} + + '@ipld/car@5.3.2': + resolution: {integrity: sha512-Bb4XrCFlnsCb9tTzZ1I8zo9O61D9qm7HfvuYrQ9gzdE8YhjyVIjrjmHmnoSWV/uCmyc2/bcqiDPIg+9WljXNzg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/car@5.3.3': + resolution: {integrity: sha512-4vgV5Ml4HCJ2iTx7vYhu0ui+Xxo1HQTtVeYgD+JKd5Wij8TlOFZnxOSickqpLcuf1fdGEStgqVItx15UWfzDYA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-cbor@9.2.2': + resolution: {integrity: sha512-uIEOuruCqKTP50OBWwgz4Js2+LhiBQaxc57cnP71f45b1mHEAo1OCR1Zn/TbvSW/mV1x+JqhacIktkKyaYqhCw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-json@10.2.2': + resolution: {integrity: sha512-NnU8HdHKwAoGyrW3S09NMa8aZw0tImLRyR64hoafpLpDpAbA9g1+fb24JsdlugbL4sXUQVwDVA+qK4Ud8V83lA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-pb@4.1.2': + resolution: {integrity: sha512-BSztO4l3C+ya9HjCaQot26Y4AVsqIKtnn6+23ubc1usucnf6yoTBme18oCCdM6gKBMxuPqju5ye3lh9WEJsdeQ==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@ipld/dag-ucan@3.4.0': + resolution: {integrity: sha512-sW4R43w3DbEdoGWWJZCwsblwXa600HCanG9p2w1MJPVBNTNjhvqc3XI0uEqKhT2oqKWrND7uInVtcPmZme7hhA==} + + '@ipld/unixfs@2.2.0': + resolution: {integrity: sha512-lDQ2eRhJlbFaBoO3bhOmDVCLmpOnhwtwbilqUgAAhbhoPSmLrnv7gsBuToZjXOdPaEGSL7apkmm6nFrcU6zh4Q==} + + '@ipld/unixfs@3.0.0': + resolution: {integrity: sha512-Tj3/BPOlnemcZQ2ETIZAO8hqAs9KNzWyX5J9+JCL9jDwvYwjxeYjqJ3v+9DusNvTBmJhZnGVP6ijUHrsuOLp+g==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.1.0': + resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.5.0': + resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jspm/core@2.1.0': + resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} + + '@multiformats/murmur3@2.1.8': + resolution: {integrity: sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + '@netlify/blobs@8.1.0': + resolution: {integrity: sha512-9hIbusvAZjSGBJ42OyFC2AxsEph1LuKQahMWFcPGEIsOqIYHhMRkYA7wSUMhH7naydjNmllpcp3pJLOK4RhFaQ==} + engines: {node: ^14.16.0 || >=16.0.0} + + '@noble/curves@1.6.0': + resolution: {integrity: sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/ed25519@1.7.3': + resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} + + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@perma/map@1.0.3': + resolution: {integrity: sha512-Bf5njk0fnJGTFE2ETntq0N1oJ6YdCPIpTDn3R3KYZJQdeYSOCNL7mBrFlGnbqav8YQhJA/p81pvHINX9vAtHkQ==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@rollup/rollup-android-arm-eabi@4.24.0': + resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.24.0': + resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.24.0': + resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.24.0': + resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.24.0': + resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.24.0': + resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.24.0': + resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.24.0': + resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.24.0': + resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.24.0': + resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.24.0': + resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.24.0': + resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + cpu: [x64] + os: [win32] + + '@scure/base@1.1.9': + resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} + + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + + '@smithy/abort-controller@3.1.8': + resolution: {integrity: sha512-+3DOBcUn5/rVjlxGvUPKc416SExarAQ+Qe0bqk30YSUjbepwpS7QN0cyKUSifvLJhdMZ0WPzPP5ymut0oonrpQ==} + engines: {node: '>=16.0.0'} + + '@smithy/chunked-blob-reader-native@3.0.1': + resolution: {integrity: sha512-VEYtPvh5rs/xlyqpm5NRnfYLZn+q0SRPELbvBV+C/G7IQ+ouTuo+NKKa3ShG5OaFR8NYVMXls9hPYLTvIKKDrQ==} + + '@smithy/chunked-blob-reader@4.0.0': + resolution: {integrity: sha512-jSqRnZvkT4egkq/7b6/QRCNXmmYVcHwnJldqJ3IhVpQE2atObVJ137xmGeuGFhjFUr8gCEVAOKwSY79OvpbDaQ==} + + '@smithy/config-resolver@3.0.12': + resolution: {integrity: sha512-YAJP9UJFZRZ8N+UruTeq78zkdjUHmzsY62J4qKWZ4SXB4QXJ/+680EfXXgkYA2xj77ooMqtUY9m406zGNqwivQ==} + engines: {node: '>=16.0.0'} + + '@smithy/core@2.5.3': + resolution: {integrity: sha512-96uW8maifUSmehaeW7uydWn7wBc98NEeNI3zN8vqakGpyCQgzyJaA64Z4FCOUmAdCJkhppd/7SZ798Fo4Xx37g==} + engines: {node: '>=16.0.0'} + + '@smithy/credential-provider-imds@3.2.7': + resolution: {integrity: sha512-cEfbau+rrWF8ylkmmVAObOmjbTIzKyUC5TkBL58SbLywD0RCBC4JAUKbmtSm2w5KUJNRPGgpGFMvE2FKnuNlWQ==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-codec@3.1.9': + resolution: {integrity: sha512-F574nX0hhlNOjBnP+noLtsPFqXnWh2L0+nZKCwcu7P7J8k+k+rdIDs+RMnrMwrzhUE4mwMgyN0cYnEn0G8yrnQ==} + + '@smithy/eventstream-serde-browser@3.0.13': + resolution: {integrity: sha512-Nee9m+97o9Qj6/XeLz2g2vANS2SZgAxV4rDBMKGHvFJHU/xz88x2RwCkwsvEwYjSX4BV1NG1JXmxEaDUzZTAtw==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-config-resolver@3.0.10': + resolution: {integrity: sha512-K1M0x7P7qbBUKB0UWIL5KOcyi6zqV5mPJoL0/o01HPJr0CSq3A9FYuJC6e11EX6hR8QTIR++DBiGrYveOu6trw==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-node@3.0.12': + resolution: {integrity: sha512-kiZymxXvZ4tnuYsPSMUHe+MMfc4FTeFWJIc0Q5wygJoUQM4rVHNghvd48y7ppuulNMbuYt95ah71pYc2+o4JOA==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-universal@3.0.12': + resolution: {integrity: sha512-1i8ifhLJrOZ+pEifTlF0EfZzMLUGQggYQ6WmZ4d5g77zEKf7oZ0kvh1yKWHPjofvOwqrkwRDVuxuYC8wVd662A==} + engines: {node: '>=16.0.0'} + + '@smithy/fetch-http-handler@4.1.1': + resolution: {integrity: sha512-bH7QW0+JdX0bPBadXt8GwMof/jz0H28I84hU1Uet9ISpzUqXqRQ3fEZJ+ANPOhzSEczYvANNl3uDQDYArSFDtA==} + + '@smithy/hash-blob-browser@3.1.9': + resolution: {integrity: sha512-wOu78omaUuW5DE+PVWXiRKWRZLecARyP3xcq5SmkXUw9+utgN8HnSnBfrjL2B/4ZxgqPjaAJQkC/+JHf1ITVaQ==} + + '@smithy/hash-node@3.0.10': + resolution: {integrity: sha512-3zWGWCHI+FlJ5WJwx73Mw2llYR8aflVyZN5JhoqLxbdPZi6UyKSdCeXAWJw9ja22m6S6Tzz1KZ+kAaSwvydi0g==} + engines: {node: '>=16.0.0'} + + '@smithy/hash-stream-node@3.1.9': + resolution: {integrity: sha512-3XfHBjSP3oDWxLmlxnt+F+FqXpL3WlXs+XXaB6bV9Wo8BBu87fK1dSEsyH7Z4ZHRmwZ4g9lFMdf08m9hoX1iRA==} + engines: {node: '>=16.0.0'} + + '@smithy/invalid-dependency@3.0.10': + resolution: {integrity: sha512-Lp2L65vFi+cj0vFMu2obpPW69DU+6O5g3086lmI4XcnRCG8PxvpWC7XyaVwJCxsZFzueHjXnrOH/E0pl0zikfA==} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@3.0.0': + resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} + engines: {node: '>=16.0.0'} + + '@smithy/md5-js@3.0.10': + resolution: {integrity: sha512-m3bv6dApflt3fS2Y1PyWPUtRP7iuBlvikEOGwu0HsCZ0vE7zcIX+dBoh3e+31/rddagw8nj92j0kJg2TfV+SJA==} + + '@smithy/middleware-content-length@3.0.12': + resolution: {integrity: sha512-1mDEXqzM20yywaMDuf5o9ue8OkJ373lSPbaSjyEvkWdqELhFMyNNgKGWL/rCSf4KME8B+HlHKuR8u9kRj8HzEQ==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-endpoint@3.2.3': + resolution: {integrity: sha512-Hdl9296i/EMptaX7agrSzJZDiz5Y8XPUeBbctTmMtnCguGpqfU3jVsTUan0VLaOhsnquqWLL8Bl5HrlbVGT1og==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-retry@3.0.27': + resolution: {integrity: sha512-H3J/PjJpLL7Tt+fxDKiOD25sMc94YetlQhCnYeNmina2LZscAdu0ZEZPas/kwePHABaEtqp7hqa5S4UJgMs1Tg==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-serde@3.0.10': + resolution: {integrity: sha512-MnAuhh+dD14F428ubSJuRnmRsfOpxSzvRhaGVTvd/lrUDE3kxzCCmH8lnVTvoNQnV2BbJ4c15QwZ3UdQBtFNZA==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-stack@3.0.10': + resolution: {integrity: sha512-grCHyoiARDBBGPyw2BeicpjgpsDFWZZxptbVKb3CRd/ZA15F/T6rZjCCuBUjJwdck1nwUuIxYtsS4H9DDpbP5w==} + engines: {node: '>=16.0.0'} + + '@smithy/node-config-provider@3.1.11': + resolution: {integrity: sha512-URq3gT3RpDikh/8MBJUB+QGZzfS7Bm6TQTqoh4CqE8NBuyPkWa5eUXj0XFcFfeZVgg3WMh1u19iaXn8FvvXxZw==} + engines: {node: '>=16.0.0'} + + '@smithy/node-http-handler@3.3.1': + resolution: {integrity: sha512-fr+UAOMGWh6bn4YSEezBCpJn9Ukp9oR4D32sCjCo7U81evE11YePOQ58ogzyfgmjIO79YeOdfXXqr0jyhPQeMg==} + engines: {node: '>=16.0.0'} + + '@smithy/property-provider@3.1.10': + resolution: {integrity: sha512-n1MJZGTorTH2DvyTVj+3wXnd4CzjJxyXeOgnTlgNVFxaaMeT4OteEp4QrzF8p9ee2yg42nvyVK6R/awLCakjeQ==} + engines: {node: '>=16.0.0'} + + '@smithy/protocol-http@4.1.7': + resolution: {integrity: sha512-FP2LepWD0eJeOTm0SjssPcgqAlDFzOmRXqXmGhfIM52G7Lrox/pcpQf6RP4F21k0+O12zaqQt5fCDOeBtqY6Cg==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-builder@3.0.10': + resolution: {integrity: sha512-nT9CQF3EIJtIUepXQuBFb8dxJi3WVZS3XfuDksxSCSn+/CzZowRLdhDn+2acbBv8R6eaJqPupoI/aRFIImNVPQ==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-parser@3.0.10': + resolution: {integrity: sha512-Oa0XDcpo9SmjhiDD9ua2UyM3uU01ZTuIrNdZvzwUTykW1PM8o2yJvMh1Do1rY5sUQg4NDV70dMi0JhDx4GyxuQ==} + engines: {node: '>=16.0.0'} + + '@smithy/service-error-classification@3.0.10': + resolution: {integrity: sha512-zHe642KCqDxXLuhs6xmHVgRwy078RfqxP2wRDpIyiF8EmsWXptMwnMwbVa50lw+WOGNrYm9zbaEg0oDe3PTtvQ==} + engines: {node: '>=16.0.0'} + + '@smithy/shared-ini-file-loader@3.1.11': + resolution: {integrity: sha512-AUdrIZHFtUgmfSN4Gq9nHu3IkHMa1YDcN+s061Nfm+6pQ0mJy85YQDB0tZBCmls0Vuj22pLwDPmL92+Hvfwwlg==} + engines: {node: '>=16.0.0'} + + '@smithy/signature-v4@4.2.3': + resolution: {integrity: sha512-pPSQQ2v2vu9vc8iew7sszLd0O09I5TRc5zhY71KA+Ao0xYazIG+uLeHbTJfIWGO3BGVLiXjUr3EEeCcEQLjpWQ==} + engines: {node: '>=16.0.0'} + + '@smithy/smithy-client@3.4.4': + resolution: {integrity: sha512-dPGoJuSZqvirBq+yROapBcHHvFjChoAQT8YPWJ820aPHHiowBlB3RL1Q4kPT1hx0qKgJuf+HhyzKi5Gbof4fNA==} + engines: {node: '>=16.0.0'} + + '@smithy/types@3.7.1': + resolution: {integrity: sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==} + engines: {node: '>=16.0.0'} + + '@smithy/url-parser@3.0.10': + resolution: {integrity: sha512-j90NUalTSBR2NaZTuruEgavSdh8MLirf58LoGSk4AtQfyIymogIhgnGUU2Mga2bkMkpSoC9gxb74xBXL5afKAQ==} + + '@smithy/util-base64@3.0.0': + resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-body-length-browser@3.0.0': + resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==} + + '@smithy/util-body-length-node@3.0.0': + resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@3.0.0': + resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-config-provider@3.0.0': + resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-defaults-mode-browser@3.0.27': + resolution: {integrity: sha512-GV8NvPy1vAGp7u5iD/xNKUxCorE4nQzlyl057qRac+KwpH5zq8wVq6rE3lPPeuFLyQXofPN6JwxL1N9ojGapiQ==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-defaults-mode-node@3.0.27': + resolution: {integrity: sha512-7+4wjWfZqZxZVJvDutO+i1GvL6bgOajEkop4FuR6wudFlqBiqwxw3HoH6M9NgeCd37km8ga8NPp2JacQEtAMPg==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-endpoints@2.1.6': + resolution: {integrity: sha512-mFV1t3ndBh0yZOJgWxO9J/4cHZVn5UG1D8DeCc6/echfNkeEJWu9LD7mgGH5fHrEdR7LDoWw7PQO6QiGpHXhgA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-hex-encoding@3.0.0': + resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-middleware@3.0.10': + resolution: {integrity: sha512-eJO+/+RsrG2RpmY68jZdwQtnfsxjmPxzMlQpnHKjFPwrYqvlcT+fHdT+ZVwcjlWSrByOhGr9Ff2GG17efc192A==} + engines: {node: '>=16.0.0'} + + '@smithy/util-retry@3.0.10': + resolution: {integrity: sha512-1l4qatFp4PiU6j7UsbasUHL2VU023NRB/gfaa1M0rDqVrRN4g3mCArLRyH3OuktApA4ye+yjWQHjdziunw2eWA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-stream@3.3.1': + resolution: {integrity: sha512-Ff68R5lJh2zj+AUTvbAU/4yx+6QPRzg7+pI7M1FbtQHcRIp7xvguxVsQBKyB3fwiOwhAKu0lnNyYBaQfSW6TNw==} + engines: {node: '>=16.0.0'} + + '@smithy/util-uri-escape@3.0.0': + resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} + engines: {node: '>=16.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@3.0.0': + resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-waiter@3.1.9': + resolution: {integrity: sha512-/aMXPANhMOlMPjfPtSrDfPeVP8l56SJlz93xeiLmhLe5xvlXA5T3abZ2ilEsDEPeY9T/wnN/vNGn9wa1SbufWA==} + engines: {node: '>=16.0.0'} + + '@storacha/one-webcrypto@1.0.1': + resolution: {integrity: sha512-bD+vWmcgsEBqU0Dz04BR43SA03bBoLTAY29vaKasY9Oe8cb6XIP0/vkm0OS2UwKC13c8uRgFW4rjJUgDCNLejQ==} + + '@types/better-sqlite3@7.6.12': + resolution: {integrity: sha512-fnQmj8lELIj7BSrZQAdBMHEHX8OZLYIHXqAKT1O7tDfLxaINzf00PMjw22r3N/xXh0w/sGHlO6SVaCQ2mj78lg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/eslint__js@8.42.3': + resolution: {integrity: sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/minimatch@3.0.5': + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + + '@types/node@22.10.1': + resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} + + '@types/retry@0.12.1': + resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} + + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + + '@types/wait-on@5.3.4': + resolution: {integrity: sha512-EBsPjFMrFlMbbUFf9D1Fp+PAB2TwmUn7a3YtHyD9RLuTIk1jDd8SxXVAoez2Ciy+8Jsceo2MYEYZzJ/DvorOKw==} + + '@types/ws@8.5.13': + resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} + + '@typescript-eslint/eslint-plugin@8.17.0': + resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@8.17.0': + resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@8.17.0': + resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.17.0': + resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@8.17.0': + resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.17.0': + resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.17.0': + resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/visitor-keys@8.17.0': + resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ucanto/client@9.0.1': + resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} + + '@ucanto/core@10.0.1': + resolution: {integrity: sha512-1BfUaJu0/c9Rl/WdZSDbScJJLsPsPe1g4ynl5kubUj3xDD/lyp/Q12PQVQ2X7hDiWwkpwmxCkRMkOxwc70iNKQ==} + + '@ucanto/interface@10.0.1': + resolution: {integrity: sha512-+Vr/N4mLsdynV9/bqtdFiq7WsUf3265/Qx2aHJmPtXo9/QvWKthJtpe0g8U4NWkWpVfqIFvyAO2db6D9zWQfQw==} + + '@ucanto/principal@9.0.1': + resolution: {integrity: sha512-8eAvaZHW1vyET4X90rkJv6pmW1IOdEYlZYwO3wDgTkC5m9VytBEywCvpzP57cavdYIbbPse5QS9nMEGvk87zhw==} + + '@ucanto/server@10.0.0': + resolution: {integrity: sha512-JMDMT3tFRE0S1cdtx/Hhh7v9FizV6IS0fPrh6pcli7AzKvXVy8Xu6EQ/66Fax4AQM2tkGxNNxjj2wHM7P4CqAg==} + + '@ucanto/transport@9.1.1': + resolution: {integrity: sha512-3CR17nEemOVaTuMZa6waWgVL4sLxSPcxYvpaNeJ6NZo1rfsqdyRXOtbVV/RcI2BtUL0Cao6JM6P9+gdghfc5ng==} + + '@ucanto/validator@9.0.2': + resolution: {integrity: sha512-LxhRbDMIoLt9LYHq/Rz1WCEH8AtmdsBTS/it28Ij/A3W0zyoSwUpAUxBtXaKRh/gpbxdWmjxX+nVfFJYL//b4g==} + + '@vitest/expect@2.1.8': + resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==} + + '@vitest/mocker@2.1.8': + resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.8': + resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} + + '@vitest/runner@2.1.8': + resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==} + + '@vitest/snapshot@2.1.8': + resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==} + + '@vitest/spy@2.1.8': + resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==} + + '@vitest/utils@2.1.8': + resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} + + '@web3-storage/access@20.1.0': + resolution: {integrity: sha512-IY6ICPRWE8++2jxvy+LzAiFvwAOIHR8cu9eNt+VT5sAFE796o4ma7GSU0eXRCiShmV2n6iSWAwWRT6XD5zIqPA==} + + '@web3-storage/blob-index@1.0.4': + resolution: {integrity: sha512-04+PrmVHFT+xzRhyIPdcvGc8Y2NDffUe8R1gJOyErVzEVz5N1I9Q/BrlFHYt/A4HrjM5JBsxqSrZgTIkjfPmLA==} + engines: {node: '>=16.15'} + + '@web3-storage/capabilities@17.4.1': + resolution: {integrity: sha512-GogLfON8PZabi03CUyncBvMcCi36yQ/0iR5P8kr4pxdnZm7OuAn4sEwbEB8rTKbah5V10Vwgb3O5dh0FBgyjHg==} + + '@web3-storage/clock@0.4.1': + resolution: {integrity: sha512-VHAyvbl7ZrNls6yltS5Djuwjz9Rw0rcA8tpv7qQp1WoheY00YBdqa8gjR1V4egVkqV1ZugGA06XH+ug0OhGXDg==} + + '@web3-storage/data-segment@5.2.0': + resolution: {integrity: sha512-Jr/bdweoEQ0lWIaNuFcYxM6BHYmXHBWwfXygHyp370agkAdU+dIFIbm+tX+66XP/1YmEUi4JI2I80psDtoJ++Q==} + + '@web3-storage/did-mailto@2.1.0': + resolution: {integrity: sha512-TRmfSXj1IhtX3ESurSNOylZSBKi0z/VJNoMLpof+AVRdovgZjjocpiePQTs2pfHKqHTHfJXc9AboWyK4IKTWMw==} + engines: {node: '>=16.15'} + + '@web3-storage/filecoin-client@3.3.4': + resolution: {integrity: sha512-T2xur1NPvuH09yajyjCWEl7MBH712nqHERj51w4nDp6f8libMCKY6lca0frCrm4OC5s8oy0ZtoRFhsRYxgTzSg==} + + '@web3-storage/pail@0.5.0': + resolution: {integrity: sha512-BUuunK6ZQQfNvECB2st0G7/rd0Vfsn6jFg01tfMLEsitFJWI9J503ixKJ8jWpoNW/3juJ32HQpo8ar3pmgG5uA==} + hasBin: true + + '@web3-storage/pail@0.6.0': + resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} + hasBin: true + + '@web3-storage/upload-client@17.1.1': + resolution: {integrity: sha512-PIPrg8uF1+NjLLNyiYQoT5gHBIO1aCiyFhYAZtg5JZZGYq/hRLh8xBTQLEBsSzSPGNm0Xpx8o4I3YQ/tTE0wUA==} + + '@web3-storage/w3up-client@16.5.2': + resolution: {integrity: sha512-yJNh3r2QWZbn2jQ1ZfsnDJ1HIyhv9akEXeFWx+xFxKViT6df8IzT6BtCnxxFL2ED3Tx7rKVVG1pNatKRO3T+Uw==} + engines: {node: '>=18'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + actor@2.3.1: + resolution: {integrity: sha512-ST/3wnvcP2tKDXnum7nLCLXm+/rsf8vPocXH2Fre6D8FQwNkGDd4JEitBlXj007VQJfiGYRQvXqwOBZVi+JtRg==} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + any-signal@3.0.1: + resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} + + archy@1.0.0: + resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-all-x@1.1.2: + resolution: {integrity: sha512-rOaX+4+ihVMmJbXMyAEQF1UDfQO2Q8RQZtokSvb2ZpXy/JDaHyY6OtVwEXDmhaLg/FsK3Pb0hJNzWbAZbnwZZg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-any-x@1.1.2: + resolution: {integrity: sha512-b9cGMCI0YlIYDuINxHy7ipAO0v9nixJg0RYwDsiJMxQewMOwBpLMW/jJGAHBoDmaHb7b2jR/j7SnyH49ZDxJyQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-filter-x@3.1.2: + resolution: {integrity: sha512-Dui8g/SEu2a8UY5f3GNzXx84WGIMYPrRaQtL5L3h1cxybDT5rsi/bkDpWq7y3/FZ5nvxyJNx4ld5C6qA3lqPDg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-for-each-x@3.1.2: + resolution: {integrity: sha512-dv8xr/sVk3d5BVyki+4CGDvJdyREEVnvV+RVLIH6IlQwpYtDpqqkpuL9Wv+io+lFprnCj0SORomlarIMdmNK/A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-like-slice-x@2.2.2: + resolution: {integrity: sha512-GqQzhIMscxFoePBnkOJNrj80A9uUGInqln4lmyzJpeJZVqoQ+78aEuRmjWVz0kuuj+MDzOJMddHIyp4kyQxJFg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-reduce-right-x@3.1.2: + resolution: {integrity: sha512-wdJDvghyE/mT5h6djsO9cAKUeLxpVohUhBJ3etms8v/g/5wt9lmL+nOSETDne3oYMLHdd44lNbxjSbWUBNxrXQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-slice-x@4.2.2: + resolution: {integrity: sha512-B/ZxDn/WVzlwNAzH2XPZb8MbqMKHAp1CiCjygLH2GamBp3tMY1Dcbwh08X+H3IWkMaV0dr8aT+BRIG0zHh199w==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + array-some-x@3.1.2: + resolution: {integrity: sha512-JccQYIaJSaDCcKsB3x7/SYnhpnKbeiyJT4g5DtkZllzfP9GfDCnl53ILaH3saiJcbFg83eWR4VbsGtzsiHLpYg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + arraybuffer-equal@1.0.4: + resolution: {integrity: sha512-B/HbicKd82qtq5NiNShqx6oAhHkYi+VFREUyHo9qdjyEwQDLL626XM80M88Pvr2TC7roUX3UsVALGvNIqeqc1g==} + + as-table@1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + + assert-is-function-x@3.1.2: + resolution: {integrity: sha512-FiMv0RYR/eMQk2EOMYJKvm+QFQa2AQzjccI9rN4cpvNd6M+UuobnV6m0sqIO5U+Q2LillGwaya16MRGa2Sr6+w==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + assert-is-object-x@3.1.2: + resolution: {integrity: sha512-PGTfDoK9nx05h4v17u5PmtLwdtty1wGQA1FZ+ZpV+YmgMSFifAwajxhCBca2p6mPfKlGUryHut7vc36UxQxG8w==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomically@2.0.3: + resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} + + attempt-x@2.1.2: + resolution: {integrity: sha512-vblT/0yT5dmm2qo8mfBjtiu0BGL/HWhxBFTrqHvkjQQSsXb/sTmpYIi1StJGSN5W/TX2E+FsuX7c23ExMZy2jw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + better-sqlite3@11.7.0: + resolution: {integrity: sha512-mXpa5jnIKKHeoGzBrUJrc65cXFKcILGZpU3FXR0pradUEm9MA7UZz02qfEejaMcm9iXrSOCenwwYMJ/tZ1y5Ig==} + + big-counter-x@4.1.2: + resolution: {integrity: sha512-rO414jDJf//NDNvIfbChPT+qAXrs5aXIWwq+327qWVn64eKpE+dMsr72o+18tYsSOnF79C6+LO9c756/h6Ghaw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + bigint-mod-arith@3.3.1: + resolution: {integrity: sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==} + engines: {node: '>=10.4.0'} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-readablestream-to-it@1.0.3: + resolution: {integrity: sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cached-constructors-x@2.2.1: + resolution: {integrity: sha512-GQFEIdT6mBLUfY986TdQA05WnmkkCFf0CDk++VfNraIWSCz0889bAu14FPMuoKNbVySAub7ItDa95ALp2008FQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + calculate-from-index-x@3.1.2: + resolution: {integrity: sha512-7TsLYHEPvyCWaFwCQgCWcE6Lt5BowjA/TqggJFhE4hs4c4UM36H3Sodf5Jy0TxVepu0pYTWHtKaeOvoKrRl4JA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + capnp-ts@0.7.0: + resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} + + carstream@2.2.0: + resolution: {integrity: sha512-/gHkK0lQjmGM45fhdx8JD+x7a1XS1qUk3T9xWWSt3oZiWPLq4u/lnDstp+N55K7hqTKKlb0CCr43EHTrlbmJSQ==} + + cborg@4.2.7: + resolution: {integrity: sha512-zHTUAm+HAoRLtGEQ1b28HXBm8d/5YP+7eiSKzEu/mpFkptGYaMQCHv15OiQBuyNlIgbCBXvBbZQPl3xvcZTJXg==} + hasBin: true + + chai@5.1.2: + resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} + engines: {node: '>=12'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + charwise@3.0.1: + resolution: {integrity: sha512-RcdumNsM6fJZ5HHbYunqj2bpurVRGsXour3OR+SlLEHFhG6ALm54i6Osnh+OvO7kEoSBzwExpblYFH8zKQiEPw==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + cli-color@2.0.4: + resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==} + engines: {node: '>=0.10'} + + clipboardy@4.0.0: + resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} + engines: {node: '>=18'} + + collections-x@3.1.2: + resolution: {integrity: sha512-UBj0YBtdMhubwaYnbfmCA8PHS79mbvCPYTw7YzUGhQzuyH3jf7Bc8RXQHqiZrTDtcl8+4oSbehFyu4jUH8PGag==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + conf@11.0.2: + resolution: {integrity: sha512-jjyhlQ0ew/iwmtwsS2RaB6s8DBifcE2GYBEaw2SJDUY/slJJbNfY4GlDVzOs/ff8cM/Wua5CikqXgbFl5eu85A==} + engines: {node: '>=14.16'} + + consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + + data-uri-to-buffer@2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + debounce-fn@5.1.2: + resolution: {integrity: sha512-Sr4SdOZ4vw6eQDvPYNxHogvrxmCIld/VenC5JbNrFwMiwd7lY/Z18ZFfo+EWNG4DD9nFlAujWAo/wGuOPHmy5A==} + engines: {node: '>=12'} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + dot-prop@7.2.0: + resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-fetch@1.9.1: + resolution: {integrity: sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==} + engines: {node: '>=6'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + err-code@3.0.1: + resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + + es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + + es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + + esbuild-plugin-replace@1.4.0: + resolution: {integrity: sha512-lP3ZAyzyRa5JXoOd59lJbRKNObtK8pJ/RO7o6vdjwLi71GfbL32NR22ZuS7/cLZkr10/L1lutoLma8E4DLngYg==} + + esbuild-plugin-resolve@2.0.0: + resolution: {integrity: sha512-eJy9B8yDW5X/J48eWtR1uVmv+DKfHvYYnrrcqQoe/nUkVHVOTZlJnSevkYyGOz6hI90t036Y5QIPDrGzmppxfg==} + + esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.16.0: + resolution: {integrity: sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + + event-target-shim@6.0.2: + resolution: {integrity: sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==} + engines: {node: '>=10.13.0'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exit-hook@2.2.1: + resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} + engines: {node: '>=6'} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + + ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.2: + resolution: {integrity: sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==} + + fast-xml-parser@4.4.1: + resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} + hasBin: true + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fdir@6.4.0: + resolution: {integrity: sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-index-x@3.1.2: + resolution: {integrity: sha512-BrDZ6eZDuspxF8qQ0n6044fnOzhY+ITNn7M+iqHekU6l1eeu6UcC5dqm+3tGip5vG4JHEEfbiT7vhcJcj3H9Bg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-iterator@1.0.2: + resolution: {integrity: sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==} + + get-own-enumerable-keys-x@2.1.2: + resolution: {integrity: sha512-2bf5zqZELbF1XX9ick95QwvBPz7rBs7FxZBXcnAj+yTxNTVd5Ns3FLPZbI5U+9RsxZ82Cswf97XvlgoSdIT2qg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + get-own-enumerable-property-symbols-x@2.1.2: + resolution: {integrity: sha512-MUKw2J+D1TLh4esLFRzqWBqqjlqBYMfOt4MTRfHT6nNBDt9tF94fEDPYY01fyR8DN3XK6AOqYXBegrGdMZW1dg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + get-own-property-names-x@3.1.2: + resolution: {integrity: sha512-616M5sAhDfRjUBAJPFYDuVmZD+rSi2MQSCo+96zr8u4xmRDaUPzQexBheey7qsYhcAqGRL6ZBMFOW+eUOoSgdQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + get-own-property-symbols-x@2.1.2: + resolution: {integrity: sha512-cFVkod03zzfHKZwwluRzva5EmrV6PuhOVNNMILc+qwbshs/tt+zJRROL4oWjtI7k6ERzMkF/PILOL2fhG0AbnA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + get-prototype-of-x@2.1.2: + resolution: {integrity: sha512-LBo5X3ed0qI8k6UmEo7JgohXu3SGki60IdpnT1OlNp83GaxK66yiMjFZk67ofPH3aHENEc1+qvCmBhrlliVPPQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + get-source@2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + hamt-sharding@3.0.6: + resolution: {integrity: sha512-nZeamxfymIWLpVcAN0CRrb7uVq3hCOGj9IcL6NMA6VVCVWqj+h9Jo/SmaWuS92AEDf1thmHsM5D5c70hM3j2Tg==} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-boxed-string-x@2.1.1: + resolution: {integrity: sha512-1MmOo3H8UbI6JQ3e3TaxAXHQmpnyrM5DjYRqRXNvjl/UHZqb2fEyfp0UPvtbzvmOf0+sBzcv4ea/LEw87WNyVA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-own-property-x@4.1.2: + resolution: {integrity: sha512-P6CEga37+01XlBfYBfnp4e2e5Mj0geyW5zvBhbmggkr9DkxtXWlDQIIv2PaJIOWql/rfGm7GDpKBqZ5/PT1wrA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbol-support-x@2.1.2: + resolution: {integrity: sha512-RpWVMhXSkiJCXI7+bavsapHwlS0VD7rCOSwhzcy0yZzFXxr+FznUBK4OkECVH/EOM1ZoVXw8OzABIEvaEFl+Zg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-to-string-tag-x@2.1.2: + resolution: {integrity: sha512-xVv4BRcvyT9FAZSzvWD6tzVWj5JHK2d+mcv2wRSIfNBhG534hSfDGPdtx3hHJUE94BufO+pFyVpKbnaC6dsalA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-working-bind-x@1.0.1: + resolution: {integrity: sha512-iVknmNYk7CdVSDsdIyaeyPNPHlhoESfNEztH9J6kUayhj123M1so039HfC91vAOtR4NyLXWyvaFiNaXvmT/JRQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + hashlru@2.3.0: + resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + idb-keyval@6.2.1: + resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + + idb@8.0.0: + resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + index-of-x@3.1.2: + resolution: {integrity: sha512-IgA7qpd3a0QeGD6GyznKqTz7IGQ6aubo19yi9Canit1ajRnqafF9iTnhuarp+ZEUBEpdIkbHSa9cpKPHA+N9cg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + infinity-x@2.2.1: + resolution: {integrity: sha512-aGc1EANwAzNPQYQ1uqZRiEVOK6NktlCQ+72Ey4+bDkKIiA93vPZiwjkz2sxgaRaEBed2FwXDdgPHez0K97sf3w==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + interface-blockstore@5.3.1: + resolution: {integrity: sha512-nhgrQnz6yUQEqxTFLhlOBurQOy5lWlwCpgFmZ3GTObTVTQS9RZjK/JTozY6ty9uz2lZs7VFJSqwjWAltorJ4Vw==} + + interface-store@6.0.2: + resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} + + ipfs-unixfs@11.2.0: + resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} + + ipfs-utils@9.0.14: + resolution: {integrity: sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer-x@2.1.2: + resolution: {integrity: sha512-8SiqbYgnBDoLFsoGP4VEW8pZuu2TW2/owsS1RDlhlg7T50XLn0QRqgzRKiA1l9LVFXbuBoGKAumhtN4lf9Erhw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-array-like-x@2.1.2: + resolution: {integrity: sha512-XkIyHvSRWLcsAYAQq71pAMqcEaq2tZuK6saW9H1iMel3IoyN2HFy6RjRzvCQR2tHqlGW7ueHxAgalr7rjYHtXA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-array-x@2.1.2: + resolution: {integrity: sha512-XuKYtKwek6xUys0fEpRQXzlvHpuO4WoDrGRHjoHw+f+AevGkiu4CKkqN2bBHKhmlLKAHv+6ekUnK5pnsNM1C4Q==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-boxed-primitive@1.0.1: + resolution: {integrity: sha512-9SGCUKKEgd7tAkgJgkiz4Hli/ASBTM37CjuT1+9C6ONC7G6HjJwaS4Vmi6ePMqBhTu0S05zFkuBzX0D3MhD2LA==} + + is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-data-view-x@2.1.2: + resolution: {integrity: sha512-IUIxqqWkplq+w3oQLmzzPW16OBJLMtPmLknR1tyj8XIPoZKpy6dyCsJs/6+Axzt85KMAGaly8bRZnpBCGwW/TQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-deep-strict-equal-x@1.1.2: + resolution: {integrity: sha512-qUeYt713o++F+SBaD+4e9kvwcuN145KNTTj6ESQKPaid3EI+LaFaKfjBgJ5Kq8vKgnLB2tGvFRPcx68PamsNJw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-electron@2.2.2: + resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} + + is-error-x@2.1.2: + resolution: {integrity: sha512-8bQJRMUP3QFz/PcS3TC6ZkHOhDv8jAvDNABNEMnclZJsLdFtJf0PzhG2OUee/KtP8eA2UxK6tM6HMqWk7cj04A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finite-x@4.2.1: + resolution: {integrity: sha512-Ec5P0yFz5GR8uYQbVNx1QFUzgggsuhv85iDUJzrAe6aiJB8DTIivJKJoDBpHDcb7VXi3tEJTnBIYYRiRwgsIxQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-function-x@4.1.2: + resolution: {integrity: sha512-Ddyyh7mT7Wa4/WCvJ1yHOVQ8Sy+fx76PlfNYoKWJAPUj3O+DjYRQF4NdZ8zRIpkN08Oyto0yPkckUrShYthrFQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-index-x@2.1.2: + resolution: {integrity: sha512-AaCvzDt3cpJg+gVeOxferhetS4bMH9Npr7MeNNwA6GZlbY5PxWkMQj8HsezyPRg7TLKO9wrnRBSUNqeg6LpgiQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-integer-x@2.2.2: + resolution: {integrity: sha512-06SipMhKYqmrf6h6P96d/0QMy7kEjo91dKjlgym9mx3yb8F0DMuLji16QA4iq1tn4ZaWMQg9dK7S57TA/rZayA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-length-x@3.2.2: + resolution: {integrity: sha512-FvtrFszHlUmX1LDYLvdd/iooYZWiVzZal0RCEDdx79vqYOChqoIxgiZETppp60znCM37dKubFLIcpQYhDpSwMw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-map-x@2.1.2: + resolution: {integrity: sha512-IEat1bmsZ/R4Y9hSeRjmuKTj9DXcc2tOeOCH2HeY1V1mUUY1oYUsPAci/6t6zIQrFktbqbQThthJ8Rpu2iMF0g==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-nan-x@2.1.1: + resolution: {integrity: sha512-pF3332LooafxENk8PnUjZlW/VTX1SNI9/gHfMKWXX/5PzpA7wjnaQcfeBa8Hyo77V1T1WOZ65YeRpidZvShkrg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-network-error@1.1.0: + resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} + engines: {node: '>=16'} + + is-nil-x@2.1.1: + resolution: {integrity: sha512-8PThmdFnNVMfzg+rsUD9lWnZ9PMOPsOzDTxTycc5xIU7nlu8jEFhIj6wk+1yTeu2UHoyj78mueL9kh/eLIGumQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-object-like-x@2.1.2: + resolution: {integrity: sha512-QledvfxPGy+NdNy5hmB7G4+AnK1y6KaBW55es/K+GfGkvX9Dvf/MgoQB5la002z1Htp3HQiiOfInbpxo4L0V6A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-primitive-x@1.0.1: + resolution: {integrity: sha512-Z29Qi/aRkELj6LO3LnnSAPN1929UIpY0h0yha5zULYo3VY1Q8hr2ocAE/fVZf22D8LFwoDoGSZwepbk7nvv+Ag==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + + is-regexp-x@3.1.2: + resolution: {integrity: sha512-Vd9F0FLvNQgEEJvcgIIpGiKnmLaYXjUSyFJd3MLNzozi79iIfDM0LfwtdB7N2ly3AUDHKlhrbUYXBBzRGt2/Sg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-safe-integer-x@2.2.2: + resolution: {integrity: sha512-ls5MYHB6n4sUtRTFR/EfngesYZUCv57/sWChbaV53q1HZSG5gYiDOIgOwCu9b95RW23LdBrbCf4A5u2F7gp2Zg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-set-x@2.1.2: + resolution: {integrity: sha512-cPidjAosuclJZzYk01eMmTEzNnB/R29a6TgJsXaCzg4q8czSGEJpuslUo4Rk4ZI6aIeQESuqj9VZhUHP5AUTvA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-surrogate-pair-x@3.1.2: + resolution: {integrity: sha512-kRjOqq0CUPVaf9apeFv6vfjPbTJjiWbDR11bzryKjrT6j/Go3dZ8/Ed464AGpCB2vUV6KYcSHoholzplgbFfeg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-var-name@2.0.0: + resolution: {integrity: sha512-U+7mpdfaV4Qz2hDNy1Vt7TjWwdIp6br/w7CUlTnyMdsJq+IOSZrh+RsJNlSSckPAnTllhWxpiqC7VSxVTbcr2Q==} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + is64bit@2.0.0: + resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iso-url@1.2.1: + resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} + engines: {node: '>=12'} + + it-all@1.0.6: + resolution: {integrity: sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==} + + it-filter@3.1.1: + resolution: {integrity: sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==} + + it-glob@1.0.2: + resolution: {integrity: sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==} + + it-last@3.0.6: + resolution: {integrity: sha512-M4/get95O85u2vWvWQinF8SJUc/RPC5bWTveBTYXvlP2q5TF9Y+QhT3nz+CRCyS2YEc66VJkyl/da6WrJ0wKhw==} + + it-map@3.1.1: + resolution: {integrity: sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==} + + it-merge@3.0.5: + resolution: {integrity: sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==} + + it-parallel@3.0.8: + resolution: {integrity: sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==} + + it-peekable@3.0.5: + resolution: {integrity: sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==} + + it-pipe@3.0.1: + resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + it-pushable@3.2.3: + resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} + + it-stream-types@2.0.2: + resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} + + it-to-stream@1.0.0: + resolution: {integrity: sha512-pLULMZMAB/+vbdvbZtebC0nWBTbG581lk6w8P7DfIIIKUfa8FbY7Oi0FxZcFPbxvISs7A9E+cMpLDBc1XhpAOA==} + + itty-time@1.0.6: + resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.1: + resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + + math-clamp-x@3.2.2: + resolution: {integrity: sha512-Oi8TI3q8QsIMAR9mhH4u2u52kqUVzvehq6tOoK92ipZO/SNVoFpAgr7alHuIQdevvczP4X71GZfMlkexJAarTw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + math-sign-x@4.2.2: + resolution: {integrity: sha512-mQ2o1VayrZ6Jaz8VyP8B7h/hdn2iAnbUOrQh4rTiwbpULhktpD8IpHGBw8Qo2fmv97Z1P3YzLF3X/DkbIHBQmA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + memfs@4.14.1: + resolution: {integrity: sha512-Fq5CMEth+2iprLJ5mNizRcWuiwRZYjNkUD0zKk224jZunE9CRacTRDK8QLALbMBlNX2y3nY6lKZbesCwDwacig==} + engines: {node: '>= 4.0.0'} + + memoizee@0.4.17: + resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} + engines: {node: '>=0.12'} + + merge-options@3.0.4: + resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} + engines: {node: '>=10'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + miniflare@3.20240718.0: + resolution: {integrity: sha512-TKgSeyqPBeT8TBLxbDJOKPWlq/wydoJRHjAyDdgxbw59N6wbP8JucK6AU1vXCfu21eKhrEin77ssXOpbfekzPA==} + engines: {node: '>=16.13'} + hasBin: true + + miniflare@3.20241205.0: + resolution: {integrity: sha512-Z0cTtIf6ZrcAJ3SrOI9EUM3s4dkGhNeU6Ubl8sroYhsPVD+rtz3m5+p6McHFWCkcMff1o60X5XEKVTmkz0gbpA==} + engines: {node: '>=16.13'} + hasBin: true + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multiformats@11.0.2: + resolution: {integrity: sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + multiformats@12.1.3: + resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} + engines: {node: '>=16.0.0', npm: '>=7.0.0'} + + multiformats@13.3.1: + resolution: {integrity: sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==} + + murmurhash3js-revisited@3.0.0: + resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} + engines: {node: '>=8.0.0'} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nan-x@2.2.1: + resolution: {integrity: sha512-kZN/tgpupBg+ZVB+25lTDNKwnDGCFia36awekeIRj4AF3zQ/bnRDgr3M3mEV2KmFYC+UW8rVCCPjAz0rGdZk8A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + + native-fetch@3.0.0: + resolution: {integrity: sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==} + peerDependencies: + node-fetch: '*' + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + + node-abi@3.68.0: + resolution: {integrity: sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==} + engines: {node: '>=10'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + + node-sql-parser@3.9.4: + resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} + engines: {node: '>=8'} + + node-sqlite3-wasm@0.8.28: + resolution: {integrity: sha512-QK5Q0+sgsHNPWiOPFHiBWrfXuJa9UDXi7nUDHhyIlVgoVzltWKDGqoNOERjga+o+ncr5Od7A7kkB4GEmsoUuSA==} + + noop-x@1.2.1: + resolution: {integrity: sha512-X+jn3u2YhlAjteZIfrcVxaDLRfnrMvkzQ+jRatOX8UO7PFqU0QKlcyI2DhvLKEK2K4u1cRrZw9QqK3XruvyH2A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + normalize-space-x@4.1.2: + resolution: {integrity: sha512-nADMBxZ8tCAS/VR6s+EU7p2P/+Hs0GSmUvkXyThZmdACqDIeyAmRHi4aRsbR32Ec0H+AC71srh2l3I5CF0NKvw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-create-x@3.1.2: + resolution: {integrity: sha512-2wuzXZSKzMHGFb7WDBwtwzGScucbHxGASyL8ti/XrM50BS0kfbmVmZAxe606Itb/rI8I2KNT6K0m3xsXCLco0g==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + object-define-properties-x@5.1.2: + resolution: {integrity: sha512-HSBe2tnSHjxTqVzS7KS59HpMffRBYEnI4xb/9k86rfC0ENLTx/o2YzK4G1D9FTQXOSoUrCPNJXWA7C64LYe1kQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + object-define-property-x@5.1.2: + resolution: {integrity: sha512-s/p8ajRQwsPBe3+8v2DjeGYBTS35XOSxBVwvvf481/gAsvcvNRjttbck2t6NPbdkkLh+Uqf9WaeiFTC1LIsZPA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + object-get-own-property-descriptor-x@4.1.2: + resolution: {integrity: sha512-ukh2PlxrPWenQ7pcCfeUbFg4Bib8Km1CvFVKrgWbPVgkBM7hMC3EhJ3RFK1zl8c3dnp+8l25IGM9RF3wpkcIQA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys-x@3.1.2: + resolution: {integrity: sha512-Ov6fQwPoxBG5iYXFpX66cSJVOKp6b06HI7KUfBTQoomVzCQSDefelL1w9IIQSXKoWjcTYIxjmuA+qNXJNGAnxA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + one-webcrypto@1.0.3: + resolution: {integrity: sha512-fu9ywBVBPx0gS9K0etIROTiCkvI5S1TDjFsYFb3rC1ewFxeOqsbzq7aIMBHsYfrTHBcGXJaONXXjTl8B01cW1Q==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-defer@3.0.0: + resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} + engines: {node: '>=8'} + + p-defer@4.0.1: + resolution: {integrity: sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==} + engines: {node: '>=12'} + + p-fifo@1.0.0: + resolution: {integrity: sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + + p-retry@5.1.2: + resolution: {integrity: sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-retry@6.2.0: + resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} + engines: {node: '>=16.17'} + + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + + p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-int-x@3.2.2: + resolution: {integrity: sha512-2hRe7DQZb8+YAXHu1esNwfEp6+yypsl1wayA7Vm7s/atrkUPltuG/y9KKfLcg3Ns/eG9EFJCugVS2eDZ8mJdYA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + partykit@0.0.111: + resolution: {integrity: sha512-pbUzJmulPTqZWgtH++eClnLlddTWS0RPKOAQyexYiSqGEg2/Ff84Ep0qWFqy+53wiz098DPFekRI375Qy2GsZw==} + hasBin: true + + partysocket@1.0.2: + resolution: {integrity: sha512-rAFOUKImaq+VBk2B+2RTBsWEvlnarEP53nchoUHzpVs8V6fG2/estihOTslTQUWHVuHEKDL5k8htG8K3TngyFA==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + + path@0.12.7: + resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + + prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} + hasBin: true + + printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + progress-events@1.0.1: + resolution: {integrity: sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==} + + prolly-trees@1.0.4: + resolution: {integrity: sha512-vtnxfw5wnUHbGa0IIIk9B9DRztJWZw+t9d0s0iGxY/VzEGCg2EMl8GgGU3EhSquFLWapwbGjFTL1ipbezaXR3g==} + + property-is-enumerable-x@2.1.2: + resolution: {integrity: sha512-lRqJh4yGnwiZUx7x8abWhfucNsImqwxbFoCQzRjfwJflOBenZoFq/YMlWJShdzBmqd9i2/RrrvFW8cBs1+H+3w==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + + protons-runtime@5.5.0: + resolution: {integrity: sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + rabin-rs@2.1.0: + resolution: {integrity: sha512-5y72gAXPzIBsAMHcpxZP8eMDuDT98qMP1BqSDHRbHkJJXEgWIN1lA47LxUqzsK6jknOJtgfkQr9v+7qMlFDm6g==} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + react-native-fetch-api@3.0.0: + resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + rename-function-x@1.1.2: + resolution: {integrity: sha512-3kkzZck51lWM7V71Px8ynhLX1JbS5EQPPeOfPywp41f50VLKdh+1lZJz3VgzTDRYerQIw1uxHUCm5XXFweCWIg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + replace-comments-x@3.1.2: + resolution: {integrity: sha512-Ig8PT8++5YLhTDD8EokcTyawaULbOzzeFk8Tb6VVAVqiqZ5ZFcU1/fBw9IEwjd8r3wMm6HSZmQOCYYYny8dGnw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + require-coercible-to-string-x@2.1.1: + resolution: {integrity: sha512-/6GKFuhc8z1zBXkTLQDH1OrbkeMWKwvJbjkLFMiKi3LOBpn+5pAdgV5B8Y4vXWrlwhvpIeg3dFRFDZdcyBDQyA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-object-coercible-x@2.1.1: + resolution: {integrity: sha512-te3nTMzvKCUMIRBQYAtLAPMfXvYnYCijZplqA3/VdSGFFNzgkiuaUGUQdZDSHhK20Z7xewHRWW4XkVpUVrQwMA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup-plugin-inject@3.0.2: + resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + + rollup-plugin-node-polyfills@0.2.1: + resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} + + rollup-pluginutils@2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + + rollup@4.24.0: + resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + same-value-x@2.1.1: + resolution: {integrity: sha512-dPxZF9siIDDQk0oZ4g88mA5OcLx7EKKqU2PNSyr8RCAjsfV1DLfWOVnETxEZSHXr+TpDy0Jco6en/RLO33vfdQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + same-value-zero-x@2.1.1: + resolution: {integrity: sha512-EYw4MgarqX8i//WneRq/jgamDcYC7KUrS9yNoRGvvQMTtrBeMLSPfnjz4+KgqueDW9If5iq2Km4MV9AswuMA9A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-bind-x@1.0.3: + resolution: {integrity: sha512-UNt+DzNdI/a6dfkpJoGTCarOKnBBNxTwcjrCqQWtHQ5NZtI0fdjL4hB4YtYCbOETGnNw5/e69K6URhSs738KLg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + simple-call-x@1.0.3: + resolution: {integrity: sha512-f80t0ft82q15coHABjl95mnqCDIkpxLeQzfwdwtc0bx0FTnsS8uKDseyY0Pxa2O6Oh5Lpe2QKG2Q3NXWPjxEMQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + simple-methodize-x@1.0.4: + resolution: {integrity: sha512-omskIMJiH/urw+5mzLDYsV7yVFigo5LHTA24CHAFkh+HmZ53eQtfoeh4nkGI03JFCacAnL1uhNCyMlJTecXvzg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + sparse-array@1.3.2: + resolution: {integrity: sha512-ZT711fePGn3+kQyLuv1fpd3rNSkNF8vd5Kv2D+qnOANeyKs3fx6bUMGWRPvgTTcYV64QMqZKZwcuaQSP3AZ0tg==} + + split-if-boxed-bug-x@2.1.2: + resolution: {integrity: sha512-s16LLvA6VVqayT560dGsP1AXGWAIBsd/1KotRSjoPiaAMPKLbyio9iAsR+b6RGBF22zdlBLGjc4KyU5KCfmzIA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + stacktracey@2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + + stream-to-it@0.2.4: + resolution: {integrity: sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + stubborn-fs@1.2.5: + resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-iterator-x@1.1.2: + resolution: {integrity: sha512-Zx/FE0En8jKE0iEGO/x1iqBW08dkY29hFrU3VC/gZktCHqQd3rKoXzhP4ArGAS99/jkOC7A0FMEPCGX4EWOG/Q==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + symbol-species-x@1.1.2: + resolution: {integrity: sha512-k15dJ8HS3gXNr/wwUbe3RAYkq/oWK3TbNa7g9/XaVK2S8f9GLACJlfwvUASIlTpzi3ip0s5m1NVmCqc13Cs/Zw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + sync-multihash-sha2@1.0.0: + resolution: {integrity: sha512-A5gVpmtKF0ov+/XID0M0QRJqF2QxAsj3x/LlDC8yivzgoYCoWkV+XaZPfVu7Vj1T/hYzYS1tfjwboSbXjqocug==} + + system-architecture@0.1.0: + resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} + engines: {node: '>=18'} + + tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + timers-ext@0.1.8: + resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} + engines: {node: '>=0.12'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + + tinyglobby@0.2.9: + resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.1: + resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + to-boolean-x@2.1.1: + resolution: {integrity: sha512-ir6nGXyTFDPIUiMuePbGIx5UnY6JbxMw7e18djKrDHhXvt14pbhsbatFzySIVW++4vevTtQNYinh8bKOCW//KQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-integer-x@4.2.2: + resolution: {integrity: sha512-dOYAgv5mt1/2rQsHne+DcHQkO9maWn1qreikAg5EMIdVZXNMYfKmrYrtKKunS4CUyqnvd1UaLgrY3QRkj8jM+A==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-length-x@4.2.2: + resolution: {integrity: sha512-ZOla1LzUusLnMyjieVtLQTtmLctIYSrXK34V2dGdALXYxIGvFxapiKgkQdIH1PlV1mPUFDziDr1TkYEa1zBwFA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-number-x@3.2.2: + resolution: {integrity: sha512-snnymZEexIsNKZQu2Ak6sZpQ9u0BZ5VJfcjBuZHg6IUih/42rup75jQlTE1K5loUB/dBeZj8uMLa2xA2VxsccQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-object-x@2.2.1: + resolution: {integrity: sha512-bTqODgmN4q3TJfIVDd4qNRNyDxOHyy0ZzFEwJsZr0RUseKQFTAcGszFCAtypLKjfTsSxoPZUkq9OPB9h/Hf2PQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-primitive-x@2.1.2: + resolution: {integrity: sha512-AXm1W8QR8tvi8HeClW3dKQxBErtvBgg54RjLY3HvuT+aXUwDPAQJETZED9yk8xA11Nd4NSql8iz4QP4nmnU2oA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-property-key-x@3.1.2: + resolution: {integrity: sha512-DHgewI2SIkHGpB5jGeesfSaEN88N0P6A83mYCd28IN5T9FkaKtb7jvqAajey1Vv20GcKAcPiL8hlEeeWdbaE4g==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-string-symbols-supported-x@2.1.2: + resolution: {integrity: sha512-sHDiVh9DeTSgMxmgDDFiay4+WpFx81U0e9el6lxORfm/s3F07suUieI+rPKOfQ3sqVvkPMd4aCvuQtHLJQj2vg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-string-tag-x@2.1.2: + resolution: {integrity: sha512-854igRa+5oWpAy2Y+SwGbjyjgFNfl1gIJH9ShVeXJYuKHIt8NS17sFllysRtFOD1iemNoGbVbTnI1qFDyjjGQw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + to-string-x@2.1.1: + resolution: {integrity: sha512-4R9y5W1m3YxHM4MGtgudgtVsx7mTTtyI7qC5wiuoJt3fwJEiNBBInmwggGawJELSY7aDajIaVyWziq46bimupw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + trim-left-x@4.1.2: + resolution: {integrity: sha512-yJeikzHJkxBygGAhXIVxxFuRqO0jptEx91+U7bS2il6uCZ/CAOWySArfOt35ZwzTyXfnfiB+BhvxvE2TroVcxA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + trim-right-x@4.1.2: + resolution: {integrity: sha512-//Z+2PD4eS9lh2lZjalpBEII7Ef2DaDQ5s1OOx1JK1L90WWfrqdC9/vX8f467lmahNGkxoxmHWwNDN6XdK0oKg==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + trim-x@4.1.2: + resolution: {integrity: sha512-Cr4fnQ52a57JCX20SzyvRyLcMvKgKd9lcf7Jh/oa1w4FfH1kGT6F7/HjNiAJZyDW+xdLLH6KhrfRhvoIYZKROA==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-essentials@10.0.2: + resolution: {integrity: sha512-Xwag0TULqriaugXqVdDiGZ5wuZpqABZlpwQ2Ho4GDyiu/R2Xjkp/9+zcFxL7uzeLl/QCPrflnvpVYyS3ouT7Zw==} + peerDependencies: + typescript: '>=4.5.0' + peerDependenciesMeta: + typescript: + optional: true + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsconfck@3.1.4: + resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tsup@8.3.5: + resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + tsx@4.19.2: + resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} + engines: {node: '>=18.0.0'} + hasBin: true + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@4.26.1: + resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} + engines: {node: '>=16'} + + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + + typescript-eslint@8.17.0: + resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + uint8-varint@2.0.4: + resolution: {integrity: sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==} + + uint8arraylist@2.4.8: + resolution: {integrity: sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==} + + uint8arrays@4.0.10: + resolution: {integrity: sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==} + + uint8arrays@5.1.0: + resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + + unenv-nightly@2.0.0-20241204-140205-a5d5190: + resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util-get-getter-x@1.0.2: + resolution: {integrity: sha512-iZF1RJsNLV7zW37sH1nTudFUkwaTgigz5O19Ok1LeRBe8eZGYNrMJ/xvUDore3nt/z2mf7gBnUH1jyg00yJ/fQ==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + util-pusher-x@1.0.3: + resolution: {integrity: sha512-+hCPl/DrppZRn/RHYnUcNwckR4h5s06pUELCSGEMhdYSy7N6dIfvozR482w5j2+eKfXvDISL/QNlTnRPB2skDw==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + + vite-node@2.1.8: + resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite-tsconfig-paths@5.1.4: + resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@6.0.3: + resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@2.1.8: + resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.8 + '@vitest/ui': 2.1.8 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + wait-on@8.0.1: + resolution: {integrity: sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig==} + engines: {node: '>=12.0.0'} + hasBin: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + when-exit@2.1.3: + resolution: {integrity: sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + white-space-x@4.1.1: + resolution: {integrity: sha512-eVlQcQLfYCUhM+oSoyKzn1j+z//UHbe9Lqr6xUeR/YG4n9AobOtLVdHnj69MJK8LaW3fqSm4n+hAbfPi/1M5/Q==} + engines: {node: '>=8.11.4', npm: 6.10.1} + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + workerd@1.20240718.0: + resolution: {integrity: sha512-w7lOLRy0XecQTg/ujTLWBiJJuoQvzB3CdQ6/8Wgex3QxFhV9Pbnh3UbwIuUfMw3OCCPQc4o7y+1P+mISAgp6yg==} + engines: {node: '>=16'} + hasBin: true + + workerd@1.20241205.0: + resolution: {integrity: sha512-vso/2n0c5SdBDWiD+Sx5gM7unA6SiZXRVUHDqH1euoP/9mFVHZF8icoYsNLB87b/TX8zNgpae+I5N/xFpd9v0g==} + engines: {node: '>=16'} + hasBin: true + + wrangler@3.93.0: + resolution: {integrity: sha512-+wfxjOrtm6YgDS+NdJkB6aiBIS3ED97mNRQmfrEShRJW4pVo4sWY6oQ1FsGT+j4tGHplrTbWCE6U5yTgjNW/lw==} + engines: {node: '>=16.17.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20241205.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xxhash-wasm@1.0.2: + resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} + + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + yoga-wasm-web@0.3.3: + resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} + + youch@3.3.4: + resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zx@8.2.4: + resolution: {integrity: sha512-g9wVU+5+M+zVen/3IyAZfsZFmeqb6vDfjqFggakviz5uLK7OAejOirX+jeTOkyvAh/OYRlCgw+SdqzN7F61QVQ==} + engines: {node: '>= 12.17.0'} + hasBin: true + +snapshots: + + '@adviser/cement@0.2.41(typescript@5.7.2)': + dependencies: + ts-essentials: 10.0.2(typescript@5.7.2) + yaml: 2.5.1 + transitivePeerDependencies: + - typescript + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.696.0 + tslib: 2.7.0 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.696.0 + tslib: 2.7.0 + + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-locate-window': 3.568.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-locate-window': 3.568.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.696.0 + tslib: 2.7.0 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.7.0 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-sdk/client-s3@3.705.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/client-sts': 3.699.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/middleware-bucket-endpoint': 3.696.0 + '@aws-sdk/middleware-expect-continue': 3.696.0 + '@aws-sdk/middleware-flexible-checksums': 3.701.0 + '@aws-sdk/middleware-host-header': 3.696.0 + '@aws-sdk/middleware-location-constraint': 3.696.0 + '@aws-sdk/middleware-logger': 3.696.0 + '@aws-sdk/middleware-recursion-detection': 3.696.0 + '@aws-sdk/middleware-sdk-s3': 3.696.0 + '@aws-sdk/middleware-ssec': 3.696.0 + '@aws-sdk/middleware-user-agent': 3.696.0 + '@aws-sdk/region-config-resolver': 3.696.0 + '@aws-sdk/signature-v4-multi-region': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-endpoints': 3.696.0 + '@aws-sdk/util-user-agent-browser': 3.696.0 + '@aws-sdk/util-user-agent-node': 3.696.0 + '@aws-sdk/xml-builder': 3.696.0 + '@smithy/config-resolver': 3.0.12 + '@smithy/core': 2.5.3 + '@smithy/eventstream-serde-browser': 3.0.13 + '@smithy/eventstream-serde-config-resolver': 3.0.10 + '@smithy/eventstream-serde-node': 3.0.12 + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/hash-blob-browser': 3.1.9 + '@smithy/hash-node': 3.0.10 + '@smithy/hash-stream-node': 3.1.9 + '@smithy/invalid-dependency': 3.0.10 + '@smithy/md5-js': 3.0.10 + '@smithy/middleware-content-length': 3.0.12 + '@smithy/middleware-endpoint': 3.2.3 + '@smithy/middleware-retry': 3.0.27 + '@smithy/middleware-serde': 3.0.10 + '@smithy/middleware-stack': 3.0.10 + '@smithy/node-config-provider': 3.1.11 + '@smithy/node-http-handler': 3.3.1 + '@smithy/protocol-http': 4.1.7 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.27 + '@smithy/util-defaults-mode-node': 3.0.27 + '@smithy/util-endpoints': 2.1.6 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-retry': 3.0.10 + '@smithy/util-stream': 3.3.1 + '@smithy/util-utf8': 3.0.0 + '@smithy/util-waiter': 3.1.9 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sts': 3.699.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/middleware-host-header': 3.696.0 + '@aws-sdk/middleware-logger': 3.696.0 + '@aws-sdk/middleware-recursion-detection': 3.696.0 + '@aws-sdk/middleware-user-agent': 3.696.0 + '@aws-sdk/region-config-resolver': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-endpoints': 3.696.0 + '@aws-sdk/util-user-agent-browser': 3.696.0 + '@aws-sdk/util-user-agent-node': 3.696.0 + '@smithy/config-resolver': 3.0.12 + '@smithy/core': 2.5.3 + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/hash-node': 3.0.10 + '@smithy/invalid-dependency': 3.0.10 + '@smithy/middleware-content-length': 3.0.12 + '@smithy/middleware-endpoint': 3.2.3 + '@smithy/middleware-retry': 3.0.27 + '@smithy/middleware-serde': 3.0.10 + '@smithy/middleware-stack': 3.0.10 + '@smithy/node-config-provider': 3.1.11 + '@smithy/node-http-handler': 3.3.1 + '@smithy/protocol-http': 4.1.7 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.27 + '@smithy/util-defaults-mode-node': 3.0.27 + '@smithy/util-endpoints': 2.1.6 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-retry': 3.0.10 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.696.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/middleware-host-header': 3.696.0 + '@aws-sdk/middleware-logger': 3.696.0 + '@aws-sdk/middleware-recursion-detection': 3.696.0 + '@aws-sdk/middleware-user-agent': 3.696.0 + '@aws-sdk/region-config-resolver': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-endpoints': 3.696.0 + '@aws-sdk/util-user-agent-browser': 3.696.0 + '@aws-sdk/util-user-agent-node': 3.696.0 + '@smithy/config-resolver': 3.0.12 + '@smithy/core': 2.5.3 + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/hash-node': 3.0.10 + '@smithy/invalid-dependency': 3.0.10 + '@smithy/middleware-content-length': 3.0.12 + '@smithy/middleware-endpoint': 3.2.3 + '@smithy/middleware-retry': 3.0.27 + '@smithy/middleware-serde': 3.0.10 + '@smithy/middleware-stack': 3.0.10 + '@smithy/node-config-provider': 3.1.11 + '@smithy/node-http-handler': 3.3.1 + '@smithy/protocol-http': 4.1.7 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.27 + '@smithy/util-defaults-mode-node': 3.0.27 + '@smithy/util-endpoints': 2.1.6 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-retry': 3.0.10 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sts@3.699.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/core': 3.696.0 + '@aws-sdk/credential-provider-node': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/middleware-host-header': 3.696.0 + '@aws-sdk/middleware-logger': 3.696.0 + '@aws-sdk/middleware-recursion-detection': 3.696.0 + '@aws-sdk/middleware-user-agent': 3.696.0 + '@aws-sdk/region-config-resolver': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-endpoints': 3.696.0 + '@aws-sdk/util-user-agent-browser': 3.696.0 + '@aws-sdk/util-user-agent-node': 3.696.0 + '@smithy/config-resolver': 3.0.12 + '@smithy/core': 2.5.3 + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/hash-node': 3.0.10 + '@smithy/invalid-dependency': 3.0.10 + '@smithy/middleware-content-length': 3.0.12 + '@smithy/middleware-endpoint': 3.2.3 + '@smithy/middleware-retry': 3.0.27 + '@smithy/middleware-serde': 3.0.10 + '@smithy/middleware-stack': 3.0.10 + '@smithy/node-config-provider': 3.1.11 + '@smithy/node-http-handler': 3.3.1 + '@smithy/protocol-http': 4.1.7 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.27 + '@smithy/util-defaults-mode-node': 3.0.27 + '@smithy/util-endpoints': 2.1.6 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-retry': 3.0.10 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/core': 2.5.3 + '@smithy/node-config-provider': 3.1.11 + '@smithy/property-provider': 3.1.10 + '@smithy/protocol-http': 4.1.7 + '@smithy/signature-v4': 4.2.3 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/util-middleware': 3.0.10 + fast-xml-parser: 4.4.1 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-env@3.696.0': + dependencies: + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/property-provider': 3.1.10 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-http@3.696.0': + dependencies: + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/node-http-handler': 3.3.1 + '@smithy/property-provider': 3.1.10 + '@smithy/protocol-http': 4.1.7 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/util-stream': 3.3.1 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-ini@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0)': + dependencies: + '@aws-sdk/client-sts': 3.699.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/credential-provider-env': 3.696.0 + '@aws-sdk/credential-provider-http': 3.696.0 + '@aws-sdk/credential-provider-process': 3.696.0 + '@aws-sdk/credential-provider-sso': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) + '@aws-sdk/credential-provider-web-identity': 3.696.0(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/types': 3.696.0 + '@smithy/credential-provider-imds': 3.2.7 + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + + '@aws-sdk/credential-provider-node@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0)': + dependencies: + '@aws-sdk/credential-provider-env': 3.696.0 + '@aws-sdk/credential-provider-http': 3.696.0 + '@aws-sdk/credential-provider-ini': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/credential-provider-process': 3.696.0 + '@aws-sdk/credential-provider-sso': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) + '@aws-sdk/credential-provider-web-identity': 3.696.0(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/types': 3.696.0 + '@smithy/credential-provider-imds': 3.2.7 + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - '@aws-sdk/client-sts' + - aws-crt + + '@aws-sdk/credential-provider-process@3.696.0': + dependencies: + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-sso@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': + dependencies: + '@aws-sdk/client-sso': 3.696.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/token-providers': 3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0)) + '@aws-sdk/types': 3.696.0 + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.696.0(@aws-sdk/client-sts@3.699.0)': + dependencies: + '@aws-sdk/client-sts': 3.699.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/property-provider': 3.1.10 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-bucket-endpoint@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-arn-parser': 3.693.0 + '@smithy/node-config-provider': 3.1.11 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + '@smithy/util-config-provider': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-expect-continue@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-flexible-checksums@3.701.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/is-array-buffer': 3.0.0 + '@smithy/node-config-provider': 3.1.11 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-stream': 3.3.1 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-host-header@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-location-constraint@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-logger@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-recursion-detection@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-sdk-s3@3.696.0': + dependencies: + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-arn-parser': 3.693.0 + '@smithy/core': 2.5.3 + '@smithy/node-config-provider': 3.1.11 + '@smithy/protocol-http': 4.1.7 + '@smithy/signature-v4': 4.2.3 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-stream': 3.3.1 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-ssec@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/middleware-user-agent@3.696.0': + dependencies: + '@aws-sdk/core': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@aws-sdk/util-endpoints': 3.696.0 + '@smithy/core': 2.5.3 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/region-config-resolver@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/node-config-provider': 3.1.11 + '@smithy/types': 3.7.1 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.10 + tslib: 2.7.0 + + '@aws-sdk/signature-v4-multi-region@3.696.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/protocol-http': 4.1.7 + '@smithy/signature-v4': 4.2.3 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/token-providers@3.699.0(@aws-sdk/client-sso-oidc@3.699.0(@aws-sdk/client-sts@3.699.0))': + dependencies: + '@aws-sdk/client-sso-oidc': 3.699.0(@aws-sdk/client-sts@3.699.0) + '@aws-sdk/types': 3.696.0 + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/types@3.696.0': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/util-arn-parser@3.693.0': + dependencies: + tslib: 2.7.0 + + '@aws-sdk/util-endpoints@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/types': 3.7.1 + '@smithy/util-endpoints': 2.1.6 + tslib: 2.7.0 + + '@aws-sdk/util-locate-window@3.568.0': + dependencies: + tslib: 2.7.0 + + '@aws-sdk/util-user-agent-browser@3.696.0': + dependencies: + '@aws-sdk/types': 3.696.0 + '@smithy/types': 3.7.1 + bowser: 2.11.0 + tslib: 2.7.0 + + '@aws-sdk/util-user-agent-node@3.696.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.696.0 + '@aws-sdk/types': 3.696.0 + '@smithy/node-config-provider': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@aws-sdk/xml-builder@3.696.0': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@cloudflare/kv-asset-handler@0.3.4': + dependencies: + mime: 3.0.0 + + '@cloudflare/workerd-darwin-64@1.20240718.0': + optional: true + + '@cloudflare/workerd-darwin-64@1.20241205.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20240718.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20241205.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20240718.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20241205.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20240718.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20241205.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20240718.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20241205.0': + optional: true + + '@cloudflare/workers-shared@0.10.0': + dependencies: + mime: 3.0.0 + zod: 3.23.8 + + '@cloudflare/workers-types@4.20240718.0': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + + '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.23.1': + optional: true + + '@esbuild/aix-ppc64@0.24.0': + optional: true + + '@esbuild/android-arm64@0.17.19': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.23.1': + optional: true + + '@esbuild/android-arm64@0.24.0': + optional: true + + '@esbuild/android-arm@0.17.19': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.23.1': + optional: true + + '@esbuild/android-arm@0.24.0': + optional: true + + '@esbuild/android-x64@0.17.19': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.23.1': + optional: true + + '@esbuild/android-x64@0.24.0': + optional: true + + '@esbuild/darwin-arm64@0.17.19': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.23.1': + optional: true + + '@esbuild/darwin-arm64@0.24.0': + optional: true + + '@esbuild/darwin-x64@0.17.19': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.23.1': + optional: true + + '@esbuild/darwin-x64@0.24.0': + optional: true + + '@esbuild/freebsd-arm64@0.17.19': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.23.1': + optional: true + + '@esbuild/freebsd-arm64@0.24.0': + optional: true + + '@esbuild/freebsd-x64@0.17.19': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.23.1': + optional: true + + '@esbuild/freebsd-x64@0.24.0': + optional: true + + '@esbuild/linux-arm64@0.17.19': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.23.1': + optional: true + + '@esbuild/linux-arm64@0.24.0': + optional: true + + '@esbuild/linux-arm@0.17.19': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.23.1': + optional: true + + '@esbuild/linux-arm@0.24.0': + optional: true + + '@esbuild/linux-ia32@0.17.19': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.23.1': + optional: true + + '@esbuild/linux-ia32@0.24.0': + optional: true + + '@esbuild/linux-loong64@0.17.19': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.23.1': + optional: true + + '@esbuild/linux-loong64@0.24.0': + optional: true + + '@esbuild/linux-mips64el@0.17.19': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.23.1': + optional: true + + '@esbuild/linux-mips64el@0.24.0': + optional: true + + '@esbuild/linux-ppc64@0.17.19': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.23.1': + optional: true + + '@esbuild/linux-ppc64@0.24.0': + optional: true + + '@esbuild/linux-riscv64@0.17.19': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.23.1': + optional: true + + '@esbuild/linux-riscv64@0.24.0': + optional: true + + '@esbuild/linux-s390x@0.17.19': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.23.1': + optional: true + + '@esbuild/linux-s390x@0.24.0': + optional: true + + '@esbuild/linux-x64@0.17.19': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.23.1': + optional: true + + '@esbuild/linux-x64@0.24.0': + optional: true + + '@esbuild/netbsd-x64@0.17.19': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/netbsd-x64@0.24.0': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.24.0': + optional: true + + '@esbuild/openbsd-x64@0.17.19': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-x64@0.24.0': + optional: true + + '@esbuild/sunos-x64@0.17.19': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.23.1': + optional: true + + '@esbuild/sunos-x64@0.24.0': + optional: true + + '@esbuild/win32-arm64@0.17.19': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.23.1': + optional: true + + '@esbuild/win32-arm64@0.24.0': + optional: true + + '@esbuild/win32-ia32@0.17.19': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.23.1': + optional: true + + '@esbuild/win32-ia32@0.24.0': + optional: true + + '@esbuild/win32-x64@0.17.19': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.23.1': + optional: true + + '@esbuild/win32-x64@0.24.0': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@9.16.0)': + dependencies: + eslint: 9.16.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.19.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/core@0.9.0': {} + + '@eslint/eslintrc@3.2.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.16.0': {} + + '@eslint/object-schema@2.1.4': {} + + '@eslint/plugin-kit@0.2.3': + dependencies: + levn: 0.4.1 + + '@fastify/busboy@2.1.1': {} + + '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.7.2)': + dependencies: + '@adviser/cement': 0.2.41(typescript@5.7.2) + '@fireproof/vendor': 1.0.0 + '@ipld/unixfs': 3.0.0 + charwise: 3.0.1 + idb: 8.0.0 + memfs: 4.14.1 + multiformats: 13.3.1 + p-limit: 6.1.0 + p-map: 7.0.2 + p-retry: 6.2.1 + prolly-trees: 1.0.4 + react: 18.3.1 + transitivePeerDependencies: + - typescript + + '@fireproof/vendor@1.0.0': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + varint: 6.0.0 + + '@hapi/hoek@9.3.0': {} + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.1': {} + + '@ipld/car@5.3.2': + dependencies: + '@ipld/dag-cbor': 9.2.2 + cborg: 4.2.7 + multiformats: 13.3.1 + varint: 6.0.0 + + '@ipld/car@5.3.3': + dependencies: + '@ipld/dag-cbor': 9.2.2 + cborg: 4.2.7 + multiformats: 13.3.1 + varint: 6.0.0 + + '@ipld/dag-cbor@9.2.2': + dependencies: + cborg: 4.2.7 + multiformats: 13.3.1 + + '@ipld/dag-json@10.2.2': + dependencies: + cborg: 4.2.7 + multiformats: 13.3.1 + + '@ipld/dag-pb@4.1.2': + dependencies: + multiformats: 13.3.1 + + '@ipld/dag-ucan@3.4.0': + dependencies: + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-json': 10.2.2 + multiformats: 11.0.2 + + '@ipld/unixfs@2.2.0': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + '@perma/map': 1.0.3 + actor: 2.3.1 + multiformats: 11.0.2 + protobufjs: 7.4.0 + rabin-rs: 2.1.0 + + '@ipld/unixfs@3.0.0': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + '@perma/map': 1.0.3 + actor: 2.3.1 + multiformats: 13.3.1 + protobufjs: 7.4.0 + rabin-rs: 2.1.0 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jsonjoy.com/base64@1.1.2(tslib@2.7.0)': + dependencies: + tslib: 2.7.0 + + '@jsonjoy.com/json-pack@1.1.0(tslib@2.7.0)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.7.0) + '@jsonjoy.com/util': 1.5.0(tslib@2.7.0) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.7.0) + tslib: 2.7.0 + + '@jsonjoy.com/util@1.5.0(tslib@2.7.0)': + dependencies: + tslib: 2.7.0 + + '@jspm/core@2.1.0': {} + + '@multiformats/murmur3@2.1.8': + dependencies: + multiformats: 13.3.1 + murmurhash3js-revisited: 3.0.0 + + '@netlify/blobs@8.1.0': {} + + '@noble/curves@1.6.0': + dependencies: + '@noble/hashes': 1.5.0 + + '@noble/ed25519@1.7.3': {} + + '@noble/hashes@1.5.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@perma/map@1.0.3': + dependencies: + '@multiformats/murmur3': 2.1.8 + murmurhash3js-revisited: 3.0.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@rollup/rollup-android-arm-eabi@4.24.0': + optional: true + + '@rollup/rollup-android-arm64@4.24.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.24.0': + optional: true + + '@rollup/rollup-darwin-x64@4.24.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.24.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.24.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.24.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.24.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.24.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.24.0': + optional: true + + '@scure/base@1.1.9': {} + + '@scure/bip39@1.4.0': + dependencies: + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.9 + + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + + '@sideway/formula@3.0.1': {} + + '@sideway/pinpoint@2.0.0': {} + + '@smithy/abort-controller@3.1.8': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/chunked-blob-reader-native@3.0.1': + dependencies: + '@smithy/util-base64': 3.0.0 + tslib: 2.7.0 + + '@smithy/chunked-blob-reader@4.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/config-resolver@3.0.12': + dependencies: + '@smithy/node-config-provider': 3.1.11 + '@smithy/types': 3.7.1 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.10 + tslib: 2.7.0 + + '@smithy/core@2.5.3': + dependencies: + '@smithy/middleware-serde': 3.0.10 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-stream': 3.3.1 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/credential-provider-imds@3.2.7': + dependencies: + '@smithy/node-config-provider': 3.1.11 + '@smithy/property-provider': 3.1.10 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + tslib: 2.7.0 + + '@smithy/eventstream-codec@3.1.9': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 3.7.1 + '@smithy/util-hex-encoding': 3.0.0 + tslib: 2.7.0 + + '@smithy/eventstream-serde-browser@3.0.13': + dependencies: + '@smithy/eventstream-serde-universal': 3.0.12 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/eventstream-serde-config-resolver@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/eventstream-serde-node@3.0.12': + dependencies: + '@smithy/eventstream-serde-universal': 3.0.12 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/eventstream-serde-universal@3.0.12': + dependencies: + '@smithy/eventstream-codec': 3.1.9 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/fetch-http-handler@4.1.1': + dependencies: + '@smithy/protocol-http': 4.1.7 + '@smithy/querystring-builder': 3.0.10 + '@smithy/types': 3.7.1 + '@smithy/util-base64': 3.0.0 + tslib: 2.7.0 + + '@smithy/hash-blob-browser@3.1.9': + dependencies: + '@smithy/chunked-blob-reader': 4.0.0 + '@smithy/chunked-blob-reader-native': 3.0.1 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/hash-node@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/hash-stream-node@3.1.9': + dependencies: + '@smithy/types': 3.7.1 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/invalid-dependency@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.7.0 + + '@smithy/is-array-buffer@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/md5-js@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/middleware-content-length@3.0.12': + dependencies: + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/middleware-endpoint@3.2.3': + dependencies: + '@smithy/core': 2.5.3 + '@smithy/middleware-serde': 3.0.10 + '@smithy/node-config-provider': 3.1.11 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + '@smithy/url-parser': 3.0.10 + '@smithy/util-middleware': 3.0.10 + tslib: 2.7.0 + + '@smithy/middleware-retry@3.0.27': + dependencies: + '@smithy/node-config-provider': 3.1.11 + '@smithy/protocol-http': 4.1.7 + '@smithy/service-error-classification': 3.0.10 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-retry': 3.0.10 + tslib: 2.7.0 + uuid: 9.0.1 + + '@smithy/middleware-serde@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/middleware-stack@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/node-config-provider@3.1.11': + dependencies: + '@smithy/property-provider': 3.1.10 + '@smithy/shared-ini-file-loader': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/node-http-handler@3.3.1': + dependencies: + '@smithy/abort-controller': 3.1.8 + '@smithy/protocol-http': 4.1.7 + '@smithy/querystring-builder': 3.0.10 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/property-provider@3.1.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/protocol-http@4.1.7': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/querystring-builder@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + '@smithy/util-uri-escape': 3.0.0 + tslib: 2.7.0 + + '@smithy/querystring-parser@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/service-error-classification@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + + '@smithy/shared-ini-file-loader@3.1.11': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/signature-v4@4.2.3': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-middleware': 3.0.10 + '@smithy/util-uri-escape': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/smithy-client@3.4.4': + dependencies: + '@smithy/core': 2.5.3 + '@smithy/middleware-endpoint': 3.2.3 + '@smithy/middleware-stack': 3.0.10 + '@smithy/protocol-http': 4.1.7 + '@smithy/types': 3.7.1 + '@smithy/util-stream': 3.3.1 + tslib: 2.7.0 + + '@smithy/types@3.7.1': + dependencies: + tslib: 2.7.0 + + '@smithy/url-parser@3.0.10': + dependencies: + '@smithy/querystring-parser': 3.0.10 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/util-base64@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-body-length-browser@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-body-length-node@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.7.0 + + '@smithy/util-buffer-from@3.0.0': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-config-provider@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-defaults-mode-browser@3.0.27': + dependencies: + '@smithy/property-provider': 3.1.10 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + bowser: 2.11.0 + tslib: 2.7.0 + + '@smithy/util-defaults-mode-node@3.0.27': + dependencies: + '@smithy/config-resolver': 3.0.12 + '@smithy/credential-provider-imds': 3.2.7 + '@smithy/node-config-provider': 3.1.11 + '@smithy/property-provider': 3.1.10 + '@smithy/smithy-client': 3.4.4 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/util-endpoints@2.1.6': + dependencies: + '@smithy/node-config-provider': 3.1.11 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/util-hex-encoding@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-middleware@3.0.10': + dependencies: + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/util-retry@3.0.10': + dependencies: + '@smithy/service-error-classification': 3.0.10 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@smithy/util-stream@3.3.1': + dependencies: + '@smithy/fetch-http-handler': 4.1.1 + '@smithy/node-http-handler': 3.3.1 + '@smithy/types': 3.7.1 + '@smithy/util-base64': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-uri-escape@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.7.0 + + '@smithy/util-utf8@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-waiter@3.1.9': + dependencies: + '@smithy/abort-controller': 3.1.8 + '@smithy/types': 3.7.1 + tslib: 2.7.0 + + '@storacha/one-webcrypto@1.0.1': {} + + '@types/better-sqlite3@7.6.12': + dependencies: + '@types/node': 22.10.1 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + + '@types/eslint__js@8.42.3': + dependencies: + '@types/eslint': 9.6.1 + + '@types/estree@1.0.6': {} + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 22.10.1 + optional: true + + '@types/json-schema@7.0.15': {} + + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 22.10.1 + optional: true + + '@types/minimatch@3.0.5': {} + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.10.1 + + '@types/node@22.10.1': + dependencies: + undici-types: 6.20.0 + + '@types/retry@0.12.1': {} + + '@types/retry@0.12.2': {} + + '@types/wait-on@5.3.4': + dependencies: + '@types/node': 22.10.1 + + '@types/ws@8.5.13': + dependencies: + '@types/node': 22.10.1 + + '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.17.0 + eslint: 9.16.0 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.17.0 + debug: 4.3.7 + eslint: 9.16.0 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.17.0': + dependencies: + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 + + '@typescript-eslint/type-utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + dependencies: + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + debug: 4.3.7 + eslint: 9.16.0 + ts-api-utils: 1.3.0(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.17.0': {} + + '@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/visitor-keys': 8.17.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.7.2) + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.17.0(eslint@9.16.0)(typescript@5.7.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + '@typescript-eslint/scope-manager': 8.17.0 + '@typescript-eslint/types': 8.17.0 + '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) + eslint: 9.16.0 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.17.0': + dependencies: + '@typescript-eslint/types': 8.17.0 + eslint-visitor-keys: 4.2.0 + + '@ucanto/client@9.0.1': + dependencies: + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + + '@ucanto/core@10.0.1': + dependencies: + '@ipld/car': 5.3.2 + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-ucan': 3.4.0 + '@ucanto/interface': 10.0.1 + multiformats: 11.0.2 + + '@ucanto/interface@10.0.1': + dependencies: + '@ipld/dag-ucan': 3.4.0 + multiformats: 11.0.2 + + '@ucanto/principal@9.0.1': + dependencies: + '@ipld/dag-ucan': 3.4.0 + '@noble/curves': 1.6.0 + '@noble/ed25519': 1.7.3 + '@noble/hashes': 1.5.0 + '@ucanto/interface': 10.0.1 + multiformats: 11.0.2 + one-webcrypto: 1.0.3 + + '@ucanto/server@10.0.0': + dependencies: + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/validator': 9.0.2 + + '@ucanto/transport@9.1.1': + dependencies: + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + + '@ucanto/validator@9.0.2': + dependencies: + '@ipld/car': 5.3.2 + '@ipld/dag-cbor': 9.2.2 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + multiformats: 11.0.2 + + '@vitest/expect@2.1.8': + dependencies: + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.1))': + dependencies: + '@vitest/spy': 2.1.8 + estree-walker: 3.0.3 + magic-string: 0.30.12 + optionalDependencies: + vite: 5.4.11(@types/node@22.10.1) + + '@vitest/pretty-format@2.1.8': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.8': + dependencies: + '@vitest/utils': 2.1.8 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.8': + dependencies: + '@vitest/pretty-format': 2.1.8 + magic-string: 0.30.12 + pathe: 1.1.2 + + '@vitest/spy@2.1.8': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.1.8': + dependencies: + '@vitest/pretty-format': 2.1.8 + loupe: 3.1.2 + tinyrainbow: 1.2.0 + + '@web3-storage/access@20.1.0': + dependencies: + '@ipld/car': 5.3.2 + '@ipld/dag-ucan': 3.4.0 + '@scure/bip39': 1.4.0 + '@storacha/one-webcrypto': 1.0.1 + '@ucanto/client': 9.0.1 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/transport': 9.1.1 + '@ucanto/validator': 9.0.2 + '@web3-storage/capabilities': 17.4.1 + '@web3-storage/did-mailto': 2.1.0 + bigint-mod-arith: 3.3.1 + conf: 11.0.2 + multiformats: 12.1.3 + p-defer: 4.0.1 + type-fest: 4.26.1 + uint8arrays: 4.0.10 + + '@web3-storage/blob-index@1.0.4': + dependencies: + '@ipld/dag-cbor': 9.2.2 + '@storacha/one-webcrypto': 1.0.1 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@web3-storage/capabilities': 17.4.1 + carstream: 2.2.0 + multiformats: 13.3.1 + uint8arrays: 5.1.0 + + '@web3-storage/capabilities@17.4.1': + dependencies: + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/transport': 9.1.1 + '@ucanto/validator': 9.0.2 + '@web3-storage/data-segment': 5.2.0 + uint8arrays: 5.1.0 + + '@web3-storage/clock@0.4.1': + dependencies: + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-ucan': 3.4.0 + '@ucanto/client': 9.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/server': 10.0.0 + '@ucanto/transport': 9.1.1 + '@ucanto/validator': 9.0.2 + '@web3-storage/pail': 0.5.0 + hashlru: 2.3.0 + multiformats: 13.3.1 + p-retry: 6.2.0 + + '@web3-storage/data-segment@5.2.0': + dependencies: + '@ipld/dag-cbor': 9.2.2 + multiformats: 13.3.1 + sync-multihash-sha2: 1.0.0 + + '@web3-storage/did-mailto@2.1.0': {} + + '@web3-storage/filecoin-client@3.3.4': + dependencies: + '@ipld/dag-ucan': 3.4.0 + '@ucanto/client': 9.0.1 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/transport': 9.1.1 + '@web3-storage/capabilities': 17.4.1 + + '@web3-storage/pail@0.5.0': + dependencies: + '@ipld/car': 5.3.3 + '@ipld/dag-cbor': 9.2.2 + archy: 1.0.0 + cborg: 4.2.7 + cli-color: 2.0.4 + multiformats: 12.1.3 + sade: 1.8.1 + + '@web3-storage/pail@0.6.0': + dependencies: + '@ipld/dag-cbor': 9.2.2 + multiformats: 13.3.1 + + '@web3-storage/upload-client@17.1.1(encoding@0.1.13)': + dependencies: + '@ipld/car': 5.3.3 + '@ipld/dag-cbor': 9.2.2 + '@ipld/dag-ucan': 3.4.0 + '@ipld/unixfs': 2.2.0 + '@ucanto/client': 9.0.1 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/transport': 9.1.1 + '@web3-storage/blob-index': 1.0.4 + '@web3-storage/capabilities': 17.4.1 + '@web3-storage/data-segment': 5.2.0 + '@web3-storage/filecoin-client': 3.3.4 + ipfs-utils: 9.0.14(encoding@0.1.13) + multiformats: 12.1.3 + p-retry: 5.1.2 + varint: 6.0.0 + transitivePeerDependencies: + - encoding + + '@web3-storage/w3up-client@16.5.2(encoding@0.1.13)': + dependencies: + '@ipld/dag-ucan': 3.4.0 + '@ucanto/client': 9.0.1 + '@ucanto/core': 10.0.1 + '@ucanto/interface': 10.0.1 + '@ucanto/principal': 9.0.1 + '@ucanto/transport': 9.1.1 + '@web3-storage/access': 20.1.0 + '@web3-storage/blob-index': 1.0.4 + '@web3-storage/capabilities': 17.4.1 + '@web3-storage/did-mailto': 2.1.0 + '@web3-storage/filecoin-client': 3.3.4 + '@web3-storage/upload-client': 17.1.1(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.0 + + acorn@8.12.1: {} + + acorn@8.14.0: {} + + actor@2.3.1: {} + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + any-signal@3.0.1: {} + + archy@1.0.0: {} + + argparse@2.0.1: {} + + array-all-x@1.1.2: + dependencies: + array-any-x: 1.1.2 + simple-call-x: 1.0.3 + + array-any-x@1.1.2: + dependencies: + assert-is-function-x: 3.1.2 + simple-call-x: 1.0.3 + split-if-boxed-bug-x: 2.1.2 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + array-filter-x@3.1.2: + dependencies: + array-all-x: 1.1.2 + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + require-object-coercible-x: 2.1.1 + simple-call-x: 1.0.3 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + + array-for-each-x@3.1.2: + dependencies: + array-all-x: 1.1.2 + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + require-object-coercible-x: 2.1.1 + simple-call-x: 1.0.3 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + + array-like-slice-x@2.2.2: + dependencies: + split-if-boxed-bug-x: 2.1.2 + to-integer-x: 4.2.2 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + array-reduce-right-x@3.1.2: + dependencies: + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + require-object-coercible-x: 2.1.1 + simple-methodize-x: 1.0.4 + split-if-boxed-bug-x: 2.1.2 + to-boolean-x: 2.1.1 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + array-slice-x@4.2.2: + dependencies: + array-like-slice-x: 2.2.2 + attempt-x: 2.1.2 + cached-constructors-x: 2.2.1 + is-arguments: 1.1.1 + is-array-x: 2.1.2 + is-string: 1.0.7 + simple-methodize-x: 1.0.4 + to-object-x: 2.2.1 + + array-some-x@3.1.2: + dependencies: + array-any-x: 1.1.2 + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + require-object-coercible-x: 2.1.1 + simple-call-x: 1.0.3 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + + arraybuffer-equal@1.0.4: {} + + as-table@1.0.55: + dependencies: + printable-characters: 1.0.42 + + assert-is-function-x@3.1.2: + dependencies: + is-function-x: 4.1.2 + is-primitive-x: 1.0.1 + to-string-symbols-supported-x: 2.1.2 + + assert-is-object-x@3.1.2: + dependencies: + is-primitive-x: 1.0.1 + to-string-symbols-supported-x: 2.1.2 + + assert@2.1.0: + dependencies: + call-bind: 1.0.7 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.5 + util: 0.12.5 + + assertion-error@2.0.1: {} + + asynckit@0.4.0: {} + + atomically@2.0.3: + dependencies: + stubborn-fs: 1.2.5 + when-exit: 2.1.3 + + attempt-x@2.1.2: + dependencies: + simple-call-x: 1.0.3 + util-pusher-x: 1.0.3 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + axios@1.7.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.1 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + better-sqlite3@11.7.0: + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.2 + + big-counter-x@4.1.2: + dependencies: + array-reduce-right-x: 3.1.2 + array-slice-x: 4.2.2 + object-define-properties-x: 5.1.2 + to-boolean-x: 2.1.1 + + big-integer@1.6.52: {} + + bigint-mod-arith@3.3.1: {} + + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + blake3-wasm@2.1.5: {} + + bowser@2.11.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-readablestream-to-it@1.0.3: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-require@5.0.0(esbuild@0.24.0): + dependencies: + esbuild: 0.24.0 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + + cached-constructors-x@2.2.1: + dependencies: + noop-x: 1.2.1 + + calculate-from-index-x@3.1.2: + dependencies: + is-array-like-x: 2.1.2 + to-integer-x: 4.2.2 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + capnp-ts@0.7.0: + dependencies: + debug: 4.3.7 + tslib: 2.7.0 + transitivePeerDependencies: + - supports-color + + carstream@2.2.0: + dependencies: + '@ipld/dag-cbor': 9.2.2 + multiformats: 13.3.1 + uint8arraylist: 2.4.8 + + cborg@4.2.7: {} + + chai@5.1.2: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.2 + pathval: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + charwise@3.0.1: {} + + check-error@2.1.1: {} + + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + + chownr@1.1.4: {} + + cli-color@2.0.4: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + memoizee: 0.4.17 + timers-ext: 0.1.8 + + clipboardy@4.0.0: + dependencies: + execa: 8.0.1 + is-wsl: 3.1.0 + is64bit: 2.0.0 + + collections-x@3.1.2: + dependencies: + array-for-each-x: 3.1.2 + array-some-x: 3.1.2 + assert-is-function-x: 3.1.2 + assert-is-object-x: 3.1.2 + attempt-x: 2.1.2 + big-counter-x: 4.1.2 + get-prototype-of-x: 2.1.2 + has-own-property-x: 4.1.2 + index-of-x: 3.1.2 + is-array-like-x: 2.1.2 + is-array-x: 2.1.2 + is-boolean-object: 1.1.2 + is-function-x: 4.1.2 + is-map-x: 2.1.2 + is-object-like-x: 2.1.2 + is-primitive-x: 1.0.1 + is-set-x: 2.1.2 + is-string: 1.0.7 + is-surrogate-pair-x: 3.1.2 + object-create-x: 3.1.2 + object-define-properties-x: 5.1.2 + object-define-property-x: 5.1.2 + rename-function-x: 1.1.2 + simple-call-x: 1.0.3 + simple-methodize-x: 1.0.4 + symbol-iterator-x: 1.1.2 + symbol-species-x: 1.1.2 + to-boolean-x: 2.1.1 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@4.1.1: {} + + concat-map@0.0.1: {} + + conf@11.0.2: + dependencies: + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + atomically: 2.0.3 + debounce-fn: 5.1.2 + dot-prop: 7.2.0 + env-paths: 3.0.0 + json-schema-typed: 8.0.1 + semver: 7.6.3 + + consola@3.2.3: {} + + cookie@0.7.2: {} + + cross-fetch@4.0.0(encoding@0.1.13): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + data-uri-to-buffer@2.0.2: {} + + date-fns@4.1.0: {} + + debounce-fn@5.1.2: + dependencies: + mimic-fn: 4.0.0 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-eql@5.0.2: {} + + deep-extend@0.6.0: {} + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + detect-libc@2.0.3: {} + + dot-prop@7.2.0: + dependencies: + type-fest: 2.19.0 + + eastasianwidth@0.2.0: {} + + electron-fetch@1.9.1: + dependencies: + encoding: 0.1.13 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + env-paths@3.0.0: {} + + err-code@3.0.1: {} + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-module-lexer@1.5.4: {} + + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + es6-weak-map@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + + esbuild-plugin-replace@1.4.0: + dependencies: + magic-string: 0.25.9 + + esbuild-plugin-resolve@2.0.0: {} + + esbuild@0.17.19: + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.2.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.16.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.16.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.0 + '@eslint/core': 0.9.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.16.0 + '@eslint/plugin-kit': 0.2.3 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.3.7 + escape-string-regexp: 4.0.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@0.6.1: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + esutils@2.0.3: {} + + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + event-target-shim@6.0.2: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + exit-hook@2.2.1: {} + + expand-template@2.0.3: {} + + expect-type@1.1.0: {} + + ext@1.7.0: + dependencies: + type: 2.7.3 + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.2: {} + + fast-xml-parser@4.4.1: + dependencies: + strnum: 1.0.5 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fdir@6.4.0(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-uri-to-path@1.0.0: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-index-x@3.1.2: + dependencies: + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + split-if-boxed-bug-x: 2.1.2 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + follow-redirects@1.15.9: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + fs-constants@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-iterator@1.0.2: {} + + get-own-enumerable-keys-x@2.1.2: + dependencies: + get-own-enumerable-property-symbols-x: 2.1.2 + object-keys-x: 3.1.2 + simple-methodize-x: 1.0.4 + to-object-x: 2.2.1 + + get-own-enumerable-property-symbols-x@2.1.2: + dependencies: + array-filter-x: 3.1.2 + get-own-property-symbols-x: 2.1.2 + property-is-enumerable-x: 2.1.2 + to-object-x: 2.2.1 + + get-own-property-names-x@3.1.2: + dependencies: + array-slice-x: 4.2.2 + attempt-x: 2.1.2 + is-array-x: 2.1.2 + object-keys-x: 3.1.2 + to-object-x: 2.2.1 + to-string-tag-x: 2.1.2 + + get-own-property-symbols-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + has-symbol-support-x: 2.1.2 + to-object-x: 2.2.1 + + get-prototype-of-x@2.1.2: + dependencies: + is-function-x: 4.1.2 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + + get-source@2.0.12: + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + + get-stream@8.0.1: {} + + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + github-from-package@0.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globals@14.0.0: {} + + globrex@0.1.2: {} + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graphemer@1.4.0: {} + + hamt-sharding@3.0.6: + dependencies: + sparse-array: 1.3.2 + uint8arrays: 5.1.0 + + has-bigints@1.0.2: {} + + has-boxed-string-x@2.1.1: {} + + has-flag@4.0.0: {} + + has-own-property-x@4.1.2: + dependencies: + simple-methodize-x: 1.0.4 + to-object-x: 2.2.1 + to-property-key-x: 3.1.2 + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbol-support-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + is-symbol: 1.0.4 + + has-symbols@1.0.3: {} + + has-to-string-tag-x@2.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + is-symbol: 1.0.4 + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + + has-working-bind-x@1.0.1: + dependencies: + noop-x: 1.2.1 + + hashlru@2.3.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + human-signals@5.0.0: {} + + hyperdyperid@1.2.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + idb-keyval@6.2.1: {} + + idb@8.0.0: {} + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + index-of-x@3.1.2: + dependencies: + attempt-x: 2.1.2 + calculate-from-index-x: 3.1.2 + find-index-x: 3.1.2 + is-nan-x: 2.1.1 + is-string: 1.0.7 + same-value-x: 2.1.1 + same-value-zero-x: 2.1.1 + simple-methodize-x: 1.0.4 + split-if-boxed-bug-x: 2.1.2 + to-boolean-x: 2.1.1 + to-integer-x: 4.2.2 + to-length-x: 4.2.2 + to-object-x: 2.2.1 + + infinity-x@2.2.1: {} + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + interface-blockstore@5.3.1: + dependencies: + interface-store: 6.0.2 + multiformats: 13.3.1 + + interface-store@6.0.2: {} + + ipfs-unixfs@11.2.0: + dependencies: + protons-runtime: 5.5.0 + uint8arraylist: 2.4.8 + + ipfs-utils@9.0.14(encoding@0.1.13): + dependencies: + any-signal: 3.0.1 + browser-readablestream-to-it: 1.0.3 + buffer: 6.0.3 + electron-fetch: 1.9.1 + err-code: 3.0.1 + is-electron: 2.2.2 + iso-url: 1.2.1 + it-all: 1.0.6 + it-glob: 1.0.2 + it-to-stream: 1.0.0 + merge-options: 3.0.4 + nanoid: 3.3.7 + native-fetch: 3.0.0(node-fetch@2.7.0(encoding@0.1.13)) + node-fetch: 2.7.0(encoding@0.1.13) + react-native-fetch-api: 3.0.0 + stream-to-it: 0.2.4 + transitivePeerDependencies: + - encoding + + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-array-buffer-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + has-to-string-tag-x: 2.1.2 + is-object-like-x: 2.1.2 + simple-call-x: 1.0.3 + to-boolean-x: 2.1.1 + to-string-tag-x: 2.1.2 + util-get-getter-x: 1.0.2 + + is-array-like-x@2.1.2: + dependencies: + is-function-x: 4.1.2 + is-length-x: 3.2.2 + is-nil-x: 2.1.1 + + is-array-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + to-string-tag-x: 2.1.2 + + is-bigint@1.0.4: + dependencies: + has-bigints: 1.0.2 + + is-boolean-object@1.1.2: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-boxed-primitive@1.0.1: + dependencies: + which-boxed-primitive: 1.0.2 + + is-buffer@2.0.5: {} + + is-callable@1.2.7: {} + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-data-view-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + has-to-string-tag-x: 2.1.2 + is-array-buffer-x: 2.1.2 + is-object-like-x: 2.1.2 + simple-call-x: 1.0.3 + to-string-tag-x: 2.1.2 + util-get-getter-x: 1.0.2 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-deep-strict-equal-x@1.1.2: + dependencies: + array-filter-x: 3.1.2 + arraybuffer-equal: 1.0.4 + attempt-x: 2.1.2 + collections-x: 3.1.2 + get-own-property-names-x: 3.1.2 + get-own-property-symbols-x: 2.1.2 + get-prototype-of-x: 2.1.2 + has-own-property-x: 4.1.2 + has-symbol-support-x: 2.1.2 + is-array-buffer-x: 2.1.2 + is-array-x: 2.1.2 + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-boxed-primitive: 1.0.1 + is-buffer: 2.0.5 + is-data-view-x: 2.1.2 + is-date-object: 1.0.5 + is-error-x: 2.1.2 + is-index-x: 2.1.2 + is-map-x: 2.1.2 + is-nan-x: 2.1.1 + is-number-object: 1.0.7 + is-regexp-x: 3.1.2 + is-set-x: 2.1.2 + is-string: 1.0.7 + is-symbol: 1.0.4 + object-keys-x: 3.1.2 + property-is-enumerable-x: 2.1.2 + same-value-x: 2.1.1 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-string-symbols-supported-x: 2.1.2 + to-string-tag-x: 2.1.2 + which-typed-array: 1.1.15 + + is-docker@3.0.0: {} + + is-electron@2.2.2: {} + + is-error-x@2.1.2: + dependencies: + get-prototype-of-x: 2.1.2 + is-object-like-x: 2.1.2 + to-string-tag-x: 2.1.2 + + is-extglob@2.1.1: {} + + is-finite-x@4.2.1: + dependencies: + infinity-x: 2.2.1 + is-nan-x: 2.1.1 + + is-fullwidth-code-point@3.0.0: {} + + is-function-x@4.1.2: + dependencies: + attempt-x: 2.1.2 + has-to-string-tag-x: 2.1.2 + is-primitive-x: 1.0.1 + normalize-space-x: 4.1.2 + replace-comments-x: 3.1.2 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-string-tag-x: 2.1.2 + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-index-x@2.1.2: + dependencies: + math-clamp-x: 3.2.2 + to-integer-x: 4.2.2 + to-number-x: 3.2.2 + to-string-symbols-supported-x: 2.1.2 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-integer-x@2.2.2: + dependencies: + is-finite-x: 4.2.1 + to-integer-x: 4.2.2 + + is-length-x@3.2.2: + dependencies: + is-safe-integer-x: 2.2.2 + + is-map-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + is-length-x: 3.2.2 + is-object-like-x: 2.1.2 + simple-call-x: 1.0.3 + util-get-getter-x: 1.0.2 + + is-nan-x@2.1.1: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + is-network-error@1.1.0: {} + + is-nil-x@2.1.1: {} + + is-number-object@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-object-like-x@2.1.2: + dependencies: + is-function-x: 4.1.2 + is-primitive-x: 1.0.1 + + is-plain-obj@2.1.0: {} + + is-primitive-x@1.0.1: {} + + is-promise@2.2.2: {} + + is-regexp-x@3.1.2: + dependencies: + has-own-property-x: 4.1.2 + has-to-string-tag-x: 2.1.2 + is-object-like-x: 2.1.2 + object-define-property-x: 5.1.2 + object-get-own-property-descriptor-x: 4.1.2 + simple-methodize-x: 1.0.4 + to-string-tag-x: 2.1.2 + + is-safe-integer-x@2.2.2: + dependencies: + is-integer-x: 2.2.2 + + is-set-x@2.1.2: + dependencies: + attempt-x: 2.1.2 + is-length-x: 3.2.2 + is-object-like-x: 2.1.2 + simple-call-x: 1.0.3 + util-get-getter-x: 1.0.2 + + is-stream@3.0.0: {} + + is-string@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-surrogate-pair-x@3.1.2: + dependencies: + is-string: 1.0.7 + simple-methodize-x: 1.0.4 + + is-symbol@1.0.4: + dependencies: + has-symbols: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.15 + + is-var-name@2.0.0: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + is64bit@2.0.0: + dependencies: + system-architecture: 0.1.0 + + isexe@2.0.0: {} + + iso-url@1.2.1: {} + + it-all@1.0.6: {} + + it-filter@3.1.1: + dependencies: + it-peekable: 3.0.5 + + it-glob@1.0.2: + dependencies: + '@types/minimatch': 3.0.5 + minimatch: 3.1.2 + + it-last@3.0.6: {} + + it-map@3.1.1: + dependencies: + it-peekable: 3.0.5 + + it-merge@3.0.5: + dependencies: + it-pushable: 3.2.3 + + it-parallel@3.0.8: + dependencies: + p-defer: 4.0.1 + + it-peekable@3.0.5: {} + + it-pipe@3.0.1: + dependencies: + it-merge: 3.0.5 + it-pushable: 3.2.3 + it-stream-types: 2.0.2 + + it-pushable@3.2.3: + dependencies: + p-defer: 4.0.1 + + it-stream-types@2.0.2: {} + + it-to-stream@1.0.0: + dependencies: + buffer: 6.0.3 + fast-fifo: 1.3.2 + get-iterator: 1.0.2 + p-defer: 3.0.0 + p-fifo: 1.0.0 + readable-stream: 3.6.2 + + itty-time@1.0.6: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + + joycon@3.1.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + load-tsconfig@0.2.5: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash.sortby@4.7.0: {} + + lodash@4.17.21: {} + + long@5.2.3: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.1.2: {} + + lru-cache@10.4.3: {} + + lru-queue@0.1.0: + dependencies: + es5-ext: 0.10.64 + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.30.12: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + math-clamp-x@3.2.2: + dependencies: + to-number-x: 3.2.2 + + math-sign-x@4.2.2: + dependencies: + is-nan-x: 2.1.1 + to-number-x: 3.2.2 + + memfs@4.14.1: + dependencies: + '@jsonjoy.com/json-pack': 1.1.0(tslib@2.7.0) + '@jsonjoy.com/util': 1.5.0(tslib@2.7.0) + tree-dump: 1.0.2(tslib@2.7.0) + tslib: 2.7.0 + + memoizee@0.4.17: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.8 + + merge-options@3.0.4: + dependencies: + is-plain-obj: 2.1.0 + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@3.0.0: {} + + mimic-fn@4.0.0: {} + + mimic-response@3.1.0: {} + + miniflare@3.20240718.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.12.1 + acorn-walk: 8.3.4 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20240718.0 + ws: 8.18.0 + youch: 3.3.4 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + miniflare@3.20241205.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.4 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20241205.0 + ws: 8.18.0 + youch: 3.3.4 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mkdirp-classic@0.5.3: {} + + mri@1.2.0: {} + + ms@2.1.3: {} + + multiformats@11.0.2: {} + + multiformats@12.1.3: {} + + multiformats@13.3.1: {} + + murmurhash3js-revisited@3.0.0: {} + + mustache@4.2.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nan-x@2.2.1: {} + + nanoid@3.3.7: {} + + napi-build-utils@1.0.2: {} + + native-fetch@3.0.0(node-fetch@2.7.0(encoding@0.1.13)): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + + natural-compare@1.4.0: {} + + next-tick@1.1.0: {} + + node-abi@3.68.0: + dependencies: + semver: 7.6.3 + + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-forge@1.3.1: {} + + node-sql-parser@3.9.4: + dependencies: + big-integer: 1.6.52 + + node-sqlite3-wasm@0.8.28: {} + + noop-x@1.2.1: {} + + normalize-space-x@4.1.2: + dependencies: + simple-methodize-x: 1.0.4 + trim-x: 4.1.2 + white-space-x: 4.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + object-assign@4.1.1: {} + + object-create-x@3.1.2: + dependencies: + attempt-x: 2.1.2 + is-primitive-x: 1.0.1 + object-define-properties-x: 5.1.2 + to-boolean-x: 2.1.1 + + object-define-properties-x@5.1.2: + dependencies: + array-for-each-x: 3.1.2 + assert-is-object-x: 3.1.2 + get-own-enumerable-keys-x: 2.1.2 + object-define-property-x: 5.1.2 + to-object-x: 2.2.1 + + object-define-property-x@5.1.2: + dependencies: + assert-is-object-x: 3.1.2 + attempt-x: 2.1.2 + has-own-property-x: 4.1.2 + has-symbol-support-x: 2.1.2 + is-function-x: 4.1.2 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + to-property-key-x: 3.1.2 + + object-get-own-property-descriptor-x@4.1.2: + dependencies: + attempt-x: 2.1.2 + has-own-property-x: 4.1.2 + has-symbol-support-x: 2.1.2 + is-index-x: 2.1.2 + is-primitive-x: 1.0.1 + is-string: 1.0.7 + property-is-enumerable-x: 2.1.2 + simple-methodize-x: 1.0.4 + to-boolean-x: 2.1.1 + to-object-x: 2.2.1 + to-property-key-x: 3.1.2 + + object-is@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + object-keys-x@3.1.2: + dependencies: + array-like-slice-x: 2.2.2 + attempt-x: 2.1.2 + has-own-property-x: 4.1.2 + is-arguments: 1.1.1 + is-array-x: 2.1.2 + is-regexp-x: 3.1.2 + is-string: 1.0.7 + object-keys: 1.1.1 + split-if-boxed-bug-x: 2.1.2 + to-object-x: 2.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + ohash@1.1.4: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + one-webcrypto@1.0.3: {} + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-defer@3.0.0: {} + + p-defer@4.0.1: {} + + p-fifo@1.0.0: + dependencies: + fast-fifo: 1.3.2 + p-defer: 3.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@6.1.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@7.0.2: {} + + p-queue@8.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.2 + + p-retry@5.1.2: + dependencies: + '@types/retry': 0.12.1 + retry: 0.13.1 + + p-retry@6.2.0: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + + p-timeout@6.1.2: {} + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-int-x@3.2.2: + dependencies: + nan-x: 2.2.1 + simple-methodize-x: 1.0.4 + to-string-x: 2.1.1 + trim-left-x: 4.1.2 + + partykit@0.0.111: + dependencies: + '@cloudflare/workers-types': 4.20240718.0 + clipboardy: 4.0.0 + esbuild: 0.21.5 + miniflare: 3.20240718.0 + yoga-wasm-web: 0.3.3 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + partysocket@1.0.2: + dependencies: + event-target-shim: 6.0.2 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@6.3.0: {} + + path@0.12.7: + dependencies: + process: 0.11.10 + util: 0.10.4 + + pathe@1.1.2: {} + + pathval@2.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pirates@4.0.6: {} + + possible-typed-array-names@1.0.0: {} + + postcss-load-config@6.0.1(postcss@8.4.49)(tsx@4.19.2)(yaml@2.5.1): + dependencies: + lilconfig: 3.1.2 + optionalDependencies: + postcss: 8.4.49 + tsx: 4.19.2 + yaml: 2.5.1 + + postcss@8.4.49: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prebuild-install@7.1.2: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.68.0 + pump: 3.0.2 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + + prelude-ls@1.2.1: {} + + prettier@3.4.2: {} + + printable-characters@1.0.42: {} + + process@0.11.10: {} + + progress-events@1.0.1: {} + + prolly-trees@1.0.4: + dependencies: + bl: 4.1.0 + node-sql-parser: 3.9.4 + + property-is-enumerable-x@2.1.2: + dependencies: + simple-methodize-x: 1.0.4 + to-object-x: 2.2.1 + to-property-key-x: 3.1.2 + + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.10.1 + long: 5.2.3 + + protons-runtime@5.5.0: + dependencies: + uint8-varint: 2.0.4 + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + + proxy-from-env@1.1.0: {} + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + rabin-rs@2.1.0: {} + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + react-native-fetch-api@3.0.0: + dependencies: + p-defer: 3.0.0 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@4.0.2: {} + + rename-function-x@1.1.2: + dependencies: + assert-is-function-x: 3.1.2 + attempt-x: 2.1.2 + is-var-name: 2.0.0 + object-define-property-x: 5.1.2 + object-get-own-property-descriptor-x: 4.1.2 + to-boolean-x: 2.1.1 + to-string-x: 2.1.1 + + replace-comments-x@3.1.2: + dependencies: + require-coercible-to-string-x: 2.1.1 + simple-methodize-x: 1.0.4 + to-string-x: 2.1.1 + + require-coercible-to-string-x@2.1.1: + dependencies: + require-object-coercible-x: 2.1.1 + to-string-x: 2.1.1 + + require-from-string@2.0.2: {} + + require-object-coercible-x@2.1.1: + dependencies: + is-nil-x: 2.1.1 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rollup-plugin-inject@3.0.2: + dependencies: + estree-walker: 0.6.1 + magic-string: 0.25.9 + rollup-pluginutils: 2.8.2 + + rollup-plugin-node-polyfills@0.2.1: + dependencies: + rollup-plugin-inject: 3.0.2 + + rollup-pluginutils@2.8.2: + dependencies: + estree-walker: 0.6.1 + + rollup@4.24.0: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.24.0 + '@rollup/rollup-android-arm64': 4.24.0 + '@rollup/rollup-darwin-arm64': 4.24.0 + '@rollup/rollup-darwin-x64': 4.24.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 + '@rollup/rollup-linux-arm-musleabihf': 4.24.0 + '@rollup/rollup-linux-arm64-gnu': 4.24.0 + '@rollup/rollup-linux-arm64-musl': 4.24.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 + '@rollup/rollup-linux-riscv64-gnu': 4.24.0 + '@rollup/rollup-linux-s390x-gnu': 4.24.0 + '@rollup/rollup-linux-x64-gnu': 4.24.0 + '@rollup/rollup-linux-x64-musl': 4.24.0 + '@rollup/rollup-win32-arm64-msvc': 4.24.0 + '@rollup/rollup-win32-ia32-msvc': 4.24.0 + '@rollup/rollup-win32-x64-msvc': 4.24.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.8.1: + dependencies: + tslib: 2.7.0 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + same-value-x@2.1.1: + dependencies: + is-nan-x: 2.1.1 + + same-value-zero-x@2.1.1: + dependencies: + same-value-x: 2.1.1 + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + semver@7.6.3: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + simple-bind-x@1.0.3: + dependencies: + has-working-bind-x: 1.0.1 + util-pusher-x: 1.0.3 + + simple-call-x@1.0.3: + dependencies: + simple-bind-x: 1.0.3 + util-pusher-x: 1.0.3 + + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + simple-methodize-x@1.0.4: + dependencies: + simple-call-x: 1.0.3 + util-pusher-x: 1.0.3 + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + sparse-array@1.3.2: {} + + split-if-boxed-bug-x@2.1.2: + dependencies: + has-boxed-string-x: 2.1.1 + is-string: 1.0.7 + simple-methodize-x: 1.0.4 + + stackback@0.0.2: {} + + stacktracey@2.1.8: + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + + std-env@3.8.0: {} + + stoppable@1.1.0: {} + + stream-to-it@0.2.4: + dependencies: + get-iterator: 1.0.2 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-final-newline@3.0.0: {} + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + strnum@1.0.5: {} + + stubborn-fs@1.2.5: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-iterator-x@1.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + is-nil-x: 2.1.1 + + symbol-species-x@1.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + + sync-multihash-sha2@1.0.0: + dependencies: + '@noble/hashes': 1.5.0 + + system-architecture@0.1.0: {} + + tar-fs@2.1.1: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.2 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + thingies@1.21.0(tslib@2.7.0): + dependencies: + tslib: 2.7.0 + + timers-ext@0.1.8: + dependencies: + es5-ext: 0.10.64 + next-tick: 1.1.0 + + tinybench@2.9.0: {} + + tinyexec@0.3.1: {} + + tinyglobby@0.2.9: + dependencies: + fdir: 6.4.0(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.0.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + to-boolean-x@2.1.1: {} + + to-integer-x@4.2.2: + dependencies: + is-finite-x: 4.2.1 + is-nan-x: 2.1.1 + math-sign-x: 4.2.2 + to-number-x: 3.2.2 + + to-length-x@4.2.2: + dependencies: + to-integer-x: 4.2.2 + + to-number-x@3.2.2: + dependencies: + is-symbol: 1.0.4 + nan-x: 2.2.1 + parse-int-x: 3.2.2 + simple-methodize-x: 1.0.4 + to-primitive-x: 2.1.2 + trim-x: 4.1.2 + + to-object-x@2.2.1: + dependencies: + cached-constructors-x: 2.2.1 + require-object-coercible-x: 2.1.1 + + to-primitive-x@2.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + is-date-object: 1.0.5 + is-function-x: 4.1.2 + is-nil-x: 2.1.1 + is-primitive-x: 1.0.1 + is-symbol: 1.0.4 + require-object-coercible-x: 2.1.1 + simple-call-x: 1.0.3 + + to-property-key-x@3.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + to-primitive-x: 2.1.2 + to-string-x: 2.1.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-string-symbols-supported-x@2.1.2: + dependencies: + has-symbol-support-x: 2.1.2 + is-symbol: 1.0.4 + + to-string-tag-x@2.1.2: + dependencies: + simple-methodize-x: 1.0.4 + + to-string-x@2.1.1: + dependencies: + is-symbol: 1.0.4 + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tree-dump@1.0.2(tslib@2.7.0): + dependencies: + tslib: 2.7.0 + + tree-kill@1.2.2: {} + + trim-left-x@4.1.2: + dependencies: + require-coercible-to-string-x: 2.1.1 + simple-methodize-x: 1.0.4 + white-space-x: 4.1.1 + + trim-right-x@4.1.2: + dependencies: + require-coercible-to-string-x: 2.1.1 + simple-methodize-x: 1.0.4 + white-space-x: 4.1.1 + + trim-x@4.1.2: + dependencies: + trim-left-x: 4.1.2 + trim-right-x: 4.1.2 + + ts-api-utils@1.3.0(typescript@5.7.2): + dependencies: + typescript: 5.7.2 + + ts-essentials@10.0.2(typescript@5.7.2): + optionalDependencies: + typescript: 5.7.2 + + ts-interface-checker@0.1.13: {} + + tsconfck@3.1.4(typescript@5.7.2): + optionalDependencies: + typescript: 5.7.2 + + tslib@2.7.0: {} + + tsup@8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.5.1): + dependencies: + bundle-require: 5.0.0(esbuild@0.24.0) + cac: 6.7.14 + chokidar: 4.0.1 + consola: 3.2.3 + debug: 4.3.7 + esbuild: 0.24.0 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(postcss@8.4.49)(tsx@4.19.2)(yaml@2.5.1) + resolve-from: 5.0.0 + rollup: 4.24.0 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tinyexec: 0.3.1 + tinyglobby: 0.2.9 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.4.49 + typescript: 5.7.2 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + tsx@4.19.2: + dependencies: + esbuild: 0.23.1 + get-tsconfig: 4.8.1 + optionalDependencies: + fsevents: 2.3.3 + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@2.19.0: {} + + type-fest@4.26.1: {} + + type@2.7.3: {} + + typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + eslint: 9.16.0 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + + typescript@5.7.2: {} + + ufo@1.5.4: {} + + uint8-varint@2.0.4: + dependencies: + uint8arraylist: 2.4.8 + uint8arrays: 5.1.0 + + uint8arraylist@2.4.8: + dependencies: + uint8arrays: 5.1.0 + + uint8arrays@4.0.10: + dependencies: + multiformats: 12.1.3 + + uint8arrays@5.1.0: + dependencies: + multiformats: 13.3.1 + + undici-types@6.20.0: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + unenv-nightly@2.0.0-20241204-140205-a5d5190: + dependencies: + defu: 6.1.4 + ohash: 1.1.4 + pathe: 1.1.2 + ufo: 1.5.4 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + util-get-getter-x@1.0.2: + dependencies: + attempt-x: 2.1.2 + is-object-like-x: 2.1.2 + object-get-own-property-descriptor-x: 4.1.2 + simple-call-x: 1.0.3 + + util-pusher-x@1.0.3: + dependencies: + has-boxed-string-x: 2.1.1 + has-working-bind-x: 1.0.1 + is-primitive-x: 1.0.1 + is-string: 1.0.7 + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + + uuid@9.0.1: {} + + varint@6.0.0: {} + + vite-node@2.1.8(@types/node@22.10.1): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + es-module-lexer: 1.5.4 + pathe: 1.1.2 + vite: 5.4.11(@types/node@22.10.1) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1)): + dependencies: + debug: 4.3.7 + globrex: 0.1.2 + tsconfck: 3.1.4(typescript@5.7.2) + optionalDependencies: + vite: 6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1) + transitivePeerDependencies: + - supports-color + - typescript + + vite@5.4.11(@types/node@22.10.1): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.24.0 + optionalDependencies: + '@types/node': 22.10.1 + fsevents: 2.3.3 + + vite@6.0.3(@types/node@22.10.1)(tsx@4.19.2)(yaml@2.5.1): + dependencies: + esbuild: 0.24.0 + postcss: 8.4.49 + rollup: 4.24.0 + optionalDependencies: + '@types/node': 22.10.1 + fsevents: 2.3.3 + tsx: 4.19.2 + yaml: 2.5.1 + + vitest@2.1.8(@types/node@22.10.1): + dependencies: + '@vitest/expect': 2.1.8 + '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.1)) + '@vitest/pretty-format': 2.1.8 + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 + debug: 4.3.7 + expect-type: 1.1.0 + magic-string: 0.30.12 + pathe: 1.1.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.1 + tinypool: 1.0.1 + tinyrainbow: 1.2.0 + vite: 5.4.11(@types/node@22.10.1) + vite-node: 2.1.8(@types/node@22.10.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.10.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + wait-on@8.0.1: + dependencies: + axios: 1.7.7 + joi: 17.13.3 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.1 + transitivePeerDependencies: + - debug + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + when-exit@2.1.3: {} + + which-boxed-primitive@1.0.2: + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + which-typed-array@1.1.15: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + white-space-x@4.1.1: {} + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + workerd@1.20240718.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20240718.0 + '@cloudflare/workerd-darwin-arm64': 1.20240718.0 + '@cloudflare/workerd-linux-64': 1.20240718.0 + '@cloudflare/workerd-linux-arm64': 1.20240718.0 + '@cloudflare/workerd-windows-64': 1.20240718.0 + + workerd@1.20241205.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20241205.0 + '@cloudflare/workerd-darwin-arm64': 1.20241205.0 + '@cloudflare/workerd-linux-64': 1.20241205.0 + '@cloudflare/workerd-linux-arm64': 1.20241205.0 + '@cloudflare/workerd-windows-64': 1.20241205.0 + + wrangler@3.93.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.10.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 4.0.1 + date-fns: 4.1.0 + esbuild: 0.17.19 + itty-time: 1.0.6 + miniflare: 3.20241205.0 + nanoid: 3.3.7 + path-to-regexp: 6.3.0 + resolve: 1.22.8 + selfsigned: 2.4.1 + source-map: 0.6.1 + unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190 + workerd: 1.20241205.0 + xxhash-wasm: 1.0.2 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@8.18.0: {} + + xxhash-wasm@1.0.2: {} + + yaml@2.5.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} + + yoga-wasm-web@0.3.3: {} + + youch@3.3.4: + dependencies: + cookie: 0.7.2 + mustache: 4.2.0 + stacktracey: 2.1.8 + + zod@3.23.8: {} + + zx@8.2.4: + optionalDependencies: + '@types/fs-extra': 11.0.4 + '@types/node': 22.10.1 diff --git a/src/ucan/clock/capabilities.ts b/src/ucan/clock/capabilities.ts index 4f83de96..ddcfce85 100644 --- a/src/ucan/clock/capabilities.ts +++ b/src/ucan/clock/capabilities.ts @@ -38,7 +38,6 @@ export const claimShare = capability({ can: "clock/claim-share", with: DID.match({ method: "key" }).or(DID.match({ method: "mailto" })), nb: Schema.struct({ - issuer: DID.match({ method: "mailto" }), proof: Link.match({ version: 1 }), recipient: DID.match({ method: "mailto" }), }), @@ -51,7 +50,6 @@ export const claimShares = capability({ can: "clock/claim-shares", with: DID.match({ method: "key" }).or(DID.match({ method: "mailto" })), nb: Schema.struct({ - issuer: DID.match({ method: "mailto" }), recipient: DID.match({ method: "mailto" }), }), }); diff --git a/src/ucan/common.ts b/src/ucan/common.ts index abdf2114..89caa55e 100644 --- a/src/ucan/common.ts +++ b/src/ucan/common.ts @@ -1,10 +1,36 @@ import { importDAG } from "@ucanto/core/delegation"; import { Delegation } from "@ucanto/interface"; -import type { AgentDataExport, DelegationMeta } from "@web3-storage/access/types"; +import type { Agent, AgentDataExport, DelegationMeta } from "@web3-storage/access/types"; import { Block } from "multiformats/block"; import { CID } from "multiformats"; import { to_arraybuf } from "../coerce-binary.js"; +import type { Service } from "./types.js"; + +export function agentProofs( + agent: Agent, + mailtoDID?: `did:mailto:${string}:${string}` +): { attestations: Delegation[]; delegations: Delegation[] } { + const proofs = agent.proofs([{ with: /did:mailto:.*/, can: "*" }]); + const delegations = proofs.filter( + (p) => p.capabilities[0].can === "*" && (mailtoDID ? p.issuer.did() === mailtoDID : true) + ); + + const delegationCids = delegations.map((d) => d.cid.toString()); + const attestations = proofs.filter((p) => { + const cap = p.capabilities[0]; + return ( + cap.can === "ucan/attest" && + delegationCids.includes((cap.nb as { proof: { toString(): string } }).proof.toString()) + ); + }); + + return { + delegations, + attestations, + }; +} + export async function extractDelegation(dataExport: AgentDataExport): Promise { const delegationKey = Array.from(dataExport.delegations.keys())[0]; const delegationExport = delegationKey ? dataExport.delegations.get(delegationKey)?.delegation : undefined; diff --git a/src/ucan/index.ts b/src/ucan/index.ts index 1316eaf5..cfda95f6 100644 --- a/src/ucan/index.ts +++ b/src/ucan/index.ts @@ -3,11 +3,14 @@ import { bs, type Database } from "@fireproof/core"; import { Delegation, Principal, SignerArchive } from "@ucanto/interface"; import { Agent, type AgentMeta, type AgentData, type AgentDataExport } from "@web3-storage/access/agent"; import { Absentee, ed25519 } from "@ucanto/principal"; -import { DID } from "@ucanto/core"; +import { DID, parseLink } from "@ucanto/core"; import { DidMailto, fromEmail, toEmail } from "@web3-storage/did-mailto"; import * as W3 from "@web3-storage/w3up-client/account"; import * as Del from "@ucanto/core/delegation"; import { unwrap } from "@web3-storage/w3up-client/result"; +import { bytesToDelegations } from "@web3-storage/access/encoding"; +import * as Signature from "@ipld/dag-ucan/signature"; +import type { Signer as SignerWithoutVerifier } from "@ipld/dag-ucan"; import * as Client from "./client.js"; import * as ClockCaps from "./clock/capabilities.js"; @@ -15,7 +18,7 @@ import { connectionFactory, makeKeyBagUrlExtractable } from "../connection-from- import { registerUCANStoreProtocol } from "./ucan-gateway.js"; import stateStore from "./store/state/index.js"; import { Service, type AgentWithStoreName, type Clock, type ClockWithoutDelegation, type Server } from "./types.js"; -import { exportDelegation, extractDelegation } from "./common.js"; +import { agentProofs, exportDelegation, extractDelegation } from "./common.js"; // Exports @@ -36,6 +39,7 @@ export interface ConnectionParams { readonly agent: AgentWithStoreName; readonly clock: Clock | ClockWithoutDelegation; readonly email: Principal; + readonly poll: boolean; readonly server: Server; } @@ -76,6 +80,7 @@ export async function connect( .setParam("agent-store", agnt.storeName) .setParam("clock-id", klok.id.did()) .setParam("name", name) + .setParam("poll", params.poll === true ? "t" : "f") .setParam("server-host", serv.uri.toString()) .setParam("server-id", serv.id.did()) .setParam("storekey", `@${dbName}:data@`); @@ -84,12 +89,15 @@ export async function connect( if (email) fpUrl.setParam("email-id", email.did()); // Connect - const connection = connectionCache.get(fpUrl.toString()).once(() => { + const connection = await connectionCache.get(fpUrl.toString()).once(async () => { makeKeyBagUrlExtractable(sthis); - const connection = connectionFactory(sthis, fpUrl); - connection.connect_X(blockstore); - return connection; + const conn = connectionFactory(sthis, fpUrl); + await conn.connect_X(blockstore); + return conn; }); + + await connection.loaded; + // Fin return { agent: agnt, @@ -162,7 +170,7 @@ export async function loadSavedAgent(options?: { export async function clock(options: { audience: Principal | AgentWithStoreName; - databaseName: string; + databaseName?: string; storeName?: string; }): Promise { const clockFromStore = await loadSavedClock(options); @@ -181,7 +189,7 @@ export async function clockDelegation({ storeName, }: { audience: Principal | AgentWithStoreName; - databaseName: string; + databaseName?: string; delegation: Delegation; storeName?: string; }): Promise { @@ -227,8 +235,8 @@ export function clockId(id: `did:key:${string}`): ClockWithoutDelegation { return { id: DID.parse(id), isNew: false }; } -export function clockStoreName({ audience, databaseName }: { audience: Principal; databaseName: string }) { - return `fireproof/${databaseName}/${audience.did()}/clock`; +export function clockStoreName({ audience, databaseName }: { audience: Principal; databaseName?: string }) { + return databaseName ? `fireproof/${databaseName}/${audience.did()}/clock` : `fireproof/${audience.did()}/clock`; } export async function createAndSaveClock({ @@ -237,7 +245,7 @@ export async function createAndSaveClock({ storeName, }: { audience: Principal | AgentWithStoreName; - databaseName: string; + databaseName?: string; storeName?: string; }): Promise { const clockAudience = "agent" in audience ? audience.agent : audience; @@ -267,7 +275,7 @@ export async function loadSavedClock({ storeName, }: { audience: Principal | AgentWithStoreName; - databaseName: string; + databaseName?: string; storeName?: string; }): Promise { const clockAudience = "agent" in audience ? audience.agent : audience; @@ -303,10 +311,20 @@ export async function registerClock(params: { clock: Clock; server?: Server }) { const AGENT_META: AgentMeta = { name: "fireproof-agent", type: "app" }; -export function email(string: `${string}@${string}`): Principal { +export function email(string: `${string}@${string}`): SignerWithoutVerifier { return Absentee.from({ id: fromEmail(string) }); } +export async function isLoggedIn(params: { + agent?: AgentWithStoreName; + email: Principal; +}): Promise { + const proxy = params.agent || (await agent()); + const proofs = proxy.agent.proofs([{ with: params.email.did(), can: "*" }]); + + return proofs.length > 0; +} + export async function login(params: { agent?: AgentWithStoreName; email: Principal }) { const proxy = params.agent || (await agent()); const result = await W3.login({ agent: proxy.agent as unknown as Agent }, toEmail(params.email.did())); @@ -359,6 +377,155 @@ export async function server( }; } +// SHARING +// ------- + +/** + * Claim a specific share. + * + * ⚠️ Polls until the share is confirmed and the delegation is available on the server. + * + * @param context + * @param context.email The (principal) email of the receiver of the share. + * @param context.cid The CID communicated by the sharer. + */ +export async function claimShare( + args: { email: Principal; cid: string }, + context?: { + agent?: AgentWithStoreName; + server?: Server; + } +) { + const ctx = { + agent: context?.agent || (await agent({ server: context?.server })), + server: context?.server || (await server()), + }; + + const proofs = agentProofs(ctx.agent.agent); + const attestation = proofs.attestations[0]; + const delegation = proofs.delegations[0]; + + const claim = async () => { + const resp = await ClockCaps.claimShare + .invoke({ + issuer: ctx.agent.agent.issuer, + audience: ctx.server.id, + with: ctx.agent.id.did(), + proofs: [attestation, delegation], + nb: { recipient: args.email.did(), proof: parseLink(args.cid) }, + }) + .execute(ctx.agent.agent.connection); + + if (resp.out.error) throw resp.out.error; + return Object.values(resp.out.ok.delegations).flatMap((proof) => bytesToDelegations(proof)); + }; + + const poll = async () => { + const proofs = await claim(); + const attestation = proofs.find((p) => p.capabilities[0].can === "ucan/attest"); + + if (!attestation) { + await new Promise((resolve) => { + setTimeout(resolve, 2500); + }); + + return await poll(); + } + + return proofs; + }; + + return await poll(); +} + +/** + * Claim all shares. + * + * @param args + * @param args.email The (principal) email of the receiver of the share. + */ +export async function claimShares( + args: { email: Principal }, + context?: { + agent?: AgentWithStoreName; + server?: Server; + } +) { + const ctx = { + agent: context?.agent || (await agent({ server: context?.server })), + server: context?.server || (await server()), + }; + + const proofs = agentProofs(ctx.agent.agent); + const attestation = proofs.attestations[0]; + const delegation = proofs.delegations[0]; + + const resp = await ClockCaps.claimShares + .invoke({ + issuer: ctx.agent.agent.issuer, + audience: ctx.server.id, + with: ctx.agent.id.did(), + proofs: [attestation, delegation], + nb: { recipient: args.email.did() }, + }) + .execute(ctx.agent.agent.connection); + + if (resp.out.error) throw resp.out.error; + return Object.values(resp.out.ok.delegations).flatMap((proof) => bytesToDelegations(proof)); +} + +/** + * Share database access to a given email address. + * + * This makes a delegation to the email address and starts + * the authorization process. The sharer will receive an email + * with a link that will validate the share. Returns a CID + * that has to be communicated to the receiver of the share. + */ +export async function share( + args: { + from: SignerWithoutVerifier; + to: Principal; + }, + { + agent, + clock, + server, + }: { + agent: AgentWithStoreName; + clock: Clock; + server: Server; + } +): Promise<{ cid: string }> { + if (clock.delegation.audience.did() !== args.from.did()) { + throw new Error("The audience of the given clock (delegation) does not match the `from` email address."); + } + + const delegation = await delegateClock({ + audience: args.to, + clockDID: clock.id.did(), + issuer: args.from, + proof: clock.delegation, + }); + + const authorizeShareResp = await ClockCaps.authorizeShare + .invoke({ + issuer: agent.agent.issuer, + audience: server.id, + with: agent.agent.issuer.did(), + nb: { + issuer: args.from.did(), + recipient: args.to.did(), + proof: delegation.cid, + }, + proofs: [delegation], + }) + .execute(agent.agent.connection); + + if (authorizeShareResp.out.error) throw authorizeShareResp.out.error; + return { cid: delegation.cid.toString() }; +} + // UTILS // ===== @@ -374,3 +541,23 @@ export const delegation = { return result.ok; }, }; + +async function delegateClock({ + audience, + clockDID, + issuer, + proof, +}: { + audience: Principal; + clockDID: `did:key:${string}`; + issuer: SignerWithoutVerifier; + proof: Delegation; +}): Promise { + return await ClockCaps.clock.delegate({ + issuer, + audience, + with: clockDID, + proofs: [proof], + expiration: Infinity, + }); +} diff --git a/src/ucan/types.ts b/src/ucan/types.ts index 671919bd..3551d895 100644 --- a/src/ucan/types.ts +++ b/src/ucan/types.ts @@ -53,10 +53,6 @@ export interface ClockAdvanceSuccess { readonly head: string; } -export interface ClockAuthorizeShareSuccess { - readonly url: string; -} - export interface ClockClaimShareSuccess { readonly delegations: Record; } @@ -87,7 +83,7 @@ export interface Service { }; readonly clock: { readonly advance: ServiceMethod; - readonly "authorize-share": ServiceMethod; + readonly "authorize-share": ServiceMethod; readonly "claim-share": ServiceMethod; readonly "claim-shares": ServiceMethod; readonly "confirm-share": ServiceMethod; diff --git a/src/ucan/ucan-gateway.ts b/src/ucan/ucan-gateway.ts index f27d1d46..27a9a704 100644 --- a/src/ucan/ucan-gateway.ts +++ b/src/ucan/ucan-gateway.ts @@ -11,7 +11,7 @@ import { CID } from "multiformats"; import * as Client from "./client.js"; import { Server, Service } from "./types.js"; import stateStore from "./store/state/index.js"; -import { extractDelegation } from "./common.js"; +import { agentProofs, extractDelegation } from "./common.js"; export class UCANGateway implements bs.Gateway { readonly sthis: SuperThis; @@ -22,6 +22,7 @@ export class UCANGateway implements bs.Gateway { clockDelegation?: Delegation; clockId: Principal<`did:key:${string}`>; email?: Principal; + polling: boolean; server: Server; service: ConnectionView; }; @@ -49,6 +50,7 @@ export class UCANGateway implements bs.Gateway { const clockStoreName = baseUrl.getParam("clock-store"); const emailIdParam = baseUrl.getParam("email-id"); const serverId = baseUrl.getParam("server-id"); + const polling = baseUrl.getParam("poll") === "t" ? true : false; // Validate params if (!dbName) throw new Error("Missing `name` param"); @@ -94,7 +96,7 @@ export class UCANGateway implements bs.Gateway { } // This - this.inst = { agent, clockDelegation, clockId, email, server, service }; + this.inst = { agent, clockDelegation, clockId, email, polling, server, service }; // Super await this.sthis.start(); @@ -136,6 +138,7 @@ export class UCANGateway implements bs.Gateway { } this.logger.Debug().Str("store", store).Str("key", key).Msg("put"); + console.log("🏗️ PUT", store); switch (store.toLowerCase()) { case "data": { @@ -219,6 +222,7 @@ export class UCANGateway implements bs.Gateway { } this.logger.Debug().Str("store", store).Str("key", key).Msg("get"); + console.log("🔮 GET", store); switch (store.toLowerCase()) { case "data": { @@ -245,10 +249,8 @@ export class UCANGateway implements bs.Gateway { service: this.inst.service, }); - // eslint-disable-next-line no-console - console.log(head.out); - this.logger.Debug().Any("head", head.out).Msg("Meta (head) retrieved"); + console.log(head.out); if (head.out.error) throw head.out.error; if (head.out.ok.head === undefined) throw new NotFoundError(); @@ -287,28 +289,61 @@ export class UCANGateway implements bs.Gateway { return Result.Ok(undefined); } + private readonly subscriberCallbacks = new Set<(data: Uint8Array) => void>(); + + private notifySubscribers(data: Uint8Array): void { + for (const callback of this.subscriberCallbacks) { + try { + callback(data); + } catch (error) { + console.error(error); + this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); + } + } + } + + async subscribe(url: URI, callback: (msg: Uint8Array) => void): Promise { + // eslint-disable-next-line + if (!this.inst?.polling) return Result.Ok(() => {}); + + // Setup polling + url = url.build().setParam("key", "main").URI(); + + const interval = 3000; + let lastData: Uint8Array | undefined = undefined; + + const fetchData = async () => { + const result = await this.get(url); + + if (result.isOk()) { + const data = result.Ok(); + + if (!lastData || !data.every((value, index) => lastData && value === lastData[index])) { + lastData = data; + this.notifySubscribers(data); + } + } + + timeoutId = setTimeout(fetchData, interval); + }; + + this.subscriberCallbacks.add(callback); + let timeoutId = setTimeout(fetchData, interval); + + return Result.Ok(() => { + clearTimeout(timeoutId); + this.subscriberCallbacks.delete(callback); + }); + } + //////////////////////////////////////// // AGENT //////////////////////////////////////// proofs(): Delegation[] { if (this.inst && this.inst.email) { - const proofs = this.inst.agent.proofs([{ with: /did:mailto:.*/, can: "*" }]); - - const delegations = proofs.filter( - (p) => p.capabilities[0].can === "*" && p.issuer.did() === this.inst?.email?.did() - ); - - const delegationCids = delegations.map((d) => d.cid.toString()); - const attestations = proofs.filter((p) => { - const cap = p.capabilities[0]; - return ( - cap.can === "ucan/attest" && - delegationCids.includes((cap.nb as { proof: { toString(): string } }).proof.toString()) - ); - }); - - return [...delegations, ...attestations]; + const proofs = agentProofs(this.inst.agent); + return [...proofs.delegations, ...proofs.attestations]; } if (this.inst && this.inst.clockDelegation) { From 3095a32011fa12004c73c93bc462e4f2ce584e95 Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Tue, 10 Dec 2024 18:28:38 +0100 Subject: [PATCH 58/83] feat: Enable polling in browser ucan example + format code --- examples/ucan/browser/package.json | 2 +- examples/ucan/browser/pnpm-lock.yaml | 120 ++--- examples/ucan/browser/src/state.js | 195 ++++--- examples/ucan/browser/src/types.d.ts | 23 +- examples/ucan/browser/src/view.js | 503 +++++++++--------- examples/ucan/node/package.json | 2 +- .../ucan/workshop/participants/package.json | 2 +- examples/ucan/workshop/team/package.json | 2 +- src/ucan/ucan-gateway.ts | 2 +- 9 files changed, 424 insertions(+), 427 deletions(-) diff --git a/examples/ucan/browser/package.json b/examples/ucan/browser/package.json index 457e7b6e..1a43d809 100644 --- a/examples/ucan/browser/package.json +++ b/examples/ucan/browser/package.json @@ -7,7 +7,7 @@ "preview": "rsbuild preview" }, "dependencies": { - "@fireproof/core": "0.19.113", + "@fireproof/core": "0.19.116", "@fireproof/ucan": "../../../dist/ucan", "@picocss/pico": "^2.0.6", "spellcaster": "^5.0.2" diff --git a/examples/ucan/browser/pnpm-lock.yaml b/examples/ucan/browser/pnpm-lock.yaml index 85ad35c4..8c55532c 100644 --- a/examples/ucan/browser/pnpm-lock.yaml +++ b/examples/ucan/browser/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@fireproof/core': - specifier: 0.19.113 - version: 0.19.113(react@18.3.1)(typescript@5.6.3) + specifier: 0.19.116 + version: 0.19.116(react@18.3.1)(typescript@5.6.3) '@fireproof/ucan': specifier: ../../../dist/ucan version: link:../../../dist/ucan @@ -42,8 +42,8 @@ importers: packages: - '@adviser/cement@0.2.36': - resolution: {integrity: sha512-Zhmr4f0/UohFh3O/6H63DoBenYjh72uGZOcEnDZ/VxmBvZelACkCR4g06c8rbZbJTu20f3gRSNnJZbmtdMOFgQ==} + '@adviser/cement@0.2.41': + resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} engines: {node: '>=16'} '@babel/code-frame@7.26.2': @@ -88,11 +88,14 @@ packages: resolution: {integrity: sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@fireproof/core@0.19.113': - resolution: {integrity: sha512-LGAgDBd8MePZ2QUaBav2Wd1pa37SvYfngNAaDh00WGCL9skF+y4ZhcVmhUGNcIKG3xcANsyxouFu7h0rgBoNeA==} + '@fireproof/core@0.19.116': + resolution: {integrity: sha512-QwxOG3Ck+j0uMTSTqg9Uy13dSB5U6QUvaNhQGeetc/BALhxTR82gS0QfnK6A6loc9kqzvKHp599gvl/rVEetVA==} peerDependencies: react: ^18.3.1 + '@fireproof/vendor@1.0.0': + resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -113,18 +116,6 @@ packages: resolution: {integrity: sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==} engines: {node: '>=18.18'} - '@ipld/car@5.3.3': - resolution: {integrity: sha512-4vgV5Ml4HCJ2iTx7vYhu0ui+Xxo1HQTtVeYgD+JKd5Wij8TlOFZnxOSickqpLcuf1fdGEStgqVItx15UWfzDYA==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - '@ipld/dag-cbor@9.2.2': - resolution: {integrity: sha512-uIEOuruCqKTP50OBWwgz4Js2+LhiBQaxc57cnP71f45b1mHEAo1OCR1Zn/TbvSW/mV1x+JqhacIktkKyaYqhCw==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - '@ipld/dag-json@10.2.3': - resolution: {integrity: sha512-itacv1j1hvYgLox2B42Msn70QLzcr0MEo5yGIENuw2SM/lQzq9bmBiMky+kDsIrsqqblKTXcHBZnnmK7D4a6ZQ==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - '@ipld/dag-pb@4.1.3': resolution: {integrity: sha512-ueULCaaSCcD+dQga6nKiRr+RSeVgdiYiEPKVUu5iQMNYDN+9osd0KpR3UDd9uQQ+6RWuv9L34SchfEwj7YIbOA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -364,10 +355,6 @@ packages: resolution: {integrity: sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@web3-storage/pail@0.6.0': - resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} - hasBin: true - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -489,10 +476,6 @@ packages: caniuse-lite@1.0.30001676: resolution: {integrity: sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==} - cborg@4.2.6: - resolution: {integrity: sha512-77vo4KlSwfjCIXcyZUVei4l2gdjesSCeYSx4U/Upwix7pcWZq8uw21sVRpjwn7mjEi//ieJPTj1MRWDHmud1Rg==} - hasBin: true - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -827,9 +810,6 @@ packages: interface-store@6.0.2: resolution: {integrity: sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==} - ipfs-unixfs-exporter@13.6.1: - resolution: {integrity: sha512-pYPI4oBTWao2//sFzAL0pURyojn79q/u5BuK6L5/nVbVUQVw6DcVP5uB1ySdWlTM2H+0Zlhp9+OL9aJBRIICpg==} - ipfs-unixfs@11.2.0: resolution: {integrity: sha512-J8FN1qM5nfrDo8sQKQwfj0+brTg1uBfZK2vY9hxci33lcl3BFrsELS9+1+4q/8tO1ASKfxZO8W3Pi2O4sVX2Lg==} @@ -973,8 +953,8 @@ packages: md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - memfs@4.14.0: - resolution: {integrity: sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==} + memfs@4.15.0: + resolution: {integrity: sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==} engines: {node: '>= 4.0.0'} merge2@1.4.1: @@ -1479,7 +1459,7 @@ packages: snapshots: - '@adviser/cement@0.2.36(typescript@5.6.3)': + '@adviser/cement@0.2.41(typescript@5.6.3)': dependencies: ts-essentials: 10.0.3(typescript@5.6.3) yaml: 2.6.1 @@ -1533,19 +1513,14 @@ snapshots: dependencies: levn: 0.4.1 - '@fireproof/core@0.19.113(react@18.3.1)(typescript@5.6.3)': + '@fireproof/core@0.19.116(react@18.3.1)(typescript@5.6.3)': dependencies: - '@adviser/cement': 0.2.36(typescript@5.6.3) - '@ipld/car': 5.3.3 - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 + '@adviser/cement': 0.2.41(typescript@5.6.3) + '@fireproof/vendor': 1.0.0 '@ipld/unixfs': 3.0.0 - '@web3-storage/pail': 0.6.0 - cborg: 4.2.6 charwise: 3.0.1 idb: 8.0.0 - ipfs-unixfs-exporter: 13.6.1 - memfs: 4.14.0 + memfs: 4.15.0 multiformats: 13.3.1 p-limit: 6.1.0 p-map: 7.0.2 @@ -1555,6 +1530,24 @@ snapshots: transitivePeerDependencies: - typescript + '@fireproof/vendor@1.0.0': + dependencies: + '@ipld/dag-pb': 4.1.3 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + varint: 6.0.0 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -1568,23 +1561,6 @@ snapshots: '@humanwhocodes/retry@0.4.0': {} - '@ipld/car@5.3.3': - dependencies: - '@ipld/dag-cbor': 9.2.2 - cborg: 4.2.6 - multiformats: 13.3.1 - varint: 6.0.0 - - '@ipld/dag-cbor@9.2.2': - dependencies: - cborg: 4.2.6 - multiformats: 13.3.1 - - '@ipld/dag-json@10.2.3': - dependencies: - cborg: 4.2.6 - multiformats: 13.3.1 - '@ipld/dag-pb@4.1.3': dependencies: multiformats: 13.3.1 @@ -1862,11 +1838,6 @@ snapshots: '@typescript-eslint/types': 8.12.2 eslint-visitor-keys: 3.4.3 - '@web3-storage/pail@0.6.0': - dependencies: - '@ipld/dag-cbor': 9.2.2 - multiformats: 13.3.1 - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -2021,8 +1992,6 @@ snapshots: caniuse-lite@1.0.30001676: {} - cborg@4.2.6: {} - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -2408,25 +2377,6 @@ snapshots: interface-store@6.0.2: {} - ipfs-unixfs-exporter@13.6.1: - dependencies: - '@ipld/dag-cbor': 9.2.2 - '@ipld/dag-json': 10.2.3 - '@ipld/dag-pb': 4.1.3 - '@multiformats/murmur3': 2.1.8 - hamt-sharding: 3.0.6 - interface-blockstore: 5.3.1 - ipfs-unixfs: 11.2.0 - it-filter: 3.1.1 - it-last: 3.0.6 - it-map: 3.1.1 - it-parallel: 3.0.8 - it-pipe: 3.0.1 - it-pushable: 3.2.3 - multiformats: 13.3.1 - p-queue: 8.0.1 - progress-events: 1.0.1 - ipfs-unixfs@11.2.0: dependencies: protons-runtime: 5.5.0 @@ -2559,7 +2509,7 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 - memfs@4.14.0: + memfs@4.15.0: dependencies: '@jsonjoy.com/json-pack': 1.1.0(tslib@2.8.1) '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) diff --git a/examples/ucan/browser/src/state.js b/examples/ucan/browser/src/state.js index c87c9edf..5bd0af18 100644 --- a/examples/ucan/browser/src/state.js +++ b/examples/ucan/browser/src/state.js @@ -30,52 +30,65 @@ const DEFAULT_DB_NAME = "my-fireproof-db"; * @returns {State} */ const update = (state, msg) => { - console.log(msg.type) + console.log(msg.type); switch (msg.type) { - case "CLAIM_ALL_SHARES": return { ...state, shareClaims: "loading" } - case "CLAIMED_SHARES": return { ...state, shareClaims: msg.delegations } + case "CLAIM_ALL_SHARES": + return { ...state, shareClaims: "loading" }; + + case "CLAIMED_SHARES": + return { ...state, shareClaims: msg.delegations }; + + case "CONNECT": + return { ...state, databaseContents: "loading", shareStatus: undefined }; - case "CONNECT": return { ...state, databaseContents: "loading", shareStatus: undefined } - case "CONNECTED": return { ...state, database: msg.database } - case "SET_CLOCK": return { ...state, clock: msg.clock } + case "CONNECTED": + return { + ...state, + database: msg.database, + databaseSubscriptions: [msg.disconnect], + }; + + case "SET_CLOCK": + return { ...state, clock: msg.clock }; case "SET_CLOCK_ID_INPUT": { const val = msg.clockId.trim(); - const clockIdInput = val.match(/did\:key\:.+/) ? /** @type {`did:key:${string}`} */ (val) : undefined + const clockIdInput = val.match(/did\:key\:.+/) ? /** @type {`did:key:${string}`} */ (val) : undefined; return { ...state, clockIdInput }; } - case "SET_DATABASE_CONTENTS": { + case "SET_DATABASE_CONTENTS": return { ...state, databaseContents: msg.contents }; - } case "SET_EMAIL": { - const val = msg.email.trim() - const email = val.length && val.includes("@") ? /** @type {`${string}@${string}`} */ (val) : undefined + const val = msg.email.trim(); + const email = val.length && val.includes("@") ? /** @type {`${string}@${string}`} */ (val) : undefined; - return { ...state, email } + return { ...state, email }; } - case "SET_LOGGED_IN": return { ...state, loggedIn: msg.loggedIn } - case "SET_SERVER": return { ...state, server: msg.server } + case "SET_LOGGED_IN": + return { ...state, loggedIn: msg.loggedIn }; + + case "SET_SERVER": + return { ...state, server: msg.server }; case "SET_SERVER_INPUT": { - const val = msg.server.trim() - const serverInput = val.length && val.match(/https?\:\/\//) ? val : undefined + const val = msg.server.trim(); + const serverInput = val.length && val.match(/https?\:\/\//) ? val : undefined; - return { ...state, serverInput } + return { ...state, serverInput }; } - case "SHARE_WITH_EMAIL": { - return { ...state, shareStatus: { type: "LOADING" } } - } + case "SHARE_WITH_EMAIL": + return { ...state, shareStatus: { type: "LOADING" } }; - case "SHARED_WITH_EMAIL": { - return { ...state, shareStatus: { type: "SHARED", cid: msg.cid, email: msg.email } } - } + case "SHARED_WITH_EMAIL": + return { ...state, shareStatus: { type: "SHARED", cid: msg.cid, email: msg.email } }; - case "WAIT_FOR_LOGIN": return { ...state, loggedIn: "in-progress" } + case "WAIT_FOR_LOGIN": + return { ...state, loggedIn: "in-progress" }; default: return state; @@ -91,17 +104,17 @@ const fx = (msg) => { case "CLAIM_ALL_SHARES": return [claimAllShares]; case "CONNECT": - return [connect] + return [connect]; case "CONNECTED": - return [fetchDbContents] + return [fetchDbContents]; case "DATABASE_CONTENTS_CHANGED": - return [fetchDbContents] + return [fetchDbContents]; case "LOGIN": return [login]; case "SET_AGENT": return [determineClock]; case "SET_CLOCK": - return [connect, saveConfig] + return [connect, saveConfig]; case "SET_CLOCK_ID_INPUT": return [determineClock]; case "SET_EMAIL": @@ -113,9 +126,9 @@ const fx = (msg) => { case "SET_SERVER_INPUT": return [determineServer]; case "SHARE_WITH_EMAIL": - return [shareWithEmail(msg.email)] + return [shareWithEmail(msg.email)]; case "WAIT_FOR_LOGIN": - return [waitForLogin(msg.promise)] + return [waitForLogin(msg.promise)]; default: return []; } @@ -128,52 +141,62 @@ const fx = (msg) => { function checkLoginStatusIfServerChanged(server) { /** @returns Promise */ return async () => { - const s = state() + const s = state(); if (server.id.did() === s.server.id.did()) { - return /** @type {Msg} */({ type: "-" }) + return /** @type {Msg} */ ({ type: "-" }); } - const loggedIn = s.email - ? await UCAN.isLoggedIn({ agent: s.agent, email: UCAN.email(s.email) }) - : false + const loggedIn = s.email ? await UCAN.isLoggedIn({ agent: s.agent, email: UCAN.email(s.email) }) : false; - return /** @type {Msg} */({ type: "SET_LOGGED_IN", loggedIn }) - } + return /** @type {Msg} */ ({ type: "SET_LOGGED_IN", loggedIn }); + }; } /** @returns {Promise} */ async function claimAllShares() { - const email = state().email - if (!email) throw new Error("Cannot claim shares if not logged in") + const email = state().email; + if (!email) throw new Error("Cannot claim shares if not logged in"); - const { agent, server } = state() - const delegations = await UCAN.claimShares({ email: UCAN.email(email) }, { agent, server }) + const { agent, server } = state(); + const delegations = await UCAN.claimShares({ email: UCAN.email(email) }, { agent, server }); - return { type: "CLAIMED_SHARES", delegations } + return { type: "CLAIMED_SHARES", delegations }; } /** @returns {Promise} */ async function connect() { - const { agent, clock, email, loggedIn, server } = state() + const { agent, clock, databaseSubscriptions, email, loggedIn, server } = state(); + const existingDatabase = state().database; + + if (existingDatabase) { + await existingDatabase.close(); + } + + databaseSubscriptions.forEach((callback) => callback()); - const database = fireproof(clock.id.did()) + const database = fireproof(clock.id.did()); if (!email || (email && loggedIn)) { await UCAN.connect(database, { agent, clock, server, - email: email && loggedIn ? UCAN.email(email) : undefined - }) + email: email && loggedIn ? UCAN.email(email) : undefined, + poll: true, + }); } - return { type: "CONNECTED", database } + const disconnect = database.subscribe(() => { + send({ type: "DATABASE_CONTENTS_CHANGED" }); + }); + + return { type: "CONNECTED", database, disconnect }; } /** @returns {Promise} */ async function determineAgent() { - const { server } = state() + const { server } = state(); const agent = await UCAN.agent({ server }); return { type: "SET_AGENT", agent }; @@ -188,7 +211,7 @@ async function determineClock() { : await UCAN.clock({ audience: email ? UCAN.email(email) : agent.agent }); if (clock.isNew && email) { - await UCAN.registerClock({ clock, server }) + await UCAN.registerClock({ clock, server }); } return { type: "SET_CLOCK", clock }; @@ -196,40 +219,40 @@ async function determineClock() { /** @returns {Promise} */ async function determineServer() { - const { serverInput } = state() - const server = await UCAN.server(serverInput) + const { serverInput } = state(); + const server = await UCAN.server(serverInput); return { type: "SET_SERVER", server }; } /** @returns {Promise} */ async function fetchDbContents() { - const db = state().database - if (!db) return { type: "-" } + const db = state().database; + if (!db) return { type: "-" }; /** @type {AllDocsResponse<{ text: string }>} */ const docs = await db.allDocs(); /** @type {[string, string][]} */ - const contents = docs.rows.map(row => { - return [row.value._id, row.value.text] - }) + const contents = docs.rows.map((row) => { + return [row.value._id, row.value.text]; + }); - return { type: "SET_DATABASE_CONTENTS", contents: new Map(contents) } + return { type: "SET_DATABASE_CONTENTS", contents: new Map(contents) }; } /** @returns {Promise} */ async function login() { - const { agent, email } = state() + const { agent, email } = state(); - if (!email) return { type: "-" } + if (!email) return { type: "-" }; const promise = UCAN.login({ agent, - email: UCAN.email(email) - }) + email: UCAN.email(email), + }); - return { type: "WAIT_FOR_LOGIN", promise } + return { type: "WAIT_FOR_LOGIN", promise }; } /** @returns {Msg} */ @@ -252,29 +275,34 @@ function saveConfig() { function shareWithEmail(toEmail) { /** @returns {Promise} */ return async () => { - const { agent, clock, email, server } = state() - - if (!email) throw new Error("Expected `state.email` to be defined.") - if (!("storeName" in clock)) throw new Error("Expected a clock delegation to be present.") - - const { cid } = await UCAN.share({ - from: UCAN.email(email), - to: UCAN.email(toEmail) - }, { - agent, clock, server, - }) + const { agent, clock, email, server } = state(); + + if (!email) throw new Error("Expected `state.email` to be defined."); + if (!("storeName" in clock)) throw new Error("Expected a clock delegation to be present."); + + const { cid } = await UCAN.share( + { + from: UCAN.email(email), + to: UCAN.email(toEmail), + }, + { + agent, + clock, + server, + } + ); return { type: "SHARED_WITH_EMAIL", cid, email: toEmail }; - } + }; } /** @param {Promise} promise */ function waitForLogin(promise) { /** @returns {Promise} */ return async () => { - await promise - return { type: "SET_LOGGED_IN", loggedIn: true } - } + await promise; + return { type: "SET_LOGGED_IN", loggedIn: true }; + }; } // Setup @@ -288,7 +316,7 @@ const config = storedState ? JSON.parse(storedState) : undefined; /** @type {State} */ const initialState = await (async () => { const server = await UCAN.server(config?.server).catch(async () => { - return await UCAN.server() + return await UCAN.server(); }); const agent = await UCAN.agent({ server }); @@ -296,7 +324,7 @@ const initialState = await (async () => { const clock = config?.clockId ? UCAN.clockId(config.clockId) : await UCAN.clock({ audience: email || agent.agent }); if (clock.isNew && email) { - await UCAN.registerClock({ clock, server }) + await UCAN.registerClock({ clock, server }); } return { @@ -304,12 +332,13 @@ const initialState = await (async () => { clock, clockIdInput: config?.clockId, databaseContents: "loading", + databaseSubscriptions: [], loggedIn: email ? await UCAN.isLoggedIn({ agent, email }) : false, server, serverInput: server.id.did() !== (await UCAN.server()).id.did() ? server.uri.toString() : undefined, - email: config?.email - } -})() + email: config?.email, + }; +})(); // Setup & export store export const [state, send] = store({ @@ -319,4 +348,4 @@ export const [state, send] = store({ }); // Setup database & connect -send({ type: "CONNECT" }) +send({ type: "CONNECT" }); diff --git a/examples/ucan/browser/src/types.d.ts b/examples/ucan/browser/src/types.d.ts index d8bf5b50..4d4579fb 100644 --- a/examples/ucan/browser/src/types.d.ts +++ b/examples/ucan/browser/src/types.d.ts @@ -7,15 +7,16 @@ import { Delegation } from "@ucanto/interface"; export type State = { agent: AgentWithStoreName; clock: Clock | ClockWithoutDelegation; - clockIdInput?: `did:key:${string}` - database?: Database - databaseContents: Map | "loading" - email?: `${string}@${string}` - loggedIn: boolean | "in-progress" - server: Server - serverInput?: string - shareClaims?: Delegation[] | "loading" - shareStatus?: { type: "SHARED"; cid: string; email: `${string}@${string}` } | { type: "LOADING" } + clockIdInput?: `did:key:${string}`; + database?: Database; + databaseContents: Map | "loading"; + databaseSubscriptions: Array<() => void>; + email?: `${string}@${string}`; + loggedIn: boolean | "in-progress"; + server: Server; + serverInput?: string; + shareClaims?: Delegation[] | "loading"; + shareStatus?: { type: "SHARED"; cid: string; email: `${string}@${string}` } | { type: "LOADING" }; }; // 📣 @@ -23,9 +24,9 @@ export type State = { export type Msg = | { type: "-" } | { type: "CLAIM_ALL_SHARES" } - | { type: "CLAIMED_SHARES", delegations: Delegation[] } + | { type: "CLAIMED_SHARES"; delegations: Delegation[] } | { type: "CONNECT" } - | { type: "CONNECTED"; database: Database } + | { type: "CONNECTED"; database: Database; disconnect: () => void } | { type: "LOGIN" } | { type: "DATABASE_CONTENTS_CHANGED" } | { type: "SET_AGENT"; agent: AgentWithStoreName } diff --git a/examples/ucan/browser/src/view.js b/examples/ucan/browser/src/view.js index 077d1d1b..623092c7 100644 --- a/examples/ucan/browser/src/view.js +++ b/examples/ucan/browser/src/view.js @@ -103,86 +103,86 @@ const Clock = () => // CLAIM SHARE -const ClaimShare = () => section({}, [ +const ClaimShare = () => + section({}, [ + // Header + hgroup({}, [ + h2({}, text("Claim share")), + p({}, [small({}, [span({}, text("Retrieve the UCAN delegation for a share."))])]), + ]), - // Header - hgroup({}, [ - h2({}, text("Claim share")), + // Buttons p({}, [ - small({}, [ - span({}, text("Retrieve the UCAN delegation for a share.")), - ]), + button( + { + onclick: () => { + const { loggedIn } = state(); + + if (loggedIn !== true) { + alert("Need to be logged in first before you can claim shares."); + return; + } + + send({ type: "CLAIM_ALL_SHARES" }); + }, + }, + text("Claim all shares") + ), ]), - ]), - // Buttons - p({}, [ - button({ - onclick: () => { - const { loggedIn } = state() + // Delegations + div({}, (element) => { + const signal = computed(() => { + const { shareClaims } = state(); + if (!shareClaims) return span({}, []); + if (shareClaims === "loading") return p({}, [small({ ariaBusy: "true" }, text("Loading delegations"))]); + + console.log( + shareClaims.map((d) => { + return { + iss: d.issuer.did(), + aud: d.audience.did(), + caps: JSON.stringify(d.capabilities), + }; + }) + ); + + const clockDIDs = shareClaims.flatMap((d) => { + const cap = d.capabilities[0]; + if (cap.can === "clock/*") return [cap.with]; + return []; + }); + + if (clockDIDs.length === 0) return p({}, text("No shares found.")); + const activeClock = state().clock.id.did(); - if (loggedIn !== true) { - alert("Need to be logged in first before you can claim shares.") - return - } + return div({}, [ + p({}, text("Available databases:")), + ul( + {}, + clockDIDs.map((did) => { + return li({}, [ + a( + { + style: "cursor: pointer; word-break: break-all;", + title: "Click to use database", + onclick: () => { + send({ type: "SET_CLOCK_ID_INPUT", clockId: did }); + }, + }, + text(did === activeClock ? `⚡ ${did} (active)` : did) + ), + ]); + }) + ), + ]); + }); - send({ type: "CLAIM_ALL_SHARES" }) - } - }, text("Claim all shares")) - ]), - - // Delegations - div({}, element => { - const signal = computed(() => { - const { shareClaims } = state() - if (!shareClaims) return span({}, []) - if (shareClaims === "loading") return p({}, [ - small({ ariaBusy: "true" }, text("Loading delegations")) - ]) - - console.log(shareClaims.map(d => { - return { - iss: d.issuer.did(), - aud: d.audience.did(), - caps: JSON.stringify(d.capabilities) - } - })) - - const clockDIDs = shareClaims.flatMap(d => { - const cap = d.capabilities[0] - if (cap.can === "clock/*") return [ cap.with ] - return [] - }) - - if (clockDIDs.length === 0) return p({}, text("No shares found.")) - const activeClock = state().clock.id.did() - - return div({}, [ - p({}, text("Available databases:")), - ul({}, clockDIDs.map(did => { - return li({}, [ - a({ - style: "cursor: pointer; word-break: break-all;", - title: "Click to use database", - onclick: () => { - send({ type: "SET_CLOCK_ID_INPUT", clockId: did }) - } - }, text( - did === activeClock - ? `⚡ ${did} (active)` - : did - )) - ]) - })) - ]) - }) - - return effect(() => { - element.replaceChildren(signal()) - }) - }) - -]) + return effect(() => { + element.replaceChildren(signal()); + }); + }), + ]); // DATABASE DATA @@ -192,71 +192,73 @@ const Data = () => hgroup({}, [h2({}, text("Database contents"))]), // Add data - form({ - - /** - * @param event {Event & { target: HTMLElement }} - */ - onsubmit: async (event) => { - event.preventDefault() - - const db = state().database - const form = event.target - - if (!db || !form) return - - const input = /** @type {HTMLInputElement | null} */ (event.target.querySelector('input[name="data"]')) - const val = input && input.value.trim() - if (val && val.length) await db.put({ text: val }) - - send({ type: "DATABASE_CONTENTS_CHANGED" }) - if (input) input.value = "" - } - - }, [ - Label({ for: "data" }, "Add data"), - fieldset({ role: "group" }, [ - input( - { - "aria-label": "Add data", - name: "data", - type: "text", - required: true - }, - [] - ), - input( - { - value: "Add", - type: "submit" - }, - [] - ), - ]), - ]), + form( + { + /** + * @param event {Event & { target: HTMLElement }} + */ + onsubmit: async (event) => { + event.preventDefault(); + + const db = state().database; + const form = event.target; + + if (!db || !form) return; + + const input = /** @type {HTMLInputElement | null} */ (event.target.querySelector('input[name="data"]')); + const val = input && input.value.trim(); + if (val && val.length) await db.put({ text: val }); + + send({ type: "DATABASE_CONTENTS_CHANGED" }); + if (input) input.value = ""; + }, + }, + [ + Label({ for: "data" }, "Add data"), + fieldset({ role: "group" }, [ + input( + { + "aria-label": "Add data", + name: "data", + type: "text", + required: true, + }, + [] + ), + input( + { + value: "Add", + type: "submit", + }, + [] + ), + ]), + ] + ), // Contents - div({}, element => { + div({}, (element) => { const signal = computed(() => { - const contents = state().databaseContents + const contents = state().databaseContents; if (contents === "loading") { - return p({}, [ - small({ ariaBusy: "true" }, text("Loading database contents")) - ]) + return p({}, [small({ ariaBusy: "true" }, text("Loading database contents"))]); } - return ul({}, repeat( - computed(() => contents), - row => li({}, text(row)) - )) - }) + return ul( + {}, + repeat( + computed(() => contents), + (row) => li({}, text(row)) + ) + ); + }); return effect(() => { - element.replaceChildren(signal()) - }) - }) - ]) + element.replaceChildren(signal()); + }); + }), + ]); // DATABASE NAME @@ -286,60 +288,52 @@ const Email = () => form({ onsubmit: preventDefault }, [ fieldset({}, [ Label({ for: "email" }, "Email address"), - input({ - "aria-label": "Email address", - autocomplete: "email", - name: "email", - type: "email", - - value: state().email || "", - - /** - * @param event {object} - * @param event.target {HTMLInputElement} - */ - onchange: (event) => send({ type: "SET_EMAIL", email: event.target.value }), - }, []), + input( + { + "aria-label": "Email address", + autocomplete: "email", + name: "email", + type: "email", + + value: state().email || "", + + /** + * @param event {object} + * @param event.target {HTMLInputElement} + */ + onchange: (event) => send({ type: "SET_EMAIL", email: event.target.value }), + }, + [] + ), ]), ]), // Logged in - div({}, element => { + div({}, (element) => { const signal = computed(() => { - const { email, loggedIn } = state() + const { email, loggedIn } = state(); if (email === undefined) { - return div({}, [ - Label({}, "No login needed when not using an email address"), - p({}, [ span({}, text("☑️")) ]) - ]) + return div({}, [Label({}, "No login needed when not using an email address"), p({}, [span({}, text("☑️"))])]); } if (loggedIn === true) { - return div({}, [ - Label({}, "Logged in successfully"), - p({}, [ span({}, text("☑️")) ]) - ]) + return div({}, [Label({}, "Logged in successfully"), p({}, [span({}, text("☑️"))])]); } if (loggedIn === "in-progress") { - return div({}, [ - Label({}, "Logging in ..."), - p({}, [ span({}, text("Check your email inbox ⚡")) ]) - ]) + return div({}, [Label({}, "Logging in ..."), p({}, [span({}, text("Check your email inbox ⚡"))])]); } return div({}, [ Label({}, "Login required"), - p({}, [ - button({ onclick: () => send({ type: "LOGIN" }) }, text("Log in")) - ]) - ]) - }) + p({}, [button({ onclick: () => send({ type: "LOGIN" }) }, text("Log in"))]), + ]); + }); return effect(() => { - element.replaceChildren(signal()) - }) + element.replaceChildren(signal()); + }); }), // Using @@ -370,20 +364,23 @@ const Server = () => form({ onsubmit: preventDefault }, [ fieldset({}, [ Label({ for: "server" }, "Custom server URL"), - input({ - "aria-label": "Custom server URL", - autocomplete: "url", - name: "server", - type: "text", - - value: state().serverInput || "", - - /** - * @param event {object} - * @param event.target {HTMLInputElement} - */ - onchange: (event) => send({ type: "SET_SERVER_INPUT", server: event.target.value }), - }, []), + input( + { + "aria-label": "Custom server URL", + autocomplete: "url", + name: "server", + type: "text", + + value: state().serverInput || "", + + /** + * @param event {object} + * @param event.target {HTMLInputElement} + */ + onchange: (event) => send({ type: "SET_SERVER_INPUT", server: event.target.value }), + }, + [] + ), ]), ]), @@ -396,78 +393,84 @@ const Server = () => export const Share = () => section({}, [ - // Header hgroup({}, [ h2({}, text("Share")), p({}, [ small({}, [ - span({}, text("Share the database with an email address. Note that sharing with a specific agent is possible too, but not enabled here.")), + span( + {}, + text( + "Share the database with an email address. Note that sharing with a specific agent is possible too, but not enabled here." + ) + ), ]), ]), ]), // Form - form({ - - /** - * @param event {Event & { target: HTMLElement }} - */ - onsubmit: async (event) => { - event.preventDefault() - - const { loggedIn } = state() - - if (loggedIn !== true) { - alert("Need to be logged in first before you can share.") - return - } - - const form = event.target - if (!form) return - - const input = /** @type {HTMLInputElement | null} */ (event.target.querySelector('input[name="shareTarget"]')) - const val = input?.value?.trim() - if (val && val.length) { - send({ type: "SHARE_WITH_EMAIL", email: /** @type {`${string}@${string}`} */ (val) }) - if (input) input.value = "" - } - } - - }, [ - Label({ for: "shareTarget" }, "Email address"), - fieldset({ role: "group" }, [ - input( - { - "aria-label": "Email address", - name: "shareTarget", - type: "email", - required: true - }, - [] - ), - input( - { - value: "Share", - type: "submit" - }, - [] - ), - ]), - ]), + form( + { + /** + * @param event {Event & { target: HTMLElement }} + */ + onsubmit: async (event) => { + event.preventDefault(); + + const { loggedIn } = state(); + + if (loggedIn !== true) { + alert("Need to be logged in first before you can share."); + return; + } + + const form = event.target; + if (!form) return; + + const input = /** @type {HTMLInputElement | null} */ ( + event.target.querySelector('input[name="shareTarget"]') + ); + const val = input?.value?.trim(); + if (val && val.length) { + send({ type: "SHARE_WITH_EMAIL", email: /** @type {`${string}@${string}`} */ (val) }); + if (input) input.value = ""; + } + }, + }, + [ + Label({ for: "shareTarget" }, "Email address"), + fieldset({ role: "group" }, [ + input( + { + "aria-label": "Email address", + name: "shareTarget", + type: "email", + required: true, + }, + [] + ), + input( + { + value: "Share", + type: "submit", + }, + [] + ), + ]), + ] + ), // Status - p({}, element => { + p({}, (element) => { const signal = computed(() => { - const {email, shareStatus} = state() - if (shareStatus === undefined) return span({}, []) + const { email, shareStatus } = state(); + if (shareStatus === undefined) return span({}, []); switch (shareStatus.type) { - case "LOADING": return p({}, [ - small({ ariaBusy: "true" }, text("Creating share delegation and invoking share authorization")) - ]) + small({ ariaBusy: "true" }, text("Creating share delegation and invoking share authorization")), + ]); case "SHARED": return p({}, [ @@ -479,17 +482,15 @@ export const Share = () => mark({}, text(shareStatus.cid)), br({}), span({}, text(`Check your email inbox (${email}) to confirm the share.`)), - ]) - ]) - + ]), + ]); } - }) + }); return effect(() => { - element.replaceChildren(signal()) - }) - }) - + element.replaceChildren(signal()); + }); + }), ]); // 🔮 @@ -503,4 +504,20 @@ export const Header = () => ]); export const Main = () => - main({ className: "container" }, [Data(), hr(), ClaimShare(), hr(), Share(), hr(), Clock(), hr(), Email(), hr(), Agent(), hr(), Server(), hr(), Database()]); + main({ className: "container" }, [ + Data(), + hr(), + ClaimShare(), + hr(), + Share(), + hr(), + Clock(), + hr(), + Email(), + hr(), + Agent(), + hr(), + Server(), + hr(), + Database(), + ]); diff --git a/examples/ucan/node/package.json b/examples/ucan/node/package.json index 39f60562..84357c70 100644 --- a/examples/ucan/node/package.json +++ b/examples/ucan/node/package.json @@ -3,7 +3,7 @@ "type": "module", "dependencies": { "@fireproof/connect": "../../../", - "@fireproof/core": "0.19.113", + "@fireproof/core": "0.19.116", "meow": "^13.2.0" } } diff --git a/examples/ucan/workshop/participants/package.json b/examples/ucan/workshop/participants/package.json index 45740c7a..25c441bd 100644 --- a/examples/ucan/workshop/participants/package.json +++ b/examples/ucan/workshop/participants/package.json @@ -2,7 +2,7 @@ "private": true, "type": "module", "dependencies": { - "@fireproof/core": "0.19.113", + "@fireproof/core": "0.19.116", "@fireproof/ucan": "../../../../dist/ucan", "multiformats": "^13.3.1" } diff --git a/examples/ucan/workshop/team/package.json b/examples/ucan/workshop/team/package.json index 35744adf..0dd6a9d1 100644 --- a/examples/ucan/workshop/team/package.json +++ b/examples/ucan/workshop/team/package.json @@ -7,7 +7,7 @@ "preview": "rsbuild preview" }, "dependencies": { - "@fireproof/core": "0.19.113", + "@fireproof/core": "0.19.116", "@fireproof/ucan": "../../../../dist/ucan", "@picocss/pico": "^2.0.6", "@ucanto/core": "^10.0.1", diff --git a/src/ucan/ucan-gateway.ts b/src/ucan/ucan-gateway.ts index 27a9a704..5c907789 100644 --- a/src/ucan/ucan-gateway.ts +++ b/src/ucan/ucan-gateway.ts @@ -309,7 +309,7 @@ export class UCANGateway implements bs.Gateway { // Setup polling url = url.build().setParam("key", "main").URI(); - const interval = 3000; + const interval = 10000; let lastData: Uint8Array | undefined = undefined; const fetchData = async () => { From 47936f8a44d2461fc83de30f3478be1ecb743fa4 Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Tue, 17 Dec 2024 13:07:41 +0100 Subject: [PATCH 59/83] chore: Rename ucan browser example to control-panel --- examples/ucan/{browser => control-panel}/README.md | 0 examples/ucan/{browser => control-panel}/eslint.config.js | 0 examples/ucan/{browser => control-panel}/package.json | 0 examples/ucan/{browser => control-panel}/pnpm-lock.yaml | 0 examples/ucan/{browser => control-panel}/rsbuild.config.js | 0 examples/ucan/{browser => control-panel}/src/index.css | 0 examples/ucan/{browser => control-panel}/src/index.html | 0 examples/ucan/{browser => control-panel}/src/index.js | 0 examples/ucan/{browser => control-panel}/src/state.js | 0 examples/ucan/{browser => control-panel}/src/types.d.ts | 0 examples/ucan/{browser => control-panel}/src/view.js | 0 examples/ucan/{browser => control-panel}/tsconfig.json | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename examples/ucan/{browser => control-panel}/README.md (100%) rename examples/ucan/{browser => control-panel}/eslint.config.js (100%) rename examples/ucan/{browser => control-panel}/package.json (100%) rename examples/ucan/{browser => control-panel}/pnpm-lock.yaml (100%) rename examples/ucan/{browser => control-panel}/rsbuild.config.js (100%) rename examples/ucan/{browser => control-panel}/src/index.css (100%) rename examples/ucan/{browser => control-panel}/src/index.html (100%) rename examples/ucan/{browser => control-panel}/src/index.js (100%) rename examples/ucan/{browser => control-panel}/src/state.js (100%) rename examples/ucan/{browser => control-panel}/src/types.d.ts (100%) rename examples/ucan/{browser => control-panel}/src/view.js (100%) rename examples/ucan/{browser => control-panel}/tsconfig.json (100%) diff --git a/examples/ucan/browser/README.md b/examples/ucan/control-panel/README.md similarity index 100% rename from examples/ucan/browser/README.md rename to examples/ucan/control-panel/README.md diff --git a/examples/ucan/browser/eslint.config.js b/examples/ucan/control-panel/eslint.config.js similarity index 100% rename from examples/ucan/browser/eslint.config.js rename to examples/ucan/control-panel/eslint.config.js diff --git a/examples/ucan/browser/package.json b/examples/ucan/control-panel/package.json similarity index 100% rename from examples/ucan/browser/package.json rename to examples/ucan/control-panel/package.json diff --git a/examples/ucan/browser/pnpm-lock.yaml b/examples/ucan/control-panel/pnpm-lock.yaml similarity index 100% rename from examples/ucan/browser/pnpm-lock.yaml rename to examples/ucan/control-panel/pnpm-lock.yaml diff --git a/examples/ucan/browser/rsbuild.config.js b/examples/ucan/control-panel/rsbuild.config.js similarity index 100% rename from examples/ucan/browser/rsbuild.config.js rename to examples/ucan/control-panel/rsbuild.config.js diff --git a/examples/ucan/browser/src/index.css b/examples/ucan/control-panel/src/index.css similarity index 100% rename from examples/ucan/browser/src/index.css rename to examples/ucan/control-panel/src/index.css diff --git a/examples/ucan/browser/src/index.html b/examples/ucan/control-panel/src/index.html similarity index 100% rename from examples/ucan/browser/src/index.html rename to examples/ucan/control-panel/src/index.html diff --git a/examples/ucan/browser/src/index.js b/examples/ucan/control-panel/src/index.js similarity index 100% rename from examples/ucan/browser/src/index.js rename to examples/ucan/control-panel/src/index.js diff --git a/examples/ucan/browser/src/state.js b/examples/ucan/control-panel/src/state.js similarity index 100% rename from examples/ucan/browser/src/state.js rename to examples/ucan/control-panel/src/state.js diff --git a/examples/ucan/browser/src/types.d.ts b/examples/ucan/control-panel/src/types.d.ts similarity index 100% rename from examples/ucan/browser/src/types.d.ts rename to examples/ucan/control-panel/src/types.d.ts diff --git a/examples/ucan/browser/src/view.js b/examples/ucan/control-panel/src/view.js similarity index 100% rename from examples/ucan/browser/src/view.js rename to examples/ucan/control-panel/src/view.js diff --git a/examples/ucan/browser/tsconfig.json b/examples/ucan/control-panel/tsconfig.json similarity index 100% rename from examples/ucan/browser/tsconfig.json rename to examples/ucan/control-panel/tsconfig.json From f6965294a8750074b372d6838be0ff0e2b7e53f6 Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Tue, 17 Dec 2024 13:08:52 +0100 Subject: [PATCH 60/83] chore: Remove console.logs from ucan connector --- src/ucan/ucan-gateway.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ucan/ucan-gateway.ts b/src/ucan/ucan-gateway.ts index 5c907789..c3ee9ca8 100644 --- a/src/ucan/ucan-gateway.ts +++ b/src/ucan/ucan-gateway.ts @@ -138,7 +138,6 @@ export class UCANGateway implements bs.Gateway { } this.logger.Debug().Str("store", store).Str("key", key).Msg("put"); - console.log("🏗️ PUT", store); switch (store.toLowerCase()) { case "data": { @@ -222,7 +221,6 @@ export class UCANGateway implements bs.Gateway { } this.logger.Debug().Str("store", store).Str("key", key).Msg("get"); - console.log("🔮 GET", store); switch (store.toLowerCase()) { case "data": { @@ -250,7 +248,6 @@ export class UCANGateway implements bs.Gateway { }); this.logger.Debug().Any("head", head.out).Msg("Meta (head) retrieved"); - console.log(head.out); if (head.out.error) throw head.out.error; if (head.out.ok.head === undefined) throw new NotFoundError(); From 53f88a4e365f8be2dd1488a96ca6f255e16d4ae2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:19:28 +0000 Subject: [PATCH 61/83] chore(deps): bump cross-fetch from 4.0.0 to 4.1.0 Bumps [cross-fetch](https://github.com/lquixada/cross-fetch) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/lquixada/cross-fetch/releases) - [Changelog](https://github.com/lquixada/cross-fetch/blob/v4.x/CHANGELOG.md) - [Commits](https://github.com/lquixada/cross-fetch/compare/v4.0.0...v4.1.0) --- updated-dependencies: - dependency-name: cross-fetch dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 1 - pnpm-lock.yaml | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/package.json b/package.json index 8492b1f1..eac8533d 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,6 @@ "aws4fetch": "^1.0.20", "better-sqlite3": "^11.7.0", "cmd-ts": "^0.13.0", - "cross-fetch": "^4.0.0", "dotenv": "^16.4.5", "events": "^3.3.0", "hono": "^4.6.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b944a3a6..19731537 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,9 +89,6 @@ importers: cmd-ts: specifier: ^0.13.0 version: 0.13.0 - cross-fetch: - specifier: ^4.0.0 - version: 4.0.0(encoding@0.1.13) dotenv: specifier: ^16.4.5 version: 16.4.7 @@ -2049,9 +2046,6 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cross-fetch@4.0.0: - resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -6356,12 +6350,6 @@ snapshots: cookie@0.7.2: {} - cross-fetch@4.0.0(encoding@0.1.13): - dependencies: - node-fetch: 2.7.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 From 4f1fa0a82f0d66a7bd7b71e40bd9db05d0fc6fc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:19:15 +0000 Subject: [PATCH 62/83] chore(deps-dev): bump wrangler from 3.95.0 to 3.99.0 Bumps [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) from 3.95.0 to 3.99.0. - [Release notes](https://github.com/cloudflare/workers-sdk/releases) - [Changelog](https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/CHANGELOG.md) - [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@3.99.0/packages/wrangler) --- updated-dependencies: - dependency-name: wrangler dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 108 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 91 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index eac8533d..a517551f 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", "wait-on": "^8.0.1", - "wrangler": "^3.95.0", + "wrangler": "^3.99.0", "ws": "^8.18.0", "vitest": "^2.1.8", "zx": "^8.2.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19731537..dace91dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,8 +205,8 @@ importers: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.2) wrangler: - specifier: ^3.95.0 - version: 3.95.0(@cloudflare/workers-types@4.20241205.0) + specifier: ^3.99.0 + version: 3.99.0(@cloudflare/workers-types@4.20241205.0) ws: specifier: ^8.18.0 version: 8.18.0 @@ -406,6 +406,12 @@ packages: cpu: [x64] os: [darwin] + '@cloudflare/workerd-darwin-64@1.20241218.0': + resolution: {integrity: sha512-8rveQoxtUvlmORKqTWgjv2ycM8uqWox0u9evn3zd2iWKdou5sncFwH517ZRLI3rq9P31ZLmCQBZ0gloFsTeY6w==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + '@cloudflare/workerd-darwin-arm64@1.20240718.0': resolution: {integrity: sha512-nlr4gaOO5gcJerILJQph3+2rnas/nx/lYsuaot1ntHu4LAPBoQo1q/Pucj2cSIav4UiMzTbDmoDwPlls4Kteog==} engines: {node: '>=16'} @@ -418,6 +424,12 @@ packages: cpu: [arm64] os: [darwin] + '@cloudflare/workerd-darwin-arm64@1.20241218.0': + resolution: {integrity: sha512-be59Ad9nmM9lCkhHqmTs/uZ3JVZt8NJ9Z0PY+B0xnc5z6WwmV2lj0RVLtq7xJhQsQJA189zt5rXqDP6J+2mu7Q==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + '@cloudflare/workerd-linux-64@1.20240718.0': resolution: {integrity: sha512-LJ/k3y47pBcjax0ee4K+6ZRrSsqWlfU4lbU8Dn6u5tSC9yzwI4YFNXDrKWInB0vd7RT3w4Yqq1S6ZEbfRrqVUg==} engines: {node: '>=16'} @@ -430,6 +442,12 @@ packages: cpu: [x64] os: [linux] + '@cloudflare/workerd-linux-64@1.20241218.0': + resolution: {integrity: sha512-MzpSBcfZXRxrYWxQ4pVDYDrUbkQuM62ssl4ZtHH8J35OAeGsWFAYji6MkS2SpVwVcvacPwJXIF4JSzp4xKImKw==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + '@cloudflare/workerd-linux-arm64@1.20240718.0': resolution: {integrity: sha512-zBEZvy88EcAMGRGfuVtS00Yl7lJdUM9sH7i651OoL+q0Plv9kphlCC0REQPwzxrEYT1qibSYtWcD9IxQGgx2/g==} engines: {node: '>=16'} @@ -442,6 +460,12 @@ packages: cpu: [arm64] os: [linux] + '@cloudflare/workerd-linux-arm64@1.20241218.0': + resolution: {integrity: sha512-RIuJjPxpNqvwIs52vQsXeRMttvhIjgg9NLjjFa3jK8Ijnj8c3ZDru9Wqi48lJP07yDFIRr4uDMMqh/y29YQi2A==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + '@cloudflare/workerd-windows-64@1.20240718.0': resolution: {integrity: sha512-YpCRvvT47XanFum7C3SedOZKK6BfVhqmwdAAVAQFyc4gsCdegZo0JkUkdloC/jwuWlbCACOG2HTADHOqyeolzQ==} engines: {node: '>=16'} @@ -454,14 +478,16 @@ packages: cpu: [x64] os: [win32] + '@cloudflare/workerd-windows-64@1.20241218.0': + resolution: {integrity: sha512-tO1VjlvK3F6Yb2d1jgEy/QBYl//9Pyv3K0j+lq8Eu7qdfm0IgKwSRgDWLept84/qmNsQfausZ4JdNGxTf9xsxQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + '@cloudflare/workers-shared@0.10.0': resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} engines: {node: '>=16.7.0'} - '@cloudflare/workers-shared@0.11.0': - resolution: {integrity: sha512-A+lQ8xp7992qSeMmuQ0ssL6CPmm+ZmAv6Ddikan0n1jjpMAic+97l7xtVIsswSn9iLMFPYQ9uNN/8Fl0AgARIQ==} - engines: {node: '>=16.7.0'} - '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} @@ -2948,6 +2974,11 @@ packages: engines: {node: '>=16.13'} hasBin: true + miniflare@3.20241218.0: + resolution: {integrity: sha512-spYFDArH0wd+wJSTrzBrWrXJrbyJhRMJa35mat947y1jYhVV8I5V8vnD3LwjfpLr0SaEilojz1OIW7ekmnRe+w==} + engines: {node: '>=16.13'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3995,6 +4026,11 @@ packages: engines: {node: '>=16'} hasBin: true + workerd@1.20241218.0: + resolution: {integrity: sha512-7Z3D4vOVChMz9mWDffE299oQxUWm/pbkeAWx1btVamPcAK/2IuoNBhwflWo3jyuKuxvYuFAdIucgYxc8ICqXiA==} + engines: {node: '>=16'} + hasBin: true + wrangler@3.93.0: resolution: {integrity: sha512-+wfxjOrtm6YgDS+NdJkB6aiBIS3ED97mNRQmfrEShRJW4pVo4sWY6oQ1FsGT+j4tGHplrTbWCE6U5yTgjNW/lw==} engines: {node: '>=16.17.0'} @@ -4005,12 +4041,12 @@ packages: '@cloudflare/workers-types': optional: true - wrangler@3.95.0: - resolution: {integrity: sha512-3w5852i3FNyDz421K2Qk4v5L8jjwegO5O8E1+VAQmjnm82HFNxpIRUBq0bmM7CTLvOPI/Jjcmj/eAWjQBL7QYg==} + wrangler@3.99.0: + resolution: {integrity: sha512-k0x4rT3G/QCbxcoZY7CHRVlAIS8WMmKdga6lf4d2c3gXFqssh44vwlTDuARA9QANBxKJTcA7JPTJRfUDhd9QBA==} engines: {node: '>=16.17.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20241205.0 + '@cloudflare/workers-types': ^4.20241218.0 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -4613,36 +4649,46 @@ snapshots: '@cloudflare/workerd-darwin-64@1.20241205.0': optional: true + '@cloudflare/workerd-darwin-64@1.20241218.0': + optional: true + '@cloudflare/workerd-darwin-arm64@1.20240718.0': optional: true '@cloudflare/workerd-darwin-arm64@1.20241205.0': optional: true + '@cloudflare/workerd-darwin-arm64@1.20241218.0': + optional: true + '@cloudflare/workerd-linux-64@1.20240718.0': optional: true '@cloudflare/workerd-linux-64@1.20241205.0': optional: true + '@cloudflare/workerd-linux-64@1.20241218.0': + optional: true + '@cloudflare/workerd-linux-arm64@1.20240718.0': optional: true '@cloudflare/workerd-linux-arm64@1.20241205.0': optional: true + '@cloudflare/workerd-linux-arm64@1.20241218.0': + optional: true + '@cloudflare/workerd-windows-64@1.20240718.0': optional: true '@cloudflare/workerd-windows-64@1.20241205.0': optional: true - '@cloudflare/workers-shared@0.10.0': - dependencies: - mime: 3.0.0 - zod: 3.23.8 + '@cloudflare/workerd-windows-64@1.20241218.0': + optional: true - '@cloudflare/workers-shared@0.11.0': + '@cloudflare/workers-shared@0.10.0': dependencies: mime: 3.0.0 zod: 3.23.8 @@ -7459,6 +7505,25 @@ snapshots: - supports-color - utf-8-validate + miniflare@3.20241218.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.4 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20241218.0 + ws: 8.18.0 + youch: 3.3.4 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -8551,6 +8616,14 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241205.0 '@cloudflare/workerd-windows-64': 1.20241205.0 + workerd@1.20241218.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20241218.0 + '@cloudflare/workerd-darwin-arm64': 1.20241218.0 + '@cloudflare/workerd-linux-64': 1.20241218.0 + '@cloudflare/workerd-linux-arm64': 1.20241218.0 + '@cloudflare/workerd-windows-64': 1.20241218.0 + wrangler@3.93.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -8579,10 +8652,9 @@ snapshots: - supports-color - utf-8-validate - wrangler@3.95.0(@cloudflare/workers-types@4.20241205.0): + wrangler@3.99.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 - '@cloudflare/workers-shared': 0.11.0 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) blake3-wasm: 2.1.5 @@ -8590,14 +8662,14 @@ snapshots: date-fns: 4.1.0 esbuild: 0.17.19 itty-time: 1.0.6 - miniflare: 3.20241205.0 + miniflare: 3.20241218.0 nanoid: 3.3.7 path-to-regexp: 6.3.0 resolve: 1.22.8 selfsigned: 2.4.1 source-map: 0.6.1 unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190 - workerd: 1.20241205.0 + workerd: 1.20241218.0 xxhash-wasm: 1.0.2 optionalDependencies: '@cloudflare/workers-types': 4.20241205.0 From 1cc1a3450c81501b6c51f3b1a728c84777f66774 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:19:01 +0000 Subject: [PATCH 63/83] chore(deps-dev): bump @typescript-eslint/typescript-estree Bumps [@typescript-eslint/typescript-estree](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-estree) from 8.18.0 to 8.18.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-estree/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.18.1/packages/typescript-estree) --- updated-dependencies: - dependency-name: "@typescript-eslint/typescript-estree" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a517551f..c675a3a6 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@types/node": "^22.10.2", "@types/wait-on": "^5.3.4", "@types/ws": "^8.5.13", - "@typescript-eslint/typescript-estree": "^8.18.0", + "@typescript-eslint/typescript-estree": "^8.18.1", "@web3-storage/access": "^20.1.1", "esbuild": "^0.24.0", "esbuild-plugin-replace": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dace91dc..35024058 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,8 +160,8 @@ importers: specifier: ^8.5.13 version: 8.5.13 '@typescript-eslint/typescript-estree': - specifier: ^8.18.0 - version: 8.18.0(typescript@5.7.2) + specifier: ^8.18.1 + version: 8.18.1(typescript@5.7.2) esbuild: specifier: ^0.24.0 version: 0.24.0 @@ -1666,12 +1666,22 @@ packages: resolution: {integrity: sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.18.1': + resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.18.0': resolution: {integrity: sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/typescript-estree@8.18.1': + resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/utils@8.18.0': resolution: {integrity: sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1683,6 +1693,10 @@ packages: resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.18.1': + resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ucanto/client@9.0.1': resolution: {integrity: sha512-cV8w3AnaZaYCdUmyFFICj8YhFckDoy2DvWgAzGDMkPz0WbUW4lw9Tjm4hEE8x5kiP47wYej/pHKWCcoELiU0qw==} @@ -5751,6 +5765,8 @@ snapshots: '@typescript-eslint/types@8.18.0': {} + '@typescript-eslint/types@8.18.1': {} + '@typescript-eslint/typescript-estree@8.18.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.18.0 @@ -5765,6 +5781,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.18.1(typescript@5.7.2)': + dependencies: + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/visitor-keys': 8.18.1 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.7.2) + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.18.0(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) @@ -5781,6 +5811,11 @@ snapshots: '@typescript-eslint/types': 8.18.0 eslint-visitor-keys: 4.2.0 + '@typescript-eslint/visitor-keys@8.18.1': + dependencies: + '@typescript-eslint/types': 8.18.1 + eslint-visitor-keys: 4.2.0 + '@ucanto/client@9.0.1': dependencies: '@ucanto/core': 10.0.1 From ab80b315a793302393c708e01bc214f3da43dd33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:18:44 +0000 Subject: [PATCH 64/83] chore(deps): bump @web3-storage/w3up-client from 16.5.2 to 17.1.1 Bumps [@web3-storage/w3up-client](https://github.com/storacha/w3up/tree/HEAD/packages/w3up-client) from 16.5.2 to 17.1.1. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/w3up-client/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/w3up-client-v17.1.1/packages/w3up-client) --- updated-dependencies: - dependency-name: "@web3-storage/w3up-client" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 56 +++++++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index c675a3a6..d227159c 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "@web3-storage/clock": "^0.4.1", "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", - "@web3-storage/w3up-client": "^16.5.2", + "@web3-storage/w3up-client": "^17.1.1", "assert": "^2.1.0", "aws4fetch": "^1.0.20", "better-sqlite3": "^11.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35024058..4b41f5a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,8 +75,8 @@ importers: specifier: ^0.6.0 version: 0.6.0 '@web3-storage/w3up-client': - specifier: ^16.5.2 - version: 16.5.2(encoding@0.1.13) + specifier: ^17.1.1 + version: 17.1.1(encoding@0.1.13) assert: specifier: ^2.1.0 version: 2.1.0 @@ -1750,16 +1750,16 @@ packages: '@web3-storage/access@20.1.1': resolution: {integrity: sha512-W2C9sn8NTWw7zIUVzEk5MtwWQLFsOREF6Ju6VK+MYcuAkQ6yVll6Q7YtB5zLPwu29xJ7KIR6e5KzbDNSXHSfrA==} - '@web3-storage/blob-index@1.0.4': - resolution: {integrity: sha512-04+PrmVHFT+xzRhyIPdcvGc8Y2NDffUe8R1gJOyErVzEVz5N1I9Q/BrlFHYt/A4HrjM5JBsxqSrZgTIkjfPmLA==} + '@web3-storage/blob-index@1.0.5': + resolution: {integrity: sha512-mhzupWeRfxLljoULcagU++mOmQOriCBMKniUhsmrCXrtRV8voF7op/ymqix1f9uX1M5iB93YXcfxAVBwGWWKoA==} engines: {node: '>=16.15'} - '@web3-storage/capabilities@17.4.1': - resolution: {integrity: sha512-GogLfON8PZabi03CUyncBvMcCi36yQ/0iR5P8kr4pxdnZm7OuAn4sEwbEB8rTKbah5V10Vwgb3O5dh0FBgyjHg==} - '@web3-storage/capabilities@18.0.0': resolution: {integrity: sha512-sG0GmHrNNR+nT7wB1sIz91FG55PWJvrquMZyY8GD20r0l49kojDTlz/n14bEhof9uKE0T9KinmxitknOx/B+4Q==} + '@web3-storage/capabilities@18.0.1': + resolution: {integrity: sha512-FLAUpuuFYkLrMkXy/W7iVNQdFlqGCZUrQr30L2C05SbQdpb/4tN6jqRG+l2nvAYTaYjWTYzsYLHGy2illsuNZQ==} + '@web3-storage/clock@0.4.1': resolution: {integrity: sha512-VHAyvbl7ZrNls6yltS5Djuwjz9Rw0rcA8tpv7qQp1WoheY00YBdqa8gjR1V4egVkqV1ZugGA06XH+ug0OhGXDg==} @@ -1770,8 +1770,8 @@ packages: resolution: {integrity: sha512-TRmfSXj1IhtX3ESurSNOylZSBKi0z/VJNoMLpof+AVRdovgZjjocpiePQTs2pfHKqHTHfJXc9AboWyK4IKTWMw==} engines: {node: '>=16.15'} - '@web3-storage/filecoin-client@3.3.4': - resolution: {integrity: sha512-T2xur1NPvuH09yajyjCWEl7MBH712nqHERj51w4nDp6f8libMCKY6lca0frCrm4OC5s8oy0ZtoRFhsRYxgTzSg==} + '@web3-storage/filecoin-client@3.3.5': + resolution: {integrity: sha512-3JFKnHFizlljRSJyyCdNN3Np4MN5riBvjAXweqNmu4s2sChMB8kopnCkAFoMeEom9r7ZAnBAkMO3Wacjs6Nlcw==} '@web3-storage/pail@0.5.0': resolution: {integrity: sha512-BUuunK6ZQQfNvECB2st0G7/rd0Vfsn6jFg01tfMLEsitFJWI9J503ixKJ8jWpoNW/3juJ32HQpo8ar3pmgG5uA==} @@ -1781,11 +1781,11 @@ packages: resolution: {integrity: sha512-/lIBu8pR92AEcCqYqjcxc3kUSLLRGQLomUes7PAyoK4lNe4ttm8Wr7WFcrbJmWTBJZmYE6npbYcVio8U+OexpA==} hasBin: true - '@web3-storage/upload-client@17.1.1': - resolution: {integrity: sha512-PIPrg8uF1+NjLLNyiYQoT5gHBIO1aCiyFhYAZtg5JZZGYq/hRLh8xBTQLEBsSzSPGNm0Xpx8o4I3YQ/tTE0wUA==} + '@web3-storage/upload-client@17.1.3': + resolution: {integrity: sha512-pOD5EM6RJgsJ3gRZWfhwfbD21OLvNQ239aD4D5BsQsEEgEoqR8aXdrjDWU4T8DA4YXU6VIai/VGIsDXgw+eg7g==} - '@web3-storage/w3up-client@16.5.2': - resolution: {integrity: sha512-yJNh3r2QWZbn2jQ1ZfsnDJ1HIyhv9akEXeFWx+xFxKViT6df8IzT6BtCnxxFL2ED3Tx7rKVVG1pNatKRO3T+Uw==} + '@web3-storage/w3up-client@17.1.1': + resolution: {integrity: sha512-ngKDS82sFF0XEvJe7IsS0JHOVawSx2XQ2CN9xuberx/FNrmlHhDYsi86J7y7+yJXhQkFyh3hSVvQ7mmPz2HJwQ==} engines: {node: '>=18'} acorn-jsx@5.3.2: @@ -5925,18 +5925,18 @@ snapshots: type-fest: 4.26.1 uint8arrays: 4.0.10 - '@web3-storage/blob-index@1.0.4': + '@web3-storage/blob-index@1.0.5': dependencies: '@ipld/dag-cbor': 9.2.2 '@storacha/one-webcrypto': 1.0.1 '@ucanto/core': 10.0.1 '@ucanto/interface': 10.0.1 - '@web3-storage/capabilities': 17.4.1 + '@web3-storage/capabilities': 18.0.1 carstream: 2.2.0 multiformats: 13.3.1 uint8arrays: 5.1.0 - '@web3-storage/capabilities@17.4.1': + '@web3-storage/capabilities@18.0.0': dependencies: '@ucanto/core': 10.0.1 '@ucanto/interface': 10.0.1 @@ -5946,7 +5946,7 @@ snapshots: '@web3-storage/data-segment': 5.2.0 uint8arrays: 5.1.0 - '@web3-storage/capabilities@18.0.0': + '@web3-storage/capabilities@18.0.1': dependencies: '@ucanto/core': 10.0.1 '@ucanto/interface': 10.0.1 @@ -5979,14 +5979,14 @@ snapshots: '@web3-storage/did-mailto@2.1.0': {} - '@web3-storage/filecoin-client@3.3.4': + '@web3-storage/filecoin-client@3.3.5': dependencies: '@ipld/dag-ucan': 3.4.0 '@ucanto/client': 9.0.1 '@ucanto/core': 10.0.1 '@ucanto/interface': 10.0.1 '@ucanto/transport': 9.1.1 - '@web3-storage/capabilities': 17.4.1 + '@web3-storage/capabilities': 18.0.1 '@web3-storage/pail@0.5.0': dependencies: @@ -6003,7 +6003,7 @@ snapshots: '@ipld/dag-cbor': 9.2.2 multiformats: 13.3.1 - '@web3-storage/upload-client@17.1.1(encoding@0.1.13)': + '@web3-storage/upload-client@17.1.3(encoding@0.1.13)': dependencies: '@ipld/car': 5.3.3 '@ipld/dag-cbor': 9.2.2 @@ -6013,10 +6013,10 @@ snapshots: '@ucanto/core': 10.0.1 '@ucanto/interface': 10.0.1 '@ucanto/transport': 9.1.1 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.1 + '@web3-storage/blob-index': 1.0.5 + '@web3-storage/capabilities': 18.0.1 '@web3-storage/data-segment': 5.2.0 - '@web3-storage/filecoin-client': 3.3.4 + '@web3-storage/filecoin-client': 3.3.5 ipfs-utils: 9.0.14(encoding@0.1.13) multiformats: 12.1.3 p-retry: 5.1.2 @@ -6024,7 +6024,7 @@ snapshots: transitivePeerDependencies: - encoding - '@web3-storage/w3up-client@16.5.2(encoding@0.1.13)': + '@web3-storage/w3up-client@17.1.1(encoding@0.1.13)': dependencies: '@ipld/dag-ucan': 3.4.0 '@ucanto/client': 9.0.1 @@ -6033,11 +6033,11 @@ snapshots: '@ucanto/principal': 9.0.1 '@ucanto/transport': 9.1.1 '@web3-storage/access': 20.1.1 - '@web3-storage/blob-index': 1.0.4 - '@web3-storage/capabilities': 17.4.1 + '@web3-storage/blob-index': 1.0.5 + '@web3-storage/capabilities': 18.0.1 '@web3-storage/did-mailto': 2.1.0 - '@web3-storage/filecoin-client': 3.3.4 - '@web3-storage/upload-client': 17.1.1(encoding@0.1.13) + '@web3-storage/filecoin-client': 3.3.5 + '@web3-storage/upload-client': 17.1.3(encoding@0.1.13) transitivePeerDependencies: - encoding From 9bb92a27e8095c1c2ce53de9a66ffbe75b524541 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:18:28 +0000 Subject: [PATCH 65/83] chore(deps-dev): bump vite from 6.0.3 to 6.0.5 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.3 to 6.0.5. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.0.5/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index d227159c..a75e2d8d 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "tsx": "^4.19.2", "typescript": "^5.7.2", "typescript-eslint": "^8.18.0", - "vite": "^6.0.3", + "vite": "^6.0.5", "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", "wait-on": "^8.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b41f5a6..6c9ccfee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,11 +196,11 @@ importers: specifier: ^8.18.0 version: 8.18.0(eslint@9.17.0)(typescript@5.7.2) vite: - specifier: ^6.0.3 - version: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + specifier: ^6.0.5 + version: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.2) @@ -3917,8 +3917,8 @@ packages: terser: optional: true - vite@6.0.3: - resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} + vite@6.0.5: + resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -8511,13 +8511,13 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.2) optionalDependencies: - vite: 6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + vite: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -8531,7 +8531,7 @@ snapshots: '@types/node': 22.10.2 fsevents: 2.3.3 - vite@6.0.3(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): + vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: esbuild: 0.24.0 postcss: 8.4.49 From 1bcd7d2ea2b0edec797e24919d50266c8d9a3242 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:18:00 +0000 Subject: [PATCH 66/83] chore(deps-dev): bump esbuild from 0.24.0 to 0.24.2 Bumps [esbuild](https://github.com/evanw/esbuild) from 0.24.0 to 0.24.2. - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](https://github.com/evanw/esbuild/compare/v0.24.0...v0.24.2) --- updated-dependencies: - dependency-name: esbuild dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 222 ++++++++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 107 deletions(-) diff --git a/package.json b/package.json index a75e2d8d..ee6d1e5a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@types/ws": "^8.5.13", "@typescript-eslint/typescript-estree": "^8.18.1", "@web3-storage/access": "^20.1.1", - "esbuild": "^0.24.0", + "esbuild": "^0.24.2", "esbuild-plugin-replace": "^1.4.0", "esbuild-plugin-resolve": "^2.0.0", "eslint": "^9.17.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c9ccfee..3b95c622 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -163,8 +163,8 @@ importers: specifier: ^8.18.1 version: 8.18.1(typescript@5.7.2) esbuild: - specifier: ^0.24.0 - version: 0.24.0 + specifier: ^0.24.2 + version: 0.24.2 esbuild-plugin-replace: specifier: ^1.4.0 version: 1.4.0 @@ -520,8 +520,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -544,8 +544,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -568,8 +568,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -592,8 +592,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -616,8 +616,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -640,8 +640,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -664,8 +664,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -688,8 +688,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -712,8 +712,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -736,8 +736,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -760,8 +760,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -784,8 +784,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -808,8 +808,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -832,8 +832,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -856,8 +856,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -880,8 +880,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -904,12 +904,18 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.17.19': resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -928,8 +934,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -940,8 +946,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -964,8 +970,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -988,8 +994,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1012,8 +1018,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1036,8 +1042,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1060,8 +1066,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -2233,8 +2239,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.24.0: - resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} hasBin: true @@ -4731,7 +4737,7 @@ snapshots: '@esbuild/aix-ppc64@0.23.1': optional: true - '@esbuild/aix-ppc64@0.24.0': + '@esbuild/aix-ppc64@0.24.2': optional: true '@esbuild/android-arm64@0.17.19': @@ -4743,7 +4749,7 @@ snapshots: '@esbuild/android-arm64@0.23.1': optional: true - '@esbuild/android-arm64@0.24.0': + '@esbuild/android-arm64@0.24.2': optional: true '@esbuild/android-arm@0.17.19': @@ -4755,7 +4761,7 @@ snapshots: '@esbuild/android-arm@0.23.1': optional: true - '@esbuild/android-arm@0.24.0': + '@esbuild/android-arm@0.24.2': optional: true '@esbuild/android-x64@0.17.19': @@ -4767,7 +4773,7 @@ snapshots: '@esbuild/android-x64@0.23.1': optional: true - '@esbuild/android-x64@0.24.0': + '@esbuild/android-x64@0.24.2': optional: true '@esbuild/darwin-arm64@0.17.19': @@ -4779,7 +4785,7 @@ snapshots: '@esbuild/darwin-arm64@0.23.1': optional: true - '@esbuild/darwin-arm64@0.24.0': + '@esbuild/darwin-arm64@0.24.2': optional: true '@esbuild/darwin-x64@0.17.19': @@ -4791,7 +4797,7 @@ snapshots: '@esbuild/darwin-x64@0.23.1': optional: true - '@esbuild/darwin-x64@0.24.0': + '@esbuild/darwin-x64@0.24.2': optional: true '@esbuild/freebsd-arm64@0.17.19': @@ -4803,7 +4809,7 @@ snapshots: '@esbuild/freebsd-arm64@0.23.1': optional: true - '@esbuild/freebsd-arm64@0.24.0': + '@esbuild/freebsd-arm64@0.24.2': optional: true '@esbuild/freebsd-x64@0.17.19': @@ -4815,7 +4821,7 @@ snapshots: '@esbuild/freebsd-x64@0.23.1': optional: true - '@esbuild/freebsd-x64@0.24.0': + '@esbuild/freebsd-x64@0.24.2': optional: true '@esbuild/linux-arm64@0.17.19': @@ -4827,7 +4833,7 @@ snapshots: '@esbuild/linux-arm64@0.23.1': optional: true - '@esbuild/linux-arm64@0.24.0': + '@esbuild/linux-arm64@0.24.2': optional: true '@esbuild/linux-arm@0.17.19': @@ -4839,7 +4845,7 @@ snapshots: '@esbuild/linux-arm@0.23.1': optional: true - '@esbuild/linux-arm@0.24.0': + '@esbuild/linux-arm@0.24.2': optional: true '@esbuild/linux-ia32@0.17.19': @@ -4851,7 +4857,7 @@ snapshots: '@esbuild/linux-ia32@0.23.1': optional: true - '@esbuild/linux-ia32@0.24.0': + '@esbuild/linux-ia32@0.24.2': optional: true '@esbuild/linux-loong64@0.17.19': @@ -4863,7 +4869,7 @@ snapshots: '@esbuild/linux-loong64@0.23.1': optional: true - '@esbuild/linux-loong64@0.24.0': + '@esbuild/linux-loong64@0.24.2': optional: true '@esbuild/linux-mips64el@0.17.19': @@ -4875,7 +4881,7 @@ snapshots: '@esbuild/linux-mips64el@0.23.1': optional: true - '@esbuild/linux-mips64el@0.24.0': + '@esbuild/linux-mips64el@0.24.2': optional: true '@esbuild/linux-ppc64@0.17.19': @@ -4887,7 +4893,7 @@ snapshots: '@esbuild/linux-ppc64@0.23.1': optional: true - '@esbuild/linux-ppc64@0.24.0': + '@esbuild/linux-ppc64@0.24.2': optional: true '@esbuild/linux-riscv64@0.17.19': @@ -4899,7 +4905,7 @@ snapshots: '@esbuild/linux-riscv64@0.23.1': optional: true - '@esbuild/linux-riscv64@0.24.0': + '@esbuild/linux-riscv64@0.24.2': optional: true '@esbuild/linux-s390x@0.17.19': @@ -4911,7 +4917,7 @@ snapshots: '@esbuild/linux-s390x@0.23.1': optional: true - '@esbuild/linux-s390x@0.24.0': + '@esbuild/linux-s390x@0.24.2': optional: true '@esbuild/linux-x64@0.17.19': @@ -4923,7 +4929,10 @@ snapshots: '@esbuild/linux-x64@0.23.1': optional: true - '@esbuild/linux-x64@0.24.0': + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': optional: true '@esbuild/netbsd-x64@0.17.19': @@ -4935,13 +4944,13 @@ snapshots: '@esbuild/netbsd-x64@0.23.1': optional: true - '@esbuild/netbsd-x64@0.24.0': + '@esbuild/netbsd-x64@0.24.2': optional: true '@esbuild/openbsd-arm64@0.23.1': optional: true - '@esbuild/openbsd-arm64@0.24.0': + '@esbuild/openbsd-arm64@0.24.2': optional: true '@esbuild/openbsd-x64@0.17.19': @@ -4953,7 +4962,7 @@ snapshots: '@esbuild/openbsd-x64@0.23.1': optional: true - '@esbuild/openbsd-x64@0.24.0': + '@esbuild/openbsd-x64@0.24.2': optional: true '@esbuild/sunos-x64@0.17.19': @@ -4965,7 +4974,7 @@ snapshots: '@esbuild/sunos-x64@0.23.1': optional: true - '@esbuild/sunos-x64@0.24.0': + '@esbuild/sunos-x64@0.24.2': optional: true '@esbuild/win32-arm64@0.17.19': @@ -4977,7 +4986,7 @@ snapshots: '@esbuild/win32-arm64@0.23.1': optional: true - '@esbuild/win32-arm64@0.24.0': + '@esbuild/win32-arm64@0.24.2': optional: true '@esbuild/win32-ia32@0.17.19': @@ -4989,7 +4998,7 @@ snapshots: '@esbuild/win32-ia32@0.23.1': optional: true - '@esbuild/win32-ia32@0.24.0': + '@esbuild/win32-ia32@0.24.2': optional: true '@esbuild/win32-x64@0.17.19': @@ -5001,7 +5010,7 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@esbuild/win32-x64@0.24.0': + '@esbuild/win32-x64@0.24.2': optional: true '@eslint-community/eslint-utils@4.4.0(eslint@9.17.0)': @@ -6280,9 +6289,9 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bundle-require@5.0.0(esbuild@0.24.0): + bundle-require@5.0.0(esbuild@0.24.2): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 load-tsconfig: 0.2.5 cac@6.7.14: {} @@ -6631,32 +6640,33 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 - esbuild@0.24.0: + esbuild@0.24.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.24.0 - '@esbuild/android-arm': 0.24.0 - '@esbuild/android-arm64': 0.24.0 - '@esbuild/android-x64': 0.24.0 - '@esbuild/darwin-arm64': 0.24.0 - '@esbuild/darwin-x64': 0.24.0 - '@esbuild/freebsd-arm64': 0.24.0 - '@esbuild/freebsd-x64': 0.24.0 - '@esbuild/linux-arm': 0.24.0 - '@esbuild/linux-arm64': 0.24.0 - '@esbuild/linux-ia32': 0.24.0 - '@esbuild/linux-loong64': 0.24.0 - '@esbuild/linux-mips64el': 0.24.0 - '@esbuild/linux-ppc64': 0.24.0 - '@esbuild/linux-riscv64': 0.24.0 - '@esbuild/linux-s390x': 0.24.0 - '@esbuild/linux-x64': 0.24.0 - '@esbuild/netbsd-x64': 0.24.0 - '@esbuild/openbsd-arm64': 0.24.0 - '@esbuild/openbsd-x64': 0.24.0 - '@esbuild/sunos-x64': 0.24.0 - '@esbuild/win32-arm64': 0.24.0 - '@esbuild/win32-ia32': 0.24.0 - '@esbuild/win32-x64': 0.24.0 + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 escape-string-regexp@4.0.0: {} @@ -8363,12 +8373,12 @@ snapshots: tsup@8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.5.1): dependencies: - bundle-require: 5.0.0(esbuild@0.24.0) + bundle-require: 5.0.0(esbuild@0.24.2) cac: 6.7.14 chokidar: 4.0.1 consola: 3.2.3 debug: 4.3.7 - esbuild: 0.24.0 + esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 postcss-load-config: 6.0.1(postcss@8.4.49)(tsx@4.19.2)(yaml@2.5.1) @@ -8533,7 +8543,7 @@ snapshots: vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: From 11afda5f6791a5611f47682f63cece539abae630 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:17:36 +0000 Subject: [PATCH 67/83] chore(deps): bump @aws-sdk/client-s3 from 3.712.0 to 3.717.0 Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.712.0 to 3.717.0. - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.717.0/clients/client-s3) --- updated-dependencies: - dependency-name: "@aws-sdk/client-s3" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 744 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 497 insertions(+), 249 deletions(-) diff --git a/package.json b/package.json index ee6d1e5a..e53ed2b6 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@adviser/cement": "^0.2.41", - "@aws-sdk/client-s3": "^3.712.0", + "@aws-sdk/client-s3": "^3.717.0", "@fireproof/core": "0.19.118", "@fireproof/vendor": "1.0.0", "@ipld/dag-ucan": "^3.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b95c622..b5634bf5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^0.2.41 version: 0.2.41(typescript@5.7.2) '@aws-sdk/client-s3': - specifier: ^3.712.0 - version: 3.712.0 + specifier: ^3.717.0 + version: 3.717.0 '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) @@ -243,135 +243,135 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.712.0': - resolution: {integrity: sha512-Hq1IIwOFutmHtTz3mROR1XhTDL8rxcYbYw3ajjgeMJB5tjcvodpfkfz/L4dxXZMwqylWf6SNQNAiaGh5mlsGGQ==} + '@aws-sdk/client-s3@3.717.0': + resolution: {integrity: sha512-jzaH8IskAXVnqlZ3/H/ROwrB2HCnq/atlN7Hi7FIfjWvMPf5nfcJKfzJ1MXFX0EQR5qO6X4TbK7rgi7Bjw9NjQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/client-sso-oidc@3.712.0': - resolution: {integrity: sha512-xNFrG9syrG6pxUP7Ld/nu3afQ9+rbJM9qrE+wDNz4VnNZ3vLiJty4fH85zBFhOQ5OF2DIJTWsFzXGi2FYjsCMA==} + '@aws-sdk/client-sso-oidc@3.716.0': + resolution: {integrity: sha512-lA4IB9FzR2KjH7EVCo+mHGFKqdViVyeBQEIX9oVratL/l7P0bMS1fMwgfHOc3ACazqNxBxDES7x08ZCp32y6Lw==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.712.0 + '@aws-sdk/client-sts': ^3.716.0 - '@aws-sdk/client-sso@3.712.0': - resolution: {integrity: sha512-tBo/eW3YpZ9f3Q1qA7aA8uliNFJJX0OP7R2IUJ8t6rqVTk15wWCEPNmXzUZKgruDnKUfCaF4+r9q/Yy4fBc9PA==} + '@aws-sdk/client-sso@3.716.0': + resolution: {integrity: sha512-5Nb0jJXce2TclbjG7WVPufwhgV1TRydz1QnsuBtKU0AdViEpr787YrZhPpGnNIM1Dx+R1H/tmAHZnOoohS6D8g==} engines: {node: '>=16.0.0'} - '@aws-sdk/client-sts@3.712.0': - resolution: {integrity: sha512-gIO6BD+hkEe3GKQhbiFP0zcNQv0EkP1Cl9SOstxS+X9CeudEgVX/xEPUjyoFVkfkntPBJ1g0I1u5xOzzRExl4g==} + '@aws-sdk/client-sts@3.716.0': + resolution: {integrity: sha512-i4SVNsrdXudp8T4bkm7Fi3YWlRnvXCSwvNDqf6nLqSJxqr4CN3VlBELueDyjBK7TAt453/qSif+eNx+bHmwo4Q==} engines: {node: '>=16.0.0'} - '@aws-sdk/core@3.709.0': - resolution: {integrity: sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw==} + '@aws-sdk/core@3.716.0': + resolution: {integrity: sha512-5DkUiTrbyzO8/W4g7UFEqRFpuhgizayHI/Zbh0wtFMcot8801nJV+MP/YMhdjimlvAr/OqYB08FbGsPyWppMTw==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-env@3.709.0': - resolution: {integrity: sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ==} + '@aws-sdk/credential-provider-env@3.716.0': + resolution: {integrity: sha512-JI2KQUnn2arICwP9F3CnqP1W3nAbm4+meQg/yOhp9X0DMzQiHrHRd4HIrK2vyVgi2/6hGhONY5uLF26yRTA7nQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-http@3.709.0': - resolution: {integrity: sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ==} + '@aws-sdk/credential-provider-http@3.716.0': + resolution: {integrity: sha512-CZ04pl2z7igQPysQyH2xKZHM3fLwkemxQbKOlje3TmiS1NwXvcKvERhp9PE/H23kOL7beTM19NMRog/Fka/rlw==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-ini@3.712.0': - resolution: {integrity: sha512-sTsdQ/Fm/suqMdpjhMuss/5uKL18vcuWnNTQVrG9iGNRqZLbq65MXquwbUpgzfoUmIcH+4CrY6H2ebpTIECIag==} + '@aws-sdk/credential-provider-ini@3.716.0': + resolution: {integrity: sha512-P37We2GtZvdROxiwP0zrpEL81/HuYK1qlYxp5VCj3uV+G4mG8UQN2gMIU/baYrpOQqa0h81RfyQGRFUjVaDVqw==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.712.0 + '@aws-sdk/client-sts': ^3.716.0 - '@aws-sdk/credential-provider-node@3.712.0': - resolution: {integrity: sha512-gXrHymW3rMRYORkPVQwL8Gi5Lu92F16SoZR543x03qCi7rm00oL9tRD85ACxkhprS1Wh8lUIUMNoeiwnYWTNuQ==} + '@aws-sdk/credential-provider-node@3.716.0': + resolution: {integrity: sha512-FGQPK2uKfS53dVvoskN/s/t6m0Po24BGd1PzJdzHBFCOjxbZLM6+8mDMXeyi2hCLVVQOUcuW41kOgmJ0+zMbww==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-process@3.709.0': - resolution: {integrity: sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q==} + '@aws-sdk/credential-provider-process@3.716.0': + resolution: {integrity: sha512-0spcu2MWVVHSTHH3WE2E//ttUJPwXRM3BCp+WyI41xLzpNu1Fd8zjOrDpEo0SnGUzsSiRTIJWgkuu/tqv9NJ2A==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-sso@3.712.0': - resolution: {integrity: sha512-8lCMxY7Lb9VK9qdlNXRJXE3W1UDVURnJZ3a4XWYNY6yr1TfQaN40mMyXX1oNlXXJtMV0szRvjM8dZj37E/ESAw==} + '@aws-sdk/credential-provider-sso@3.716.0': + resolution: {integrity: sha512-J2IA3WuCpRGGoZm6VHZVFCnrxXP+41iUWb9Ct/1spljegTa1XjiaZ5Jf3+Ubj7WKiyvP9/dgz1L0bu2bYEjliw==} engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-web-identity@3.709.0': - resolution: {integrity: sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA==} + '@aws-sdk/credential-provider-web-identity@3.716.0': + resolution: {integrity: sha512-vzgpWKs2gGXZGdbMKRFrMW4PqEFWkGvwWH2T7ZwQv9m+8lQ7P4Dk2uimqu0f37HZAbpn8HFMqRh4CaySjU354A==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sts': ^3.709.0 + '@aws-sdk/client-sts': ^3.716.0 - '@aws-sdk/middleware-bucket-endpoint@3.709.0': - resolution: {integrity: sha512-03+tJOd7KIZOiqWH7Z8BOfQIWkKJgjcpKOJKZ6FR2KjWGUOE1G+bo11wF4UuHQ0RmpKnApt+pQghZmSnE7WEeg==} + '@aws-sdk/middleware-bucket-endpoint@3.714.0': + resolution: {integrity: sha512-I/xSOskiseJJ8i183Z522BgqbgYzLKP7jGcg2Qeib/IWoG2IP+9DH8pwqagKaPAycyswtnoKBJiiFXY43n0CkA==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-expect-continue@3.709.0': - resolution: {integrity: sha512-Tbl/DFvE4rHl8lMb9IzetwK4tf5R3VeHZkvEXQalsWoK0tbEQ8kXWi7wAYO4qbE7bFVvaxKX+irjJjTxf3BrCQ==} + '@aws-sdk/middleware-expect-continue@3.714.0': + resolution: {integrity: sha512-rlzsXdG8Lzo4Qpl35ZnpOBAWlzvDHpP9++0AXoUwAJA0QmMm7auIRmgxJuNj91VwT9h15ZU6xjU4S7fJl4W0+w==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.709.0': - resolution: {integrity: sha512-wbYm9tkyCaqMeU82yjaXw7V5BxCSlSLNupENW63LC7Fvyo/aQzj6LjSMHcBpR2QwjBEhXCtF47L7aQ8SPTNhdw==} + '@aws-sdk/middleware-flexible-checksums@3.717.0': + resolution: {integrity: sha512-a5kY5r7/7bDZZlOQQGWOR1ulQewdtNexdW1Ex5DD0FLKlFY7RD0va24hxQ6BP7mWHol+Dx4pj6UQ8ahk0ap1tw==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-host-header@3.709.0': - resolution: {integrity: sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw==} + '@aws-sdk/middleware-host-header@3.714.0': + resolution: {integrity: sha512-6l68kjNrh5QC8FGX3I3geBDavWN5Tg1RLHJ2HLA8ByGBtJyCwnz3hEkKfaxn0bBx0hF9DzbfjEOUF6cDqy2Kjg==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-location-constraint@3.709.0': - resolution: {integrity: sha512-5YQWPXfZq7OE0jB2G0PP8K10GBod/YPJXb+1CfJS6FbQaglRoIm8KZmVEvJNnptSKyGtE62veeCcCQcfAUfFig==} + '@aws-sdk/middleware-location-constraint@3.714.0': + resolution: {integrity: sha512-MX7M+V+FblujKck3fyuzePVIAy9530gY719IiSxV6uN1qLHl7VDJxNblpF/KpXakD6rOg8OpvtmqsXj9aBMftw==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-logger@3.709.0': - resolution: {integrity: sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg==} + '@aws-sdk/middleware-logger@3.714.0': + resolution: {integrity: sha512-RkqHlMvQWUaRklU1bMfUuBvdWwxgUtEqpADaHXlGVj3vtEY2UgBjy+57CveC4MByqKIunNvVHBBbjrGVtwY7Lg==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-recursion-detection@3.709.0': - resolution: {integrity: sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw==} + '@aws-sdk/middleware-recursion-detection@3.714.0': + resolution: {integrity: sha512-AVU5ixnh93nqtsfgNc284oXsXaadyHGPHpql/jwgaaqQfEXjS/1/j3j9E/vpacfTTz2Vzo7hAOjnvrOXSEVDaA==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-sdk-s3@3.709.0': - resolution: {integrity: sha512-FwtOG9t9xsLoLOQZ6qAdsWOjx9dsO6t28IjIDV1l6Ixiu2oC0Yks7goONjJUH0IDE4pDDDGzmuq0sn1XtHhheA==} + '@aws-sdk/middleware-sdk-s3@3.716.0': + resolution: {integrity: sha512-Qzz5OfRA/5brqfvq+JHTInwS1EuJ1+tC6qMtwKWJN3czMnVJVdnnsPTf+G5IM/1yYaGEIjY8rC1ExQLcc8ApFQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-ssec@3.709.0': - resolution: {integrity: sha512-2muiLe7YkmlwZp2SKz+goZrDThGfRq3o0FcJF3Puc0XGmcEPEDjih537mCoTrGgcXNFlBc7YChd84r3t72ySaQ==} + '@aws-sdk/middleware-ssec@3.714.0': + resolution: {integrity: sha512-RkK8REAVwNUQmYbIDRw8eYbMJ8F1Rw4C9mlME4BBMhFlelGcD3ErU2ce24moQbDxBjNwHNESmIqgmdQk93CDCQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-user-agent@3.709.0': - resolution: {integrity: sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw==} + '@aws-sdk/middleware-user-agent@3.716.0': + resolution: {integrity: sha512-FpAtT6nNKrYdkDZndutEraiRMf+TgDzAGvniqRtZ/YTPA+gIsWrsn+TwMKINR81lFC3nQfb9deS5CFtxd021Ew==} engines: {node: '>=16.0.0'} - '@aws-sdk/region-config-resolver@3.709.0': - resolution: {integrity: sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w==} + '@aws-sdk/region-config-resolver@3.714.0': + resolution: {integrity: sha512-HJzsQxgMOAzZrbf/YIqEx30or4tZK1oNAk6Wm6xecUQx+23JXIaePRu1YFUOLBBERQ4QBPpISFurZWBMZ5ibAw==} engines: {node: '>=16.0.0'} - '@aws-sdk/signature-v4-multi-region@3.709.0': - resolution: {integrity: sha512-m0vhJEy6SLbjL11K9cHzX/ZhCIj//1GkTbYk2d4tTQFSuPyJEkjmoeHk9dYm2mJy0wH48j29OJadI1JUsR5bOw==} + '@aws-sdk/signature-v4-multi-region@3.716.0': + resolution: {integrity: sha512-k0goWotZKKz+kV6Ln0qeAMSeSVi4NipuIIz5R8A0uCF2zBK4CXWdZR7KeaIoLBhJwQnHj1UU7E+2MK74KIUBzA==} engines: {node: '>=16.0.0'} - '@aws-sdk/token-providers@3.709.0': - resolution: {integrity: sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA==} + '@aws-sdk/token-providers@3.714.0': + resolution: {integrity: sha512-vKN064aLE3kl+Zl16Ony3jltHnMddMBT7JRkP1L+lLywhA0PcAKxpdvComul/sTBWnbnwLnaS5NsDUhcWySH8A==} engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-sso-oidc': ^3.709.0 + '@aws-sdk/client-sso-oidc': ^3.714.0 - '@aws-sdk/types@3.709.0': - resolution: {integrity: sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg==} + '@aws-sdk/types@3.714.0': + resolution: {integrity: sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==} engines: {node: '>=16.0.0'} '@aws-sdk/util-arn-parser@3.693.0': resolution: {integrity: sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ==} engines: {node: '>=16.0.0'} - '@aws-sdk/util-endpoints@3.709.0': - resolution: {integrity: sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q==} + '@aws-sdk/util-endpoints@3.714.0': + resolution: {integrity: sha512-Xv+Z2lhe7w7ZZRsgBwBMZgGTVmS+dkkj2S13uNHAx9lhB5ovM8PhK5G/j28xYf6vIibeuHkRAbb7/ozdZIGR+A==} engines: {node: '>=16.0.0'} '@aws-sdk/util-locate-window@3.568.0': resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} engines: {node: '>=16.0.0'} - '@aws-sdk/util-user-agent-browser@3.709.0': - resolution: {integrity: sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg==} + '@aws-sdk/util-user-agent-browser@3.714.0': + resolution: {integrity: sha512-OdJJ03cP9/MgIVToPJPCPUImbpZzTcwdIgbXC0tUQPJhbD7b7cB4LdnkhNHko+MptpOrCq4CPY/33EpOjRdofw==} - '@aws-sdk/util-user-agent-node@3.712.0': - resolution: {integrity: sha512-26X21bZ4FWsVpqs33uOXiB60TOWQdVlr7T7XONDFL/XN7GEpUJkWuuIB4PTok6VOmh1viYcdxZQqekXPuzXexQ==} + '@aws-sdk/util-user-agent-node@3.716.0': + resolution: {integrity: sha512-3PqaXmQbxrtHKAsPCdp7kn5FrQktj8j3YyuNsqFZ8rWZeEQ88GWlsvE61PTsr2peYCKzpFqYVddef2x1axHU0w==} engines: {node: '>=16.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -520,6 +520,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -544,6 +550,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.24.2': resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} @@ -568,6 +580,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.24.2': resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} @@ -592,6 +610,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.24.2': resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} @@ -616,6 +640,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.24.2': resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} @@ -640,6 +670,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.24.2': resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} @@ -664,6 +700,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} @@ -688,6 +730,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} @@ -712,6 +760,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.24.2': resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} @@ -736,6 +790,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.24.2': resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} @@ -760,6 +820,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.24.2': resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} @@ -784,6 +850,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.24.2': resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} @@ -808,6 +880,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.24.2': resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} @@ -832,6 +910,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.24.2': resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} @@ -856,6 +940,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.24.2': resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} @@ -880,6 +970,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.24.2': resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} @@ -904,6 +1000,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.24.2': resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} @@ -934,6 +1036,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} @@ -946,6 +1054,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.24.2': resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} @@ -970,6 +1084,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} @@ -994,6 +1114,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.24.2': resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} @@ -1018,6 +1144,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.24.2': resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} @@ -1042,6 +1174,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.24.2': resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} @@ -1066,6 +1204,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.24.2': resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} @@ -1467,12 +1611,12 @@ packages: resolution: {integrity: sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-endpoint@3.2.5': - resolution: {integrity: sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==} + '@smithy/middleware-endpoint@3.2.6': + resolution: {integrity: sha512-WAqzyulvvSKrT5c6VrQelgNVNNO7BlTQW9Z+s9tcG6G5CaBS1YBpPtT3VuhXLQbewSiGi7oXQROwpw26EG9PLQ==} engines: {node: '>=16.0.0'} - '@smithy/middleware-retry@3.0.30': - resolution: {integrity: sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==} + '@smithy/middleware-retry@3.0.31': + resolution: {integrity: sha512-yq9wawrJLYHAYFpChLujxRN4My+SiKXvZk9Ml/CvTdRSA8ew+hvuR5LT+mjSlSBv3c4XJrkN8CWegkBaeD0Vrg==} engines: {node: '>=16.0.0'} '@smithy/middleware-serde@3.0.11': @@ -1519,8 +1663,8 @@ packages: resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} - '@smithy/smithy-client@3.5.0': - resolution: {integrity: sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==} + '@smithy/smithy-client@3.5.1': + resolution: {integrity: sha512-PmjskH4Os1Eh3rd5vSsa5uVelZ4DRu+N5CBEgb9AT96hQSJGWSEb6pGxKV/PtKQSIp9ft3+KvnT8ViMKaguzgA==} engines: {node: '>=16.0.0'} '@smithy/types@3.7.2': @@ -1553,12 +1697,12 @@ packages: resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} engines: {node: '>=16.0.0'} - '@smithy/util-defaults-mode-browser@3.0.30': - resolution: {integrity: sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==} + '@smithy/util-defaults-mode-browser@3.0.31': + resolution: {integrity: sha512-eO+zkbqrPnmsagqzrmF7IJrCoU2wTQXWVYxMPqA9Oue55kw9WEvhyuw2XQzTVTCRcYsg6KgmV3YYhLlWQJfK1A==} engines: {node: '>= 10.0.0'} - '@smithy/util-defaults-mode-node@3.0.30': - resolution: {integrity: sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==} + '@smithy/util-defaults-mode-node@3.0.31': + resolution: {integrity: sha512-0/nJfpSpbGZOs6qs42wCe2TdjobbnnD4a3YUUlvTXSQqLy4qa63luDaV04hGvqSHP7wQ7/WGehbvHkDhMZd1MQ==} engines: {node: '>= 10.0.0'} '@smithy/util-endpoints@2.1.7': @@ -2239,6 +2383,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.24.2: resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} @@ -4136,20 +4285,20 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4159,7 +4308,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@aws-sdk/util-locate-window': 3.568.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -4167,7 +4316,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -4176,35 +4325,35 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.712.0': + '@aws-sdk/client-s3@3.717.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/client-sts': 3.712.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/middleware-bucket-endpoint': 3.709.0 - '@aws-sdk/middleware-expect-continue': 3.709.0 - '@aws-sdk/middleware-flexible-checksums': 3.709.0 - '@aws-sdk/middleware-host-header': 3.709.0 - '@aws-sdk/middleware-location-constraint': 3.709.0 - '@aws-sdk/middleware-logger': 3.709.0 - '@aws-sdk/middleware-recursion-detection': 3.709.0 - '@aws-sdk/middleware-sdk-s3': 3.709.0 - '@aws-sdk/middleware-ssec': 3.709.0 - '@aws-sdk/middleware-user-agent': 3.709.0 - '@aws-sdk/region-config-resolver': 3.709.0 - '@aws-sdk/signature-v4-multi-region': 3.709.0 - '@aws-sdk/types': 3.709.0 - '@aws-sdk/util-endpoints': 3.709.0 - '@aws-sdk/util-user-agent-browser': 3.709.0 - '@aws-sdk/util-user-agent-node': 3.712.0 + '@aws-sdk/client-sso-oidc': 3.716.0(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/client-sts': 3.716.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/credential-provider-node': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/middleware-bucket-endpoint': 3.714.0 + '@aws-sdk/middleware-expect-continue': 3.714.0 + '@aws-sdk/middleware-flexible-checksums': 3.717.0 + '@aws-sdk/middleware-host-header': 3.714.0 + '@aws-sdk/middleware-location-constraint': 3.714.0 + '@aws-sdk/middleware-logger': 3.714.0 + '@aws-sdk/middleware-recursion-detection': 3.714.0 + '@aws-sdk/middleware-sdk-s3': 3.716.0 + '@aws-sdk/middleware-ssec': 3.714.0 + '@aws-sdk/middleware-user-agent': 3.716.0 + '@aws-sdk/region-config-resolver': 3.714.0 + '@aws-sdk/signature-v4-multi-region': 3.716.0 + '@aws-sdk/types': 3.714.0 + '@aws-sdk/util-endpoints': 3.714.0 + '@aws-sdk/util-user-agent-browser': 3.714.0 + '@aws-sdk/util-user-agent-node': 3.716.0 '@aws-sdk/xml-builder': 3.709.0 '@smithy/config-resolver': 3.0.13 '@smithy/core': 2.5.5 @@ -4218,21 +4367,21 @@ snapshots: '@smithy/invalid-dependency': 3.0.11 '@smithy/md5-js': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.5 - '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.30 - '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4243,43 +4392,43 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)': + '@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0)': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sts': 3.712.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/middleware-host-header': 3.709.0 - '@aws-sdk/middleware-logger': 3.709.0 - '@aws-sdk/middleware-recursion-detection': 3.709.0 - '@aws-sdk/middleware-user-agent': 3.709.0 - '@aws-sdk/region-config-resolver': 3.709.0 - '@aws-sdk/types': 3.709.0 - '@aws-sdk/util-endpoints': 3.709.0 - '@aws-sdk/util-user-agent-browser': 3.709.0 - '@aws-sdk/util-user-agent-node': 3.712.0 + '@aws-sdk/client-sts': 3.716.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/credential-provider-node': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/middleware-host-header': 3.714.0 + '@aws-sdk/middleware-logger': 3.714.0 + '@aws-sdk/middleware-recursion-detection': 3.714.0 + '@aws-sdk/middleware-user-agent': 3.716.0 + '@aws-sdk/region-config-resolver': 3.714.0 + '@aws-sdk/types': 3.714.0 + '@aws-sdk/util-endpoints': 3.714.0 + '@aws-sdk/util-user-agent-browser': 3.714.0 + '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.5 - '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.30 - '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4288,41 +4437,41 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.712.0': + '@aws-sdk/client-sso@3.716.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/middleware-host-header': 3.709.0 - '@aws-sdk/middleware-logger': 3.709.0 - '@aws-sdk/middleware-recursion-detection': 3.709.0 - '@aws-sdk/middleware-user-agent': 3.709.0 - '@aws-sdk/region-config-resolver': 3.709.0 - '@aws-sdk/types': 3.709.0 - '@aws-sdk/util-endpoints': 3.709.0 - '@aws-sdk/util-user-agent-browser': 3.709.0 - '@aws-sdk/util-user-agent-node': 3.712.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/middleware-host-header': 3.714.0 + '@aws-sdk/middleware-logger': 3.714.0 + '@aws-sdk/middleware-recursion-detection': 3.714.0 + '@aws-sdk/middleware-user-agent': 3.716.0 + '@aws-sdk/region-config-resolver': 3.714.0 + '@aws-sdk/types': 3.714.0 + '@aws-sdk/util-endpoints': 3.714.0 + '@aws-sdk/util-user-agent-browser': 3.714.0 + '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.5 - '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.30 - '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4331,43 +4480,43 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sts@3.712.0': + '@aws-sdk/client-sts@3.716.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/core': 3.709.0 - '@aws-sdk/credential-provider-node': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/middleware-host-header': 3.709.0 - '@aws-sdk/middleware-logger': 3.709.0 - '@aws-sdk/middleware-recursion-detection': 3.709.0 - '@aws-sdk/middleware-user-agent': 3.709.0 - '@aws-sdk/region-config-resolver': 3.709.0 - '@aws-sdk/types': 3.709.0 - '@aws-sdk/util-endpoints': 3.709.0 - '@aws-sdk/util-user-agent-browser': 3.709.0 - '@aws-sdk/util-user-agent-node': 3.712.0 + '@aws-sdk/client-sso-oidc': 3.716.0(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/core': 3.716.0 + '@aws-sdk/credential-provider-node': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/middleware-host-header': 3.714.0 + '@aws-sdk/middleware-logger': 3.714.0 + '@aws-sdk/middleware-recursion-detection': 3.714.0 + '@aws-sdk/middleware-user-agent': 3.716.0 + '@aws-sdk/region-config-resolver': 3.714.0 + '@aws-sdk/types': 3.714.0 + '@aws-sdk/util-endpoints': 3.714.0 + '@aws-sdk/util-user-agent-browser': 3.714.0 + '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.5 - '@smithy/middleware-retry': 3.0.30 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.30 - '@smithy/util-defaults-mode-node': 3.0.30 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4376,51 +4525,51 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.709.0': + '@aws-sdk/core@3.716.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/core': 2.5.5 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 fast-xml-parser: 4.4.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.709.0': + '@aws-sdk/credential-provider-env@3.716.0': dependencies: - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/property-provider': 3.1.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.709.0': + '@aws-sdk/credential-provider-http@3.716.0': dependencies: - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/fetch-http-handler': 4.1.2 '@smithy/node-http-handler': 3.3.2 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-stream': 3.3.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0)': + '@aws-sdk/credential-provider-ini@3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0)': dependencies: - '@aws-sdk/client-sts': 3.712.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/credential-provider-env': 3.709.0 - '@aws-sdk/credential-provider-http': 3.709.0 - '@aws-sdk/credential-provider-process': 3.709.0 - '@aws-sdk/credential-provider-sso': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) - '@aws-sdk/credential-provider-web-identity': 3.709.0(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/types': 3.709.0 + '@aws-sdk/client-sts': 3.716.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/credential-provider-env': 3.716.0 + '@aws-sdk/credential-provider-http': 3.716.0 + '@aws-sdk/credential-provider-process': 3.716.0 + '@aws-sdk/credential-provider-sso': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0)) + '@aws-sdk/credential-provider-web-identity': 3.716.0(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/types': 3.714.0 '@smithy/credential-provider-imds': 3.2.8 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 @@ -4430,15 +4579,15 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-node@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0)': + '@aws-sdk/credential-provider-node@3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0)': dependencies: - '@aws-sdk/credential-provider-env': 3.709.0 - '@aws-sdk/credential-provider-http': 3.709.0 - '@aws-sdk/credential-provider-ini': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/credential-provider-process': 3.709.0 - '@aws-sdk/credential-provider-sso': 3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) - '@aws-sdk/credential-provider-web-identity': 3.709.0(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/types': 3.709.0 + '@aws-sdk/credential-provider-env': 3.716.0 + '@aws-sdk/credential-provider-http': 3.716.0 + '@aws-sdk/credential-provider-ini': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/credential-provider-process': 3.716.0 + '@aws-sdk/credential-provider-sso': 3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0)) + '@aws-sdk/credential-provider-web-identity': 3.716.0(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/types': 3.714.0 '@smithy/credential-provider-imds': 3.2.8 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 @@ -4449,21 +4598,21 @@ snapshots: - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-process@3.709.0': + '@aws-sdk/credential-provider-process@3.716.0': dependencies: - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.712.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))': + '@aws-sdk/credential-provider-sso@3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))': dependencies: - '@aws-sdk/client-sso': 3.712.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/token-providers': 3.709.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0)) - '@aws-sdk/types': 3.709.0 + '@aws-sdk/client-sso': 3.716.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/token-providers': 3.714.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0)) + '@aws-sdk/types': 3.714.0 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 @@ -4472,18 +4621,18 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-web-identity@3.709.0(@aws-sdk/client-sts@3.712.0)': + '@aws-sdk/credential-provider-web-identity@3.716.0(@aws-sdk/client-sts@3.716.0)': dependencies: - '@aws-sdk/client-sts': 3.712.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/client-sts': 3.716.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/property-provider': 3.1.11 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-bucket-endpoint@3.709.0': + '@aws-sdk/middleware-bucket-endpoint@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@aws-sdk/util-arn-parser': 3.693.0 '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 @@ -4491,20 +4640,20 @@ snapshots: '@smithy/util-config-provider': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.709.0': + '@aws-sdk/middleware-expect-continue@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.709.0': + '@aws-sdk/middleware-flexible-checksums@3.717.0': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/is-array-buffer': 3.0.0 '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 @@ -4514,42 +4663,42 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.709.0': + '@aws-sdk/middleware-host-header@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.709.0': + '@aws-sdk/middleware-location-constraint@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.709.0': + '@aws-sdk/middleware-logger@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.709.0': + '@aws-sdk/middleware-recursion-detection@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.709.0': + '@aws-sdk/middleware-sdk-s3@3.716.0': dependencies: - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 '@aws-sdk/util-arn-parser': 3.693.0 '@smithy/core': 2.5.5 '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.11 @@ -4557,50 +4706,50 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.709.0': + '@aws-sdk/middleware-ssec@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.709.0': + '@aws-sdk/middleware-user-agent@3.716.0': dependencies: - '@aws-sdk/core': 3.709.0 - '@aws-sdk/types': 3.709.0 - '@aws-sdk/util-endpoints': 3.709.0 + '@aws-sdk/core': 3.716.0 + '@aws-sdk/types': 3.714.0 + '@aws-sdk/util-endpoints': 3.714.0 '@smithy/core': 2.5.5 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/region-config-resolver@3.709.0': + '@aws-sdk/region-config-resolver@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.709.0': + '@aws-sdk/signature-v4-multi-region@3.716.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/middleware-sdk-s3': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/token-providers@3.709.0(@aws-sdk/client-sso-oidc@3.712.0(@aws-sdk/client-sts@3.712.0))': + '@aws-sdk/token-providers@3.714.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))': dependencies: - '@aws-sdk/client-sso-oidc': 3.712.0(@aws-sdk/client-sts@3.712.0) - '@aws-sdk/types': 3.709.0 + '@aws-sdk/client-sso-oidc': 3.716.0(@aws-sdk/client-sts@3.716.0) + '@aws-sdk/types': 3.714.0 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 - '@aws-sdk/types@3.709.0': + '@aws-sdk/types@3.714.0': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -4609,9 +4758,9 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.709.0': + '@aws-sdk/util-endpoints@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/types': 3.7.2 '@smithy/util-endpoints': 2.1.7 tslib: 2.8.1 @@ -4620,17 +4769,17 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.709.0': + '@aws-sdk/util-user-agent-browser@3.714.0': dependencies: - '@aws-sdk/types': 3.709.0 + '@aws-sdk/types': 3.714.0 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.712.0': + '@aws-sdk/util-user-agent-node@3.716.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.709.0 - '@aws-sdk/types': 3.709.0 + '@aws-sdk/middleware-user-agent': 3.716.0 + '@aws-sdk/types': 3.714.0 '@smithy/node-config-provider': 3.1.12 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -4737,6 +4886,9 @@ snapshots: '@esbuild/aix-ppc64@0.23.1': optional: true + '@esbuild/aix-ppc64@0.24.0': + optional: true + '@esbuild/aix-ppc64@0.24.2': optional: true @@ -4749,6 +4901,9 @@ snapshots: '@esbuild/android-arm64@0.23.1': optional: true + '@esbuild/android-arm64@0.24.0': + optional: true + '@esbuild/android-arm64@0.24.2': optional: true @@ -4761,6 +4916,9 @@ snapshots: '@esbuild/android-arm@0.23.1': optional: true + '@esbuild/android-arm@0.24.0': + optional: true + '@esbuild/android-arm@0.24.2': optional: true @@ -4773,6 +4931,9 @@ snapshots: '@esbuild/android-x64@0.23.1': optional: true + '@esbuild/android-x64@0.24.0': + optional: true + '@esbuild/android-x64@0.24.2': optional: true @@ -4785,6 +4946,9 @@ snapshots: '@esbuild/darwin-arm64@0.23.1': optional: true + '@esbuild/darwin-arm64@0.24.0': + optional: true + '@esbuild/darwin-arm64@0.24.2': optional: true @@ -4797,6 +4961,9 @@ snapshots: '@esbuild/darwin-x64@0.23.1': optional: true + '@esbuild/darwin-x64@0.24.0': + optional: true + '@esbuild/darwin-x64@0.24.2': optional: true @@ -4809,6 +4976,9 @@ snapshots: '@esbuild/freebsd-arm64@0.23.1': optional: true + '@esbuild/freebsd-arm64@0.24.0': + optional: true + '@esbuild/freebsd-arm64@0.24.2': optional: true @@ -4821,6 +4991,9 @@ snapshots: '@esbuild/freebsd-x64@0.23.1': optional: true + '@esbuild/freebsd-x64@0.24.0': + optional: true + '@esbuild/freebsd-x64@0.24.2': optional: true @@ -4833,6 +5006,9 @@ snapshots: '@esbuild/linux-arm64@0.23.1': optional: true + '@esbuild/linux-arm64@0.24.0': + optional: true + '@esbuild/linux-arm64@0.24.2': optional: true @@ -4845,6 +5021,9 @@ snapshots: '@esbuild/linux-arm@0.23.1': optional: true + '@esbuild/linux-arm@0.24.0': + optional: true + '@esbuild/linux-arm@0.24.2': optional: true @@ -4857,6 +5036,9 @@ snapshots: '@esbuild/linux-ia32@0.23.1': optional: true + '@esbuild/linux-ia32@0.24.0': + optional: true + '@esbuild/linux-ia32@0.24.2': optional: true @@ -4869,6 +5051,9 @@ snapshots: '@esbuild/linux-loong64@0.23.1': optional: true + '@esbuild/linux-loong64@0.24.0': + optional: true + '@esbuild/linux-loong64@0.24.2': optional: true @@ -4881,6 +5066,9 @@ snapshots: '@esbuild/linux-mips64el@0.23.1': optional: true + '@esbuild/linux-mips64el@0.24.0': + optional: true + '@esbuild/linux-mips64el@0.24.2': optional: true @@ -4893,6 +5081,9 @@ snapshots: '@esbuild/linux-ppc64@0.23.1': optional: true + '@esbuild/linux-ppc64@0.24.0': + optional: true + '@esbuild/linux-ppc64@0.24.2': optional: true @@ -4905,6 +5096,9 @@ snapshots: '@esbuild/linux-riscv64@0.23.1': optional: true + '@esbuild/linux-riscv64@0.24.0': + optional: true + '@esbuild/linux-riscv64@0.24.2': optional: true @@ -4917,6 +5111,9 @@ snapshots: '@esbuild/linux-s390x@0.23.1': optional: true + '@esbuild/linux-s390x@0.24.0': + optional: true + '@esbuild/linux-s390x@0.24.2': optional: true @@ -4929,6 +5126,9 @@ snapshots: '@esbuild/linux-x64@0.23.1': optional: true + '@esbuild/linux-x64@0.24.0': + optional: true + '@esbuild/linux-x64@0.24.2': optional: true @@ -4944,12 +5144,18 @@ snapshots: '@esbuild/netbsd-x64@0.23.1': optional: true + '@esbuild/netbsd-x64@0.24.0': + optional: true + '@esbuild/netbsd-x64@0.24.2': optional: true '@esbuild/openbsd-arm64@0.23.1': optional: true + '@esbuild/openbsd-arm64@0.24.0': + optional: true + '@esbuild/openbsd-arm64@0.24.2': optional: true @@ -4962,6 +5168,9 @@ snapshots: '@esbuild/openbsd-x64@0.23.1': optional: true + '@esbuild/openbsd-x64@0.24.0': + optional: true + '@esbuild/openbsd-x64@0.24.2': optional: true @@ -4974,6 +5183,9 @@ snapshots: '@esbuild/sunos-x64@0.23.1': optional: true + '@esbuild/sunos-x64@0.24.0': + optional: true + '@esbuild/sunos-x64@0.24.2': optional: true @@ -4986,6 +5198,9 @@ snapshots: '@esbuild/win32-arm64@0.23.1': optional: true + '@esbuild/win32-arm64@0.24.0': + optional: true + '@esbuild/win32-arm64@0.24.2': optional: true @@ -4998,6 +5213,9 @@ snapshots: '@esbuild/win32-ia32@0.23.1': optional: true + '@esbuild/win32-ia32@0.24.0': + optional: true + '@esbuild/win32-ia32@0.24.2': optional: true @@ -5010,6 +5228,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true + '@esbuild/win32-x64@0.24.0': + optional: true + '@esbuild/win32-x64@0.24.2': optional: true @@ -5468,7 +5689,7 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/middleware-endpoint@3.2.5': + '@smithy/middleware-endpoint@3.2.6': dependencies: '@smithy/core': 2.5.5 '@smithy/middleware-serde': 3.0.11 @@ -5479,12 +5700,12 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/middleware-retry@3.0.30': + '@smithy/middleware-retry@3.0.31': dependencies: '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/service-error-classification': 3.0.11 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -5557,10 +5778,10 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/smithy-client@3.5.0': + '@smithy/smithy-client@3.5.1': dependencies: '@smithy/core': 2.5.5 - '@smithy/middleware-endpoint': 3.2.5 + '@smithy/middleware-endpoint': 3.2.6 '@smithy/middleware-stack': 3.0.11 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 @@ -5605,21 +5826,21 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@3.0.30': + '@smithy/util-defaults-mode-browser@3.0.31': dependencies: '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@3.0.30': + '@smithy/util-defaults-mode-node@3.0.31': dependencies: '@smithy/config-resolver': 3.0.13 '@smithy/credential-provider-imds': 3.2.8 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.0 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -6640,6 +6861,33 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + esbuild@0.24.2: optionalDependencies: '@esbuild/aix-ppc64': 0.24.2 @@ -8543,7 +8791,7 @@ snapshots: vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: - esbuild: 0.24.2 + esbuild: 0.24.0 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: From ba7efebfeec83b204072e54241823bff76ae7308 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:51:08 +0000 Subject: [PATCH 68/83] chore(deps): bump @adviser/cement from 0.2.41 to 0.2.44 Bumps [@adviser/cement](https://github.com/mabels/cement) from 0.2.41 to 0.2.44. - [Commits](https://github.com/mabels/cement/compare/v0.2.41...v0.2.44) --- updated-dependencies: - dependency-name: "@adviser/cement" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 6 +----- pnpm-lock.yaml | 49 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index e53ed2b6..6e2832b0 100644 --- a/package.json +++ b/package.json @@ -93,17 +93,13 @@ }, "dependencies": { "@adviser/cement": "^0.3.0", - "@aws-sdk/client-s3": "^3.705.0", + "@aws-sdk/client-s3": "^3.717.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", "@fireproof/core": "^0.19.119", "@fireproof/vendor": "^1.0.0", "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", - "@adviser/cement": "^0.2.41", - "@aws-sdk/client-s3": "^3.717.0", - "@fireproof/core": "0.19.118", - "@fireproof/vendor": "1.0.0", "@ipld/dag-ucan": "^3.4.0", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b5634bf5..ac500b1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.2.41 - version: 0.2.41(typescript@5.7.2) + specifier: ^0.3.0 + version: 0.3.4(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.717.0 version: 3.717.0 @@ -21,10 +21,10 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: 0.19.118 - version: 0.19.118(react@18.3.1)(typescript@5.7.2) + specifier: ^0.19.119 + version: 0.19.121(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': - specifier: 1.0.0 + specifier: ^1.0.0 version: 1.0.0 '@hono/node-server': specifier: ^1.13.7 @@ -216,9 +216,9 @@ importers: packages: - '@adviser/cement@0.2.41': - resolution: {integrity: sha512-Vam1JYxC1lOSkJZJa7CQJWL7jbjkPw5MzhYxMGWjLIK5l3tKDk5Q4SeLVEvPp2xhRGiBBzE9rZrQdt+0GtefFA==} - engines: {node: '>=16'} + '@adviser/cement@0.3.4': + resolution: {integrity: sha512-wG0rIHej2uvXGknp0mokM/8reXXtFg9wiWDzuXXmaxzjaae4cVG4og76SeQf9suWb+MiyPsn19B7HX+gFvIs7A==} + engines: {node: '>=20'} '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} @@ -1254,14 +1254,17 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@fireproof/core@0.19.118': - resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} + '@fireproof/core@0.19.121': + resolution: {integrity: sha512-HTHM9MXPEvby66h2I4zGT7VqFVpJMzcd3xiGeInzAwwO8mFB5ZQ6ic/i/P+5R6iN0ZNucGMKVOUAh2+XysxmHQ==} peerDependencies: react: ^18.3.1 '@fireproof/vendor@1.0.0': resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} + '@fireproof/vendor@1.0.4': + resolution: {integrity: sha512-F8yYaYGRNrtYo4KyMzMuKwI5mGieYMkI23KnYkQ3ixKhIu3J6qRGZsuROFjOv2zWjQvtPronvqyxNc9P5km31g==} + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -4275,7 +4278,7 @@ packages: snapshots: - '@adviser/cement@0.2.41(typescript@5.7.2)': + '@adviser/cement@0.3.4(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -5275,10 +5278,10 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': + '@fireproof/core@0.19.121(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.2.41(typescript@5.7.2) - '@fireproof/vendor': 1.0.0 + '@adviser/cement': 0.3.4(typescript@5.7.2) + '@fireproof/vendor': 1.0.4 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 idb: 8.0.1 @@ -5310,6 +5313,24 @@ snapshots: progress-events: 1.0.1 varint: 6.0.0 + '@fireproof/vendor@1.0.4': + dependencies: + '@ipld/dag-pb': 4.1.2 + '@multiformats/murmur3': 2.1.8 + hamt-sharding: 3.0.6 + interface-blockstore: 5.3.1 + ipfs-unixfs: 11.2.0 + it-filter: 3.1.1 + it-last: 3.0.6 + it-map: 3.1.1 + it-parallel: 3.0.8 + it-pipe: 3.0.1 + it-pushable: 3.2.3 + multiformats: 13.3.1 + p-queue: 8.0.1 + progress-events: 1.0.1 + varint: 6.0.0 + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': From 5d727b39edcc06621714e3d75ccdca938e35eb73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:50:34 +0000 Subject: [PATCH 69/83] chore(deps): bump @web3-storage/capabilities from 18.0.0 to 18.0.1 Bumps [@web3-storage/capabilities](https://github.com/storacha/w3up/tree/HEAD/packages/capabilities) from 18.0.0 to 18.0.1. - [Release notes](https://github.com/storacha/w3up/releases) - [Changelog](https://github.com/storacha/w3up/blob/main/packages/capabilities/CHANGELOG.md) - [Commits](https://github.com/storacha/w3up/commits/access-v18.0.1/packages/capabilities) --- updated-dependencies: - dependency-name: "@web3-storage/capabilities" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 19 +++---------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 6e2832b0..7317d637 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "@ucanto/transport": "^9.1.1", "@ucanto/validator": "^9.0.2", "@web3-storage/access": "^20.1.1", - "@web3-storage/capabilities": "^18.0.0", + "@web3-storage/capabilities": "^18.0.1", "@web3-storage/clock": "^0.4.1", "@web3-storage/did-mailto": "^2.1.0", "@web3-storage/pail": "^0.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac500b1f..fa646b0f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,8 +63,8 @@ importers: specifier: ^20.1.1 version: 20.1.1 '@web3-storage/capabilities': - specifier: ^18.0.0 - version: 18.0.0 + specifier: ^18.0.1 + version: 18.0.1 '@web3-storage/clock': specifier: ^0.4.1 version: 0.4.1 @@ -1907,9 +1907,6 @@ packages: resolution: {integrity: sha512-mhzupWeRfxLljoULcagU++mOmQOriCBMKniUhsmrCXrtRV8voF7op/ymqix1f9uX1M5iB93YXcfxAVBwGWWKoA==} engines: {node: '>=16.15'} - '@web3-storage/capabilities@18.0.0': - resolution: {integrity: sha512-sG0GmHrNNR+nT7wB1sIz91FG55PWJvrquMZyY8GD20r0l49kojDTlz/n14bEhof9uKE0T9KinmxitknOx/B+4Q==} - '@web3-storage/capabilities@18.0.1': resolution: {integrity: sha512-FLAUpuuFYkLrMkXy/W7iVNQdFlqGCZUrQr30L2C05SbQdpb/4tN6jqRG+l2nvAYTaYjWTYzsYLHGy2illsuNZQ==} @@ -6167,7 +6164,7 @@ snapshots: '@ucanto/principal': 9.0.1 '@ucanto/transport': 9.1.1 '@ucanto/validator': 9.0.2 - '@web3-storage/capabilities': 18.0.0 + '@web3-storage/capabilities': 18.0.1 '@web3-storage/did-mailto': 2.1.0 bigint-mod-arith: 3.3.1 conf: 11.0.2 @@ -6187,16 +6184,6 @@ snapshots: multiformats: 13.3.1 uint8arrays: 5.1.0 - '@web3-storage/capabilities@18.0.0': - dependencies: - '@ucanto/core': 10.0.1 - '@ucanto/interface': 10.0.1 - '@ucanto/principal': 9.0.1 - '@ucanto/transport': 9.1.1 - '@ucanto/validator': 9.0.2 - '@web3-storage/data-segment': 5.2.0 - uint8arrays: 5.1.0 - '@web3-storage/capabilities@18.0.1': dependencies: '@ucanto/core': 10.0.1 From ade8403a2d293c1a972fe2aa8a466d404429b1f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:17:48 +0000 Subject: [PATCH 70/83] chore(deps): bump node-sqlite3-wasm from 0.8.29 to 0.8.30 Bumps [node-sqlite3-wasm](https://github.com/tndrle/node-sqlite3-wasm) from 0.8.29 to 0.8.30. - [Release notes](https://github.com/tndrle/node-sqlite3-wasm/releases) - [Commits](https://github.com/tndrle/node-sqlite3-wasm/compare/v0.8.29...v0.8.30) --- updated-dependencies: - dependency-name: node-sqlite3-wasm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7317d637..5d376432 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "idb-keyval": "^6.2.1", "is-deep-strict-equal-x": "^1.1.2", "multiformats": "^13.3.1", - "node-sqlite3-wasm": "^0.8.29", + "node-sqlite3-wasm": "^0.8.30", "partykit": "^0.0.111", "partyserver": "^0.0.57", "partysocket": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa646b0f..69db7629 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,8 +108,8 @@ importers: specifier: ^13.3.1 version: 13.3.1 node-sqlite3-wasm: - specifier: ^0.8.29 - version: 0.8.29 + specifier: ^0.8.30 + version: 0.8.30 partykit: specifier: ^0.0.111 version: 0.0.111 @@ -3243,8 +3243,8 @@ packages: resolution: {integrity: sha512-U8xa/QBpNz/dc4BERBkMg//XTrBDcj0uIg5YDYPV4ChYgHPEw4JhoT5YWTxQuKBg/3C1kfkTO4MuEYw7fCYHJw==} engines: {node: '>=8'} - node-sqlite3-wasm@0.8.29: - resolution: {integrity: sha512-daoT9XIXCjW/Cg6YEGxdfod4wJMoHVuu4xDjHVWE7Zl45eiGkRBOErc73TYcO4rh02dDSFRDK7q7OUQnNXCrTQ==} + node-sqlite3-wasm@0.8.30: + resolution: {integrity: sha512-MU88q65ircWo4Xi/auv9hgZbAnxkSWuLDbzWPmwGgzWMmukQCrYejwvyivejGkjVmoHMdLA4BMXZvc/zimZjxQ==} noop-x@1.2.1: resolution: {integrity: sha512-X+jn3u2YhlAjteZIfrcVxaDLRfnrMvkzQ+jRatOX8UO7PFqU0QKlcyI2DhvLKEK2K4u1cRrZw9QqK3XruvyH2A==} @@ -7891,7 +7891,7 @@ snapshots: dependencies: big-integer: 1.6.52 - node-sqlite3-wasm@0.8.29: {} + node-sqlite3-wasm@0.8.30: {} noop-x@1.2.1: {} From 9112a8382e28a7304c3191bded4d58595398e33d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:51:21 +0000 Subject: [PATCH 71/83] chore(deps-dev): bump typescript-eslint from 8.18.0 to 8.18.1 Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.18.0 to 8.18.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.18.1/packages/typescript-eslint) --- updated-dependencies: - dependency-name: typescript-eslint dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 113 +++++++++++++++++-------------------------------- 2 files changed, 40 insertions(+), 75 deletions(-) diff --git a/package.json b/package.json index 5d376432..651fa76e 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "tsup": "^8.3.5", "tsx": "^4.19.2", "typescript": "^5.7.2", - "typescript-eslint": "^8.18.0", + "typescript-eslint": "^8.18.1", "vite": "^6.0.5", "vite-tsconfig-paths": "^5.1.4", "vitest": "^2.1.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69db7629..3135c1c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -193,8 +193,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 typescript-eslint: - specifier: ^8.18.0 - version: 8.18.0(eslint@9.17.0)(typescript@5.7.2) + specifier: ^8.18.1 + version: 8.18.1(eslint@9.17.0)(typescript@5.7.2) vite: specifier: ^6.0.5 version: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) @@ -1789,63 +1789,49 @@ packages: '@types/ws@8.5.13': resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@typescript-eslint/eslint-plugin@8.18.0': - resolution: {integrity: sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==} + '@typescript-eslint/eslint-plugin@8.18.1': + resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.18.0': - resolution: {integrity: sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==} + '@typescript-eslint/parser@8.18.1': + resolution: {integrity: sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.18.0': - resolution: {integrity: sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==} + '@typescript-eslint/scope-manager@8.18.1': + resolution: {integrity: sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.18.0': - resolution: {integrity: sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==} + '@typescript-eslint/type-utils@8.18.1': + resolution: {integrity: sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.18.0': - resolution: {integrity: sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.18.1': resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.18.0': - resolution: {integrity: sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/typescript-estree@8.18.1': resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.18.0': - resolution: {integrity: sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==} + '@typescript-eslint/utils@8.18.1': + resolution: {integrity: sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@8.18.0': - resolution: {integrity: sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.18.1': resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3956,8 +3942,8 @@ packages: type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - typescript-eslint@8.18.0: - resolution: {integrity: sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==} + typescript-eslint@8.18.1: + resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5966,14 +5952,14 @@ snapshots: dependencies: '@types/node': 22.10.2 - '@typescript-eslint/eslint-plugin@8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.18.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.18.0 - '@typescript-eslint/type-utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.0 + '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/type-utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.1 eslint: 9.17.0 graphemer: 1.4.0 ignore: 5.3.2 @@ -5983,27 +5969,27 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.18.0 - '@typescript-eslint/types': 8.18.0 - '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.0 + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.1 debug: 4.3.7 eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.18.0': + '@typescript-eslint/scope-manager@8.18.1': dependencies: - '@typescript-eslint/types': 8.18.0 - '@typescript-eslint/visitor-keys': 8.18.0 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/visitor-keys': 8.18.1 - '@typescript-eslint/type-utils@8.18.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) debug: 4.3.7 eslint: 9.17.0 ts-api-utils: 1.3.0(typescript@5.7.2) @@ -6011,24 +5997,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.18.0': {} - '@typescript-eslint/types@8.18.1': {} - '@typescript-eslint/typescript-estree@8.18.0(typescript@5.7.2)': - dependencies: - '@typescript-eslint/types': 8.18.0 - '@typescript-eslint/visitor-keys': 8.18.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.18.1(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.18.1 @@ -6043,22 +6013,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.18.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) - '@typescript-eslint/scope-manager': 8.18.0 - '@typescript-eslint/types': 8.18.0 - '@typescript-eslint/typescript-estree': 8.18.0(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.18.0': - dependencies: - '@typescript-eslint/types': 8.18.0 - eslint-visitor-keys: 4.2.0 - '@typescript-eslint/visitor-keys@8.18.1': dependencies: '@typescript-eslint/types': 8.18.1 @@ -8675,11 +8640,11 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.18.0(eslint@9.17.0)(typescript@5.7.2): + typescript-eslint@8.18.1(eslint@9.17.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.18.0(@typescript-eslint/parser@8.18.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.18.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: From 675c3474ad0a12f21a8bd496b8723edd3842518e Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 15 Nov 2024 09:20:11 +0100 Subject: [PATCH 72/83] chore: intro of local cloud tests chore: cloud now generated pre-signed-urls chore: fix signature chore: remove env version chore: remove console.log chore: now we have cloud-backend tests chore: the ng redirecting backend chore: everything except subscript chore: MsgConnection chore: Msger with connection tests chore: hono is our server platform chore: Get/Put/Delete.Data/WAL chore: refactor cloud test helper chore: added data/wal store tests chore: remove dotenv --- package.json | 6 + pnpm-lock.yaml | 846 +++++++++++++++++++++++++++---------------------- 2 files changed, 474 insertions(+), 378 deletions(-) diff --git a/package.json b/package.json index 651fa76e..b777e426 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,12 @@ "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@ipld/dag-ucan": "^3.4.0", + "@cloudflare/vitest-pool-workers": "^0.5.30", + "@cloudflare/workers-types": "^4.20241127.0", + "@fireproof/core": "^0.19.119", + "@fireproof/vendor": "^1.0.0", + "@hono/node-server": "^1.13.7", + "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3135c1c1..b6fa9a48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,20 +9,46 @@ importers: .: dependencies: '@adviser/cement': +<<<<<<< HEAD specifier: ^0.3.0 version: 0.3.4(typescript@5.7.2) +||||||| parent of b1f796c (chore: intro of local cloud tests) + specifier: ^0.2.44 + version: 0.2.44(typescript@5.7.2) +======= + specifier: ^0.2.44 + version: 0.2.45(typescript@5.7.2) +>>>>>>> b1f796c (chore: intro of local cloud tests) '@aws-sdk/client-s3': specifier: ^3.717.0 version: 3.717.0 +<<<<<<< HEAD '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/vitest-pool-workers': + specifier: ^0.5.30 + version: 0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) + '@cloudflare/workers-types': + specifier: ^4.20241127.0 + version: 4.20241205.0 +>>>>>>> b1f796c (chore: intro of local cloud tests) '@fireproof/core': +<<<<<<< HEAD specifier: ^0.19.119 version: 0.19.121(react@18.3.1)(typescript@5.7.2) +||||||| parent of b1f796c (chore: intro of local cloud tests) + specifier: 0.19.118 + version: 0.19.118(react@18.3.1)(typescript@5.7.2) +======= + specifier: ^0.19.119 + version: 0.19.119(react@18.3.1)(typescript@5.7.2) +>>>>>>> b1f796c (chore: intro of local cloud tests) '@fireproof/vendor': specifier: ^1.0.0 version: 1.0.0 @@ -161,7 +187,7 @@ importers: version: 8.5.13 '@typescript-eslint/typescript-estree': specifier: ^8.18.1 - version: 8.18.1(typescript@5.7.2) + version: 8.18.2(typescript@5.7.2) esbuild: specifier: ^0.24.2 version: 0.24.2 @@ -194,13 +220,13 @@ importers: version: 5.7.2 typescript-eslint: specifier: ^8.18.1 - version: 8.18.1(eslint@9.17.0)(typescript@5.7.2) + version: 8.18.2(eslint@9.17.0)(typescript@5.7.2) vite: specifier: ^6.0.5 - version: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + version: 6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.2) @@ -216,9 +242,23 @@ importers: packages: +<<<<<<< HEAD '@adviser/cement@0.3.4': resolution: {integrity: sha512-wG0rIHej2uvXGknp0mokM/8reXXtFg9wiWDzuXXmaxzjaae4cVG4og76SeQf9suWb+MiyPsn19B7HX+gFvIs7A==} engines: {node: '>=20'} +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@adviser/cement@0.2.44': + resolution: {integrity: sha512-IxmNkCSpST2FBeHqhk1RGxcb6pF8FZMSFbPpNUi0Drx3v219gNl5Q1gOQ2TWPqblTvMO942MqSE/QlgEppshgg==} + engines: {node: '>=16'} +======= + '@adviser/cement@0.2.45': + resolution: {integrity: sha512-322C+IWgUhjomzTKohy86maLoOASUf5ZrIAs01dfZF2NLey/6GlUi3vehR4MpDXo/8lceuvemVCw/wd7kmWOtg==} + engines: {node: '>=16'} +>>>>>>> b1f796c (chore: intro of local cloud tests) + + '@adviser/cement@0.3.3': + resolution: {integrity: sha512-yCkdozDJsqWF++f8CMTapDo5D/DZ5ssVSU/CRjxVe9pOngi8rWK/OWG8CIVVAQq+ODwWmBfy8OajF5l9wNEWUQ==} + engines: {node: '>=20'} '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} @@ -387,6 +427,7 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} +<<<<<<< HEAD '@cloudflare/vitest-pool-workers@0.5.34': resolution: {integrity: sha512-OoC51MBgz0z/SNG5GnvE9VAyBB/xxJODb7OazoWyZlMWe8HIGjg/Dti1hyn18dugJeIL6WiT11E90CLVbNl48g==} peerDependencies: @@ -394,18 +435,38 @@ packages: '@vitest/snapshot': 2.0.x - 2.1.x vitest: 2.0.x - 2.1.x +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/vitest-pool-workers@0.5.33': + resolution: {integrity: sha512-gsMArZ7fN9WB8blVIK8kVPXV8zI7JuoQN6n4grBYMmJgqfLrWE5N8NnEz0O5qagyLQJvD9TxD16WZOzVT/fbzw==} + peerDependencies: + '@vitest/runner': 2.0.x - 2.1.x + '@vitest/snapshot': 2.0.x - 2.1.x + vitest: 2.0.x - 2.1.x + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20240718.0': resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} engines: {node: '>=16'} cpu: [x64] os: [darwin] +<<<<<<< HEAD '@cloudflare/workerd-darwin-64@1.20241205.0': resolution: {integrity: sha512-TArEZkSZkHJyEwnlWWkSpCI99cF6lJ14OVeEoI9Um/+cD9CKZLM9vCmsLeKglKheJ0KcdCnkA+DbeD15t3VaWg==} engines: {node: '>=16'} cpu: [x64] os: [darwin] +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-darwin-64@1.20241106.2': + resolution: {integrity: sha512-p3PzgiMBp9xKo4dMINM1RkrC+miUtz65IuuMCEdCa5QZTM0eyEGcBj1A9/lmS3wW72oMfRTo6CxCkqPteFJeBA==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20241218.0': resolution: {integrity: sha512-8rveQoxtUvlmORKqTWgjv2ycM8uqWox0u9evn3zd2iWKdou5sncFwH517ZRLI3rq9P31ZLmCQBZ0gloFsTeY6w==} engines: {node: '>=16'} @@ -418,12 +479,22 @@ packages: cpu: [arm64] os: [darwin] +<<<<<<< HEAD '@cloudflare/workerd-darwin-arm64@1.20241205.0': resolution: {integrity: sha512-u5eqKa9QRdA8MugfgCoD+ADDjY6EpKbv3hSYJETmmUh17l7WXjWBzv4pUvOKIX67C0UzMUy4jZYwC53MymhX3w==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-darwin-arm64@1.20241106.2': + resolution: {integrity: sha512-AZQTAKG6bP9z0SKSXQGlXR2K2MQnDMtKC78NGjN0NOcjALTsFlLFhczaLvmuJjsT16k9yJUq2Gl+NG4ao/qgvg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-arm64@1.20241218.0': resolution: {integrity: sha512-be59Ad9nmM9lCkhHqmTs/uZ3JVZt8NJ9Z0PY+B0xnc5z6WwmV2lj0RVLtq7xJhQsQJA189zt5rXqDP6J+2mu7Q==} engines: {node: '>=16'} @@ -436,12 +507,22 @@ packages: cpu: [x64] os: [linux] +<<<<<<< HEAD '@cloudflare/workerd-linux-64@1.20241205.0': resolution: {integrity: sha512-OYA7S5zpumMamWEW+IhhBU6YojIEocyE5X/YFPiTOCrDE3dsfr9t6oqNE7hxGm1VAAu+Irtl+a/5LwmBOU681w==} engines: {node: '>=16'} cpu: [x64] os: [linux] +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-linux-64@1.20241106.2': + resolution: {integrity: sha512-TWIcVdUzU7w7YP2OEIgTDtNl9jyzjxOptjRDw7jhSUsQy/02IjBLP+ZnNpgB5CUJ1tCbcOp1L2IGhZmayd7OEQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-64@1.20241218.0': resolution: {integrity: sha512-MzpSBcfZXRxrYWxQ4pVDYDrUbkQuM62ssl4ZtHH8J35OAeGsWFAYji6MkS2SpVwVcvacPwJXIF4JSzp4xKImKw==} engines: {node: '>=16'} @@ -454,12 +535,22 @@ packages: cpu: [arm64] os: [linux] +<<<<<<< HEAD '@cloudflare/workerd-linux-arm64@1.20241205.0': resolution: {integrity: sha512-qAzecONjFJGIAVJZKExQ5dlbic0f3d4A+GdKa+H6SoUJtPaWiE3K6WuePo4JOT7W3/Zfh25McmX+MmpMUUcM5Q==} engines: {node: '>=16'} cpu: [arm64] os: [linux] +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-linux-arm64@1.20241106.2': + resolution: {integrity: sha512-f5Mn9IzfLs9yGjB2UCcKh+I7Ahiw6xqiQ9f/FGsHjsgLELjJ8JCKBwXmc9WdfNmVPae5jNCg2N5qVfDoWBKbCA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-arm64@1.20241218.0': resolution: {integrity: sha512-RIuJjPxpNqvwIs52vQsXeRMttvhIjgg9NLjjFa3jK8Ijnj8c3ZDru9Wqi48lJP07yDFIRr4uDMMqh/y29YQi2A==} engines: {node: '>=16'} @@ -472,22 +563,40 @@ packages: cpu: [x64] os: [win32] +<<<<<<< HEAD '@cloudflare/workerd-windows-64@1.20241205.0': resolution: {integrity: sha512-BEab+HiUgCdl6GXAT7EI2yaRtDPiRJlB94XLvRvXi1ZcmQqsrq6awGo6apctFo4WUL29V7c09LxmN4HQ3X2Tvg==} engines: {node: '>=16'} cpu: [x64] os: [win32] +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-windows-64@1.20241106.2': + resolution: {integrity: sha512-kdLExN3rktax23iHUKP7AHQP0HT0yGHik58fMP4kExjsMnwxw92TLI3n4HlmEqsbtMtwr9rhTJVaMBRUXq0aXw==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-windows-64@1.20241218.0': resolution: {integrity: sha512-tO1VjlvK3F6Yb2d1jgEy/QBYl//9Pyv3K0j+lq8Eu7qdfm0IgKwSRgDWLept84/qmNsQfausZ4JdNGxTf9xsxQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] +<<<<<<< HEAD '@cloudflare/workers-shared@0.10.0': resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} engines: {node: '>=16.7.0'} +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workers-shared@0.9.1': + resolution: {integrity: sha512-56w4pL5D6ODw7+SieMgdwrwNyyT7tY8H4UPD4/95TSBVjqDcMPq0Dr+D4rJ+nHK+290o4ZnSiOOiKqRMqy6tPg==} + engines: {node: '>=16.7.0'} + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} @@ -520,12 +629,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -550,12 +653,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.24.2': resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} @@ -580,12 +677,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.24.2': resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} @@ -610,12 +701,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.24.2': resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} @@ -640,12 +725,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.24.2': resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} @@ -670,12 +749,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.24.2': resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} @@ -700,12 +773,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.24.2': resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} @@ -730,12 +797,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.24.2': resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} @@ -760,12 +821,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.24.2': resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} @@ -790,12 +845,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.24.2': resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} @@ -820,12 +869,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.24.2': resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} @@ -850,12 +893,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.24.2': resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} @@ -880,12 +917,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.24.2': resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} @@ -910,12 +941,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.24.2': resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} @@ -940,12 +965,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.24.2': resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} @@ -970,12 +989,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.24.2': resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} @@ -1000,12 +1013,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.24.2': resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} @@ -1036,12 +1043,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.24.2': resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} @@ -1054,12 +1055,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.24.2': resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} @@ -1084,12 +1079,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.24.2': resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} @@ -1114,12 +1103,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.24.2': resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} @@ -1144,12 +1127,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.24.2': resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} @@ -1174,12 +1151,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.24.2': resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} @@ -1204,12 +1175,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.24.2': resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} @@ -1254,8 +1219,16 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} +<<<<<<< HEAD '@fireproof/core@0.19.121': resolution: {integrity: sha512-HTHM9MXPEvby66h2I4zGT7VqFVpJMzcd3xiGeInzAwwO8mFB5ZQ6ic/i/P+5R6iN0ZNucGMKVOUAh2+XysxmHQ==} +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@fireproof/core@0.19.118': + resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} +======= + '@fireproof/core@0.19.119': + resolution: {integrity: sha512-PSluwTsob3i5+tnrxGIQDNGsJJZ2xzs1uxAaBHyPoeo+wqoDkH86XTJTDpIR2SuL2RfMhX2t8EvtsF5sz4C8/Q==} +>>>>>>> b1f796c (chore: intro of local cloud tests) peerDependencies: react: ^18.3.1 @@ -1555,8 +1528,8 @@ packages: resolution: {integrity: sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==} engines: {node: '>=16.0.0'} - '@smithy/core@2.5.5': - resolution: {integrity: sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==} + '@smithy/core@2.5.6': + resolution: {integrity: sha512-w494xO+CPwG/5B/N2l0obHv2Fi9U4DAY+sTi1GWT3BVvGpZetJjJXAynIO9IHp4zS1PinGhXtRSZydUXbJO4ag==} engines: {node: '>=16.0.0'} '@smithy/credential-provider-imds@3.2.8': @@ -1614,12 +1587,12 @@ packages: resolution: {integrity: sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-endpoint@3.2.6': - resolution: {integrity: sha512-WAqzyulvvSKrT5c6VrQelgNVNNO7BlTQW9Z+s9tcG6G5CaBS1YBpPtT3VuhXLQbewSiGi7oXQROwpw26EG9PLQ==} + '@smithy/middleware-endpoint@3.2.7': + resolution: {integrity: sha512-GTxSKf280aJBANGN97MomUQhW1VNxZ6w7HAj/pvZM5MUHbMPOGnWOp1PRYKi4czMaHNj9bdiA+ZarmT3Wkdqiw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-retry@3.0.31': - resolution: {integrity: sha512-yq9wawrJLYHAYFpChLujxRN4My+SiKXvZk9Ml/CvTdRSA8ew+hvuR5LT+mjSlSBv3c4XJrkN8CWegkBaeD0Vrg==} + '@smithy/middleware-retry@3.0.32': + resolution: {integrity: sha512-v8gVA9HqibuZkFuFpfkC/EcHE8no/3Mv3JvRUGly63Axt4yyas1WDVOasFSdiqm2hZVpY7/k8mRT1Wd5k7r3Yw==} engines: {node: '>=16.0.0'} '@smithy/middleware-serde@3.0.11': @@ -1634,8 +1607,8 @@ packages: resolution: {integrity: sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==} engines: {node: '>=16.0.0'} - '@smithy/node-http-handler@3.3.2': - resolution: {integrity: sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==} + '@smithy/node-http-handler@3.3.3': + resolution: {integrity: sha512-BrpZOaZ4RCbcJ2igiSNG16S+kgAc65l/2hmxWdmhyoGWHTLlzQzr06PXavJp9OBlPEG/sHlqdxjWmjzV66+BSQ==} engines: {node: '>=16.0.0'} '@smithy/property-provider@3.1.11': @@ -1666,8 +1639,8 @@ packages: resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} - '@smithy/smithy-client@3.5.1': - resolution: {integrity: sha512-PmjskH4Os1Eh3rd5vSsa5uVelZ4DRu+N5CBEgb9AT96hQSJGWSEb6pGxKV/PtKQSIp9ft3+KvnT8ViMKaguzgA==} + '@smithy/smithy-client@3.5.2': + resolution: {integrity: sha512-h7xn+1wlpbXyLrtvo/teHR1SFGIIrQ3imzG0nz43zVLAJgvfC1Mtdwa1pFhoIOYrt/TiNjt4pD0gSYQEdZSBtg==} engines: {node: '>=16.0.0'} '@smithy/types@3.7.2': @@ -1700,12 +1673,12 @@ packages: resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} engines: {node: '>=16.0.0'} - '@smithy/util-defaults-mode-browser@3.0.31': - resolution: {integrity: sha512-eO+zkbqrPnmsagqzrmF7IJrCoU2wTQXWVYxMPqA9Oue55kw9WEvhyuw2XQzTVTCRcYsg6KgmV3YYhLlWQJfK1A==} + '@smithy/util-defaults-mode-browser@3.0.32': + resolution: {integrity: sha512-FAGsnm/xJ19SZeoqGyo9CosqjUlm+XJTmygDMktebvDKw3bKiIiZ40O1MA6Z52KLmekYU2GO7BEK7u6e7ZORKw==} engines: {node: '>= 10.0.0'} - '@smithy/util-defaults-mode-node@3.0.31': - resolution: {integrity: sha512-0/nJfpSpbGZOs6qs42wCe2TdjobbnnD4a3YUUlvTXSQqLy4qa63luDaV04hGvqSHP7wQ7/WGehbvHkDhMZd1MQ==} + '@smithy/util-defaults-mode-node@3.0.32': + resolution: {integrity: sha512-2CzKhkPFCVdd15f3+0D1rldNlvJME8pVRBtVVsea2hy7lcOn0bGB0dTVUwzgfM4LW/aU4IOg3jWf25ZWaxbOiw==} engines: {node: '>= 10.0.0'} '@smithy/util-endpoints@2.1.7': @@ -1724,8 +1697,8 @@ packages: resolution: {integrity: sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==} engines: {node: '>=16.0.0'} - '@smithy/util-stream@3.3.2': - resolution: {integrity: sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==} + '@smithy/util-stream@3.3.3': + resolution: {integrity: sha512-bOm0YMMxRjbI3X6QkWwADPFkh2AH2xBMQIB1IQgCsCRqXXpSJatgjUR3oxHthpYwFkw3WPkOt8VgMpJxC0rFqg==} engines: {node: '>=16.0.0'} '@smithy/util-uri-escape@3.0.0': @@ -1789,51 +1762,51 @@ packages: '@types/ws@8.5.13': resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@typescript-eslint/eslint-plugin@8.18.1': - resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==} + '@typescript-eslint/eslint-plugin@8.18.2': + resolution: {integrity: sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.18.1': - resolution: {integrity: sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==} + '@typescript-eslint/parser@8.18.2': + resolution: {integrity: sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.18.1': - resolution: {integrity: sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==} + '@typescript-eslint/scope-manager@8.18.2': + resolution: {integrity: sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.18.1': - resolution: {integrity: sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==} + '@typescript-eslint/type-utils@8.18.2': + resolution: {integrity: sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.18.1': - resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==} + '@typescript-eslint/types@8.18.2': + resolution: {integrity: sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.18.1': - resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==} + '@typescript-eslint/typescript-estree@8.18.2': + resolution: {integrity: sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.18.1': - resolution: {integrity: sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==} + '@typescript-eslint/utils@8.18.2': + resolution: {integrity: sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@8.18.1': - resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==} + '@typescript-eslint/visitor-keys@8.18.2': + resolution: {integrity: sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ucanto/client@9.0.1': @@ -2369,11 +2342,6 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.24.0: - resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.24.2: resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} @@ -3124,11 +3092,20 @@ packages: engines: {node: '>=16.13'} hasBin: true +<<<<<<< HEAD miniflare@3.20241205.0: resolution: {integrity: sha512-Z0cTtIf6ZrcAJ3SrOI9EUM3s4dkGhNeU6Ubl8sroYhsPVD+rtz3m5+p6McHFWCkcMff1o60X5XEKVTmkz0gbpA==} engines: {node: '>=16.13'} hasBin: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + miniflare@3.20241106.2: + resolution: {integrity: sha512-40JAPtNFMFrSW41CSxPgDykX4CgDokDfTZgDYYL8dsODb7pdAlj/dvlDPnaonkyXjRO7svyDwAavQT6IdagMwA==} + engines: {node: '>=16.13'} + hasBin: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) miniflare@3.20241218.0: resolution: {integrity: sha512-spYFDArH0wd+wJSTrzBrWrXJrbyJhRMJa35mat947y1jYhVV8I5V8vnD3LwjfpLr0SaEilojz1OIW7ekmnRe+w==} engines: {node: '>=16.13'} @@ -3942,8 +3919,8 @@ packages: type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - typescript-eslint@8.18.1: - resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==} + typescript-eslint@8.18.2: + resolution: {integrity: sha512-KuXezG6jHkvC3MvizeXgupZzaG5wjhU3yE8E7e6viOvAvD9xAWYp8/vy0WULTGe9DYDWcQu7aW03YIV3mSitrQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3976,6 +3953,9 @@ packages: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} + unenv-nightly@2.0.0-20241121-161142-806b5c0: + resolution: {integrity: sha512-RnFOasE/O0Q55gBkNB1b84OgKttgLEijGO0JCWpbn+O4XxpyCQg89NmcqQ5RGUiy4y+rMIrKzePTquQcLQF5pQ==} + unenv-nightly@2.0.0-20241204-140205-a5d5190: resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} @@ -4058,8 +4038,8 @@ packages: terser: optional: true - vite@6.0.5: - resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} + vite@6.0.6: + resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -4176,16 +4156,26 @@ packages: engines: {node: '>=16'} hasBin: true +<<<<<<< HEAD workerd@1.20241205.0: resolution: {integrity: sha512-vso/2n0c5SdBDWiD+Sx5gM7unA6SiZXRVUHDqH1euoP/9mFVHZF8icoYsNLB87b/TX8zNgpae+I5N/xFpd9v0g==} engines: {node: '>=16'} hasBin: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + workerd@1.20241106.2: + resolution: {integrity: sha512-Xw2hVIXA9MvDSHx3IX55ouGRPsQUzG0oadRVeQRs5xwgmiKshR0ompyYDO1JUvozJazfjcCSdgV8jyLcPqNIDA==} + engines: {node: '>=16'} + hasBin: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) workerd@1.20241218.0: resolution: {integrity: sha512-7Z3D4vOVChMz9mWDffE299oQxUWm/pbkeAWx1btVamPcAK/2IuoNBhwflWo3jyuKuxvYuFAdIucgYxc8ICqXiA==} engines: {node: '>=16'} hasBin: true +<<<<<<< HEAD wrangler@3.93.0: resolution: {integrity: sha512-+wfxjOrtm6YgDS+NdJkB6aiBIS3ED97mNRQmfrEShRJW4pVo4sWY6oQ1FsGT+j4tGHplrTbWCE6U5yTgjNW/lw==} engines: {node: '>=16.17.0'} @@ -4196,6 +4186,19 @@ packages: '@cloudflare/workers-types': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + wrangler@3.92.0: + resolution: {integrity: sha512-MC+s+stSYQKXEn7ucENhzrw+RyMc5bSIRQ2EVcjCtqjAtO82uKQBatW2YXK5hkQOZg9Kfcdqgkcnpf/Bn94FiA==} + engines: {node: '>=16.17.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20241106.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) wrangler@3.99.0: resolution: {integrity: sha512-k0x4rT3G/QCbxcoZY7CHRVlAIS8WMmKdga6lf4d2c3gXFqssh44vwlTDuARA9QANBxKJTcA7JPTJRfUDhd9QBA==} engines: {node: '>=16.17.0'} @@ -4261,7 +4264,20 @@ packages: snapshots: +<<<<<<< HEAD '@adviser/cement@0.3.4(typescript@5.7.2)': +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@adviser/cement@0.2.44(typescript@5.7.2)': +======= + '@adviser/cement@0.2.45(typescript@5.7.2)': + dependencies: + ts-essentials: 10.0.2(typescript@5.7.2) + yaml: 2.5.1 + transitivePeerDependencies: + - typescript + + '@adviser/cement@0.3.3(typescript@5.7.2)': +>>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4342,7 +4358,7 @@ snapshots: '@aws-sdk/util-user-agent-node': 3.716.0 '@aws-sdk/xml-builder': 3.709.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/eventstream-serde-browser': 3.0.14 '@smithy/eventstream-serde-config-resolver': 3.0.11 '@smithy/eventstream-serde-node': 3.0.13 @@ -4353,25 +4369,25 @@ snapshots: '@smithy/invalid-dependency': 3.0.11 '@smithy/md5-js': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.6 - '@smithy/middleware-retry': 3.0.31 + '@smithy/middleware-endpoint': 3.2.7 + '@smithy/middleware-retry': 3.0.32 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.31 - '@smithy/util-defaults-mode-node': 3.0.31 + '@smithy/util-defaults-mode-browser': 3.0.32 + '@smithy/util-defaults-mode-node': 3.0.32 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 - '@smithy/util-stream': 3.3.2 + '@smithy/util-stream': 3.3.3 '@smithy/util-utf8': 3.0.0 '@smithy/util-waiter': 3.2.0 tslib: 2.8.1 @@ -4395,26 +4411,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.6 - '@smithy/middleware-retry': 3.0.31 + '@smithy/middleware-endpoint': 3.2.7 + '@smithy/middleware-retry': 3.0.32 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.31 - '@smithy/util-defaults-mode-node': 3.0.31 + '@smithy/util-defaults-mode-browser': 3.0.32 + '@smithy/util-defaults-mode-node': 3.0.32 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4438,26 +4454,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.6 - '@smithy/middleware-retry': 3.0.31 + '@smithy/middleware-endpoint': 3.2.7 + '@smithy/middleware-retry': 3.0.32 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.31 - '@smithy/util-defaults-mode-node': 3.0.31 + '@smithy/util-defaults-mode-browser': 3.0.32 + '@smithy/util-defaults-mode-node': 3.0.32 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4483,26 +4499,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.6 - '@smithy/middleware-retry': 3.0.31 + '@smithy/middleware-endpoint': 3.2.7 + '@smithy/middleware-retry': 3.0.32 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.31 - '@smithy/util-defaults-mode-node': 3.0.31 + '@smithy/util-defaults-mode-browser': 3.0.32 + '@smithy/util-defaults-mode-node': 3.0.32 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4514,12 +4530,12 @@ snapshots: '@aws-sdk/core@3.716.0': dependencies: '@aws-sdk/types': 3.714.0 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 fast-xml-parser: 4.4.1 @@ -4538,13 +4554,21 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@smithy/fetch-http-handler': 4.1.2 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 +<<<<<<< HEAD '@smithy/util-stream': 3.3.2 tslib: 2.8.1 +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@smithy/util-stream': 3.3.2 + tslib: 2.7.0 +======= + '@smithy/util-stream': 3.3.3 + tslib: 2.8.1 +>>>>>>> b1f796c (chore: intro of local cloud tests) '@aws-sdk/credential-provider-ini@3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0)': dependencies: @@ -4645,7 +4669,7 @@ snapshots: '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.2 + '@smithy/util-stream': 3.3.3 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -4680,15 +4704,15 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@aws-sdk/util-arn-parser': 3.693.0 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.2 + '@smithy/util-stream': 3.3.3 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -4703,7 +4727,7 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@aws-sdk/util-endpoints': 3.714.0 - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -4779,6 +4803,7 @@ snapshots: dependencies: mime: 3.0.0 +<<<<<<< HEAD '@cloudflare/vitest-pool-workers@0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))': dependencies: '@vitest/runner': 2.1.8 @@ -4798,56 +4823,122 @@ snapshots: - supports-color - utf-8-validate +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/vitest-pool-workers@0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))': + dependencies: + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + birpc: 0.2.14 + cjs-module-lexer: 1.4.1 + devalue: 4.3.3 + esbuild: 0.17.19 + miniflare: 3.20241106.2 + semver: 7.6.3 + vitest: 2.1.8(@types/node@22.10.2) + wrangler: 3.92.0(@cloudflare/workers-types@4.20241205.0) + zod: 3.23.8 + transitivePeerDependencies: + - '@cloudflare/workers-types' + - bufferutil + - supports-color + - utf-8-validate + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20240718.0': optional: true +<<<<<<< HEAD '@cloudflare/workerd-darwin-64@1.20241205.0': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-darwin-64@1.20241106.2': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20241218.0': optional: true '@cloudflare/workerd-darwin-arm64@1.20240718.0': optional: true +<<<<<<< HEAD '@cloudflare/workerd-darwin-arm64@1.20241205.0': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-darwin-arm64@1.20241106.2': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-arm64@1.20241218.0': optional: true '@cloudflare/workerd-linux-64@1.20240718.0': optional: true +<<<<<<< HEAD '@cloudflare/workerd-linux-64@1.20241205.0': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-linux-64@1.20241106.2': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-64@1.20241218.0': optional: true '@cloudflare/workerd-linux-arm64@1.20240718.0': optional: true +<<<<<<< HEAD '@cloudflare/workerd-linux-arm64@1.20241205.0': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-linux-arm64@1.20241106.2': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-arm64@1.20241218.0': optional: true '@cloudflare/workerd-windows-64@1.20240718.0': optional: true +<<<<<<< HEAD '@cloudflare/workerd-windows-64@1.20241205.0': optional: true +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workerd-windows-64@1.20241106.2': + optional: true + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-windows-64@1.20241218.0': optional: true +<<<<<<< HEAD '@cloudflare/workers-shared@0.10.0': dependencies: mime: 3.0.0 zod: 3.23.8 +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + '@cloudflare/workers-shared@0.9.1': + dependencies: + mime: 3.0.0 + zod: 3.23.8 + +>>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workers-types@4.20240718.0': {} '@cloudflare/workers-types@4.20241205.0': {} @@ -4872,9 +4963,6 @@ snapshots: '@esbuild/aix-ppc64@0.23.1': optional: true - '@esbuild/aix-ppc64@0.24.0': - optional: true - '@esbuild/aix-ppc64@0.24.2': optional: true @@ -4887,9 +4975,6 @@ snapshots: '@esbuild/android-arm64@0.23.1': optional: true - '@esbuild/android-arm64@0.24.0': - optional: true - '@esbuild/android-arm64@0.24.2': optional: true @@ -4902,9 +4987,6 @@ snapshots: '@esbuild/android-arm@0.23.1': optional: true - '@esbuild/android-arm@0.24.0': - optional: true - '@esbuild/android-arm@0.24.2': optional: true @@ -4917,9 +4999,6 @@ snapshots: '@esbuild/android-x64@0.23.1': optional: true - '@esbuild/android-x64@0.24.0': - optional: true - '@esbuild/android-x64@0.24.2': optional: true @@ -4932,9 +5011,6 @@ snapshots: '@esbuild/darwin-arm64@0.23.1': optional: true - '@esbuild/darwin-arm64@0.24.0': - optional: true - '@esbuild/darwin-arm64@0.24.2': optional: true @@ -4947,9 +5023,6 @@ snapshots: '@esbuild/darwin-x64@0.23.1': optional: true - '@esbuild/darwin-x64@0.24.0': - optional: true - '@esbuild/darwin-x64@0.24.2': optional: true @@ -4962,9 +5035,6 @@ snapshots: '@esbuild/freebsd-arm64@0.23.1': optional: true - '@esbuild/freebsd-arm64@0.24.0': - optional: true - '@esbuild/freebsd-arm64@0.24.2': optional: true @@ -4977,9 +5047,6 @@ snapshots: '@esbuild/freebsd-x64@0.23.1': optional: true - '@esbuild/freebsd-x64@0.24.0': - optional: true - '@esbuild/freebsd-x64@0.24.2': optional: true @@ -4992,9 +5059,6 @@ snapshots: '@esbuild/linux-arm64@0.23.1': optional: true - '@esbuild/linux-arm64@0.24.0': - optional: true - '@esbuild/linux-arm64@0.24.2': optional: true @@ -5007,9 +5071,6 @@ snapshots: '@esbuild/linux-arm@0.23.1': optional: true - '@esbuild/linux-arm@0.24.0': - optional: true - '@esbuild/linux-arm@0.24.2': optional: true @@ -5022,9 +5083,6 @@ snapshots: '@esbuild/linux-ia32@0.23.1': optional: true - '@esbuild/linux-ia32@0.24.0': - optional: true - '@esbuild/linux-ia32@0.24.2': optional: true @@ -5037,9 +5095,6 @@ snapshots: '@esbuild/linux-loong64@0.23.1': optional: true - '@esbuild/linux-loong64@0.24.0': - optional: true - '@esbuild/linux-loong64@0.24.2': optional: true @@ -5052,9 +5107,6 @@ snapshots: '@esbuild/linux-mips64el@0.23.1': optional: true - '@esbuild/linux-mips64el@0.24.0': - optional: true - '@esbuild/linux-mips64el@0.24.2': optional: true @@ -5067,9 +5119,6 @@ snapshots: '@esbuild/linux-ppc64@0.23.1': optional: true - '@esbuild/linux-ppc64@0.24.0': - optional: true - '@esbuild/linux-ppc64@0.24.2': optional: true @@ -5082,9 +5131,6 @@ snapshots: '@esbuild/linux-riscv64@0.23.1': optional: true - '@esbuild/linux-riscv64@0.24.0': - optional: true - '@esbuild/linux-riscv64@0.24.2': optional: true @@ -5097,9 +5143,6 @@ snapshots: '@esbuild/linux-s390x@0.23.1': optional: true - '@esbuild/linux-s390x@0.24.0': - optional: true - '@esbuild/linux-s390x@0.24.2': optional: true @@ -5112,9 +5155,6 @@ snapshots: '@esbuild/linux-x64@0.23.1': optional: true - '@esbuild/linux-x64@0.24.0': - optional: true - '@esbuild/linux-x64@0.24.2': optional: true @@ -5130,18 +5170,12 @@ snapshots: '@esbuild/netbsd-x64@0.23.1': optional: true - '@esbuild/netbsd-x64@0.24.0': - optional: true - '@esbuild/netbsd-x64@0.24.2': optional: true '@esbuild/openbsd-arm64@0.23.1': optional: true - '@esbuild/openbsd-arm64@0.24.0': - optional: true - '@esbuild/openbsd-arm64@0.24.2': optional: true @@ -5154,9 +5188,6 @@ snapshots: '@esbuild/openbsd-x64@0.23.1': optional: true - '@esbuild/openbsd-x64@0.24.0': - optional: true - '@esbuild/openbsd-x64@0.24.2': optional: true @@ -5169,9 +5200,6 @@ snapshots: '@esbuild/sunos-x64@0.23.1': optional: true - '@esbuild/sunos-x64@0.24.0': - optional: true - '@esbuild/sunos-x64@0.24.2': optional: true @@ -5184,9 +5212,6 @@ snapshots: '@esbuild/win32-arm64@0.23.1': optional: true - '@esbuild/win32-arm64@0.24.0': - optional: true - '@esbuild/win32-arm64@0.24.2': optional: true @@ -5199,9 +5224,6 @@ snapshots: '@esbuild/win32-ia32@0.23.1': optional: true - '@esbuild/win32-ia32@0.24.0': - optional: true - '@esbuild/win32-ia32@0.24.2': optional: true @@ -5214,9 +5236,6 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@esbuild/win32-x64@0.24.0': - optional: true - '@esbuild/win32-x64@0.24.2': optional: true @@ -5261,10 +5280,24 @@ snapshots: '@fastify/busboy@2.1.1': {} +<<<<<<< HEAD '@fireproof/core@0.19.121(react@18.3.1)(typescript@5.7.2)': +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': +======= + '@fireproof/core@0.19.119(react@18.3.1)(typescript@5.7.2)': +>>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: +<<<<<<< HEAD '@adviser/cement': 0.3.4(typescript@5.7.2) '@fireproof/vendor': 1.0.4 +||||||| parent of b1f796c (chore: intro of local cloud tests) + '@adviser/cement': 0.2.44(typescript@5.7.2) + '@fireproof/vendor': 1.0.0 +======= + '@adviser/cement': 0.3.3(typescript@5.7.2) + '@fireproof/vendor': 1.0.0 +>>>>>>> b1f796c (chore: intro of local cloud tests) '@ipld/unixfs': 3.0.0 charwise: 3.0.1 idb: 8.0.1 @@ -5591,14 +5624,14 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/core@2.5.5': + '@smithy/core@2.5.6': dependencies: '@smithy/middleware-serde': 3.0.11 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.2 + '@smithy/util-stream': 3.3.3 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -5693,9 +5726,9 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/middleware-endpoint@3.2.6': + '@smithy/middleware-endpoint@3.2.7': dependencies: - '@smithy/core': 2.5.5 + '@smithy/core': 2.5.6 '@smithy/middleware-serde': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/shared-ini-file-loader': 3.1.12 @@ -5704,12 +5737,12 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/middleware-retry@3.0.31': + '@smithy/middleware-retry@3.0.32': dependencies: '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/service-error-classification': 3.0.11 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -5733,7 +5766,7 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/node-http-handler@3.3.2': + '@smithy/node-http-handler@3.3.3': dependencies: '@smithy/abort-controller': 3.1.9 '@smithy/protocol-http': 4.1.8 @@ -5782,19 +5815,27 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/smithy-client@3.5.1': + '@smithy/smithy-client@3.5.2': dependencies: - '@smithy/core': 2.5.5 - '@smithy/middleware-endpoint': 3.2.6 + '@smithy/core': 2.5.6 + '@smithy/middleware-endpoint': 3.2.7 '@smithy/middleware-stack': 3.0.11 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 +<<<<<<< HEAD + '@smithy/util-stream': 3.3.2 + tslib: 2.8.1 +||||||| parent of b1f796c (chore: intro of local cloud tests) '@smithy/util-stream': 3.3.2 + tslib: 2.7.0 +======= + '@smithy/util-stream': 3.3.3 tslib: 2.8.1 +>>>>>>> b1f796c (chore: intro of local cloud tests) '@smithy/types@3.7.2': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@smithy/url-parser@3.0.11': dependencies: @@ -5830,21 +5871,21 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@3.0.31': + '@smithy/util-defaults-mode-browser@3.0.32': dependencies: '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@3.0.31': + '@smithy/util-defaults-mode-node@3.0.32': dependencies: '@smithy/config-resolver': 3.0.13 '@smithy/credential-provider-imds': 3.2.8 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.1 + '@smithy/smithy-client': 3.5.2 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5869,10 +5910,10 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-stream@3.3.2': + '@smithy/util-stream@3.3.3': dependencies: '@smithy/fetch-http-handler': 4.1.2 - '@smithy/node-http-handler': 3.3.2 + '@smithy/node-http-handler': 3.3.3 '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 '@smithy/util-buffer-from': 3.0.0 @@ -5952,14 +5993,14 @@ snapshots: dependencies: '@types/node': 22.10.2 - '@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.18.2(@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/type-utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/parser': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.2 + '@typescript-eslint/type-utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.2 eslint: 9.17.0 graphemer: 1.4.0 ignore: 5.3.2 @@ -5969,27 +6010,27 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/scope-manager': 8.18.2 + '@typescript-eslint/types': 8.18.2 + '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.2 debug: 4.3.7 eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.18.1': + '@typescript-eslint/scope-manager@8.18.2': dependencies: - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/types': 8.18.2 + '@typescript-eslint/visitor-keys': 8.18.2 - '@typescript-eslint/type-utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.18.2(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) debug: 4.3.7 eslint: 9.17.0 ts-api-utils: 1.3.0(typescript@5.7.2) @@ -5997,12 +6038,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.18.1': {} + '@typescript-eslint/types@8.18.2': {} - '@typescript-eslint/typescript-estree@8.18.1(typescript@5.7.2)': + '@typescript-eslint/typescript-estree@8.18.2(typescript@5.7.2)': dependencies: - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/types': 8.18.2 + '@typescript-eslint/visitor-keys': 8.18.2 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 @@ -6013,20 +6054,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.18.2(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.2 + '@typescript-eslint/types': 8.18.2 + '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.18.1': + '@typescript-eslint/visitor-keys@8.18.2': dependencies: - '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/types': 8.18.2 eslint-visitor-keys: 4.2.0 '@ucanto/client@9.0.1': @@ -6834,33 +6875,6 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 - esbuild@0.24.0: - optionalDependencies: - '@esbuild/aix-ppc64': 0.24.0 - '@esbuild/android-arm': 0.24.0 - '@esbuild/android-arm64': 0.24.0 - '@esbuild/android-x64': 0.24.0 - '@esbuild/darwin-arm64': 0.24.0 - '@esbuild/darwin-x64': 0.24.0 - '@esbuild/freebsd-arm64': 0.24.0 - '@esbuild/freebsd-x64': 0.24.0 - '@esbuild/linux-arm': 0.24.0 - '@esbuild/linux-arm64': 0.24.0 - '@esbuild/linux-ia32': 0.24.0 - '@esbuild/linux-loong64': 0.24.0 - '@esbuild/linux-mips64el': 0.24.0 - '@esbuild/linux-ppc64': 0.24.0 - '@esbuild/linux-riscv64': 0.24.0 - '@esbuild/linux-s390x': 0.24.0 - '@esbuild/linux-x64': 0.24.0 - '@esbuild/netbsd-x64': 0.24.0 - '@esbuild/openbsd-arm64': 0.24.0 - '@esbuild/openbsd-x64': 0.24.0 - '@esbuild/sunos-x64': 0.24.0 - '@esbuild/win32-arm64': 0.24.0 - '@esbuild/win32-ia32': 0.24.0 - '@esbuild/win32-x64': 0.24.0 - esbuild@0.24.2: optionalDependencies: '@esbuild/aix-ppc64': 0.24.2 @@ -7752,6 +7766,7 @@ snapshots: - supports-color - utf-8-validate +<<<<<<< HEAD miniflare@3.20241205.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -7771,6 +7786,28 @@ snapshots: - supports-color - utf-8-validate +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + miniflare@3.20241106.2: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.4 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20241106.2 + ws: 8.18.0 + youch: 3.3.4 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + +>>>>>>> b1f796c (chore: intro of local cloud tests) miniflare@3.20241218.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -8640,11 +8677,11 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.18.1(eslint@9.17.0)(typescript@5.7.2): + typescript-eslint@8.18.2(eslint@9.17.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 8.18.2(@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: @@ -8677,6 +8714,13 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 + unenv-nightly@2.0.0-20241121-161142-806b5c0: + dependencies: + defu: 6.1.4 + ohash: 1.1.4 + pathe: 1.1.2 + ufo: 1.5.4 + unenv-nightly@2.0.0-20241204-140205-a5d5190: dependencies: defu: 6.1.4 @@ -8742,13 +8786,13 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.2) optionalDependencies: - vite: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + vite: 6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -8762,9 +8806,9 @@ snapshots: '@types/node': 22.10.2 fsevents: 2.3.3 - vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): + vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: @@ -8874,6 +8918,7 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20240718.0 '@cloudflare/workerd-windows-64': 1.20240718.0 +<<<<<<< HEAD workerd@1.20241205.0: optionalDependencies: '@cloudflare/workerd-darwin-64': 1.20241205.0 @@ -8882,6 +8927,17 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241205.0 '@cloudflare/workerd-windows-64': 1.20241205.0 +||||||| parent of b1f796c (chore: intro of local cloud tests) +======= + workerd@1.20241106.2: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20241106.2 + '@cloudflare/workerd-darwin-arm64': 1.20241106.2 + '@cloudflare/workerd-linux-64': 1.20241106.2 + '@cloudflare/workerd-linux-arm64': 1.20241106.2 + '@cloudflare/workerd-windows-64': 1.20241106.2 + +>>>>>>> b1f796c (chore: intro of local cloud tests) workerd@1.20241218.0: optionalDependencies: '@cloudflare/workerd-darwin-64': 1.20241218.0 @@ -8890,6 +8946,7 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241218.0 '@cloudflare/workerd-windows-64': 1.20241218.0 +<<<<<<< HEAD wrangler@3.93.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -8919,6 +8976,39 @@ snapshots: - utf-8-validate wrangler@3.99.0(@cloudflare/workers-types@4.20241205.0): +||||||| parent of b1f796c (chore: intro of local cloud tests) + wrangler@3.99.0: +======= + wrangler@3.92.0(@cloudflare/workers-types@4.20241205.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.9.1 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 4.0.1 + date-fns: 4.1.0 + esbuild: 0.17.19 + itty-time: 1.0.6 + miniflare: 3.20241106.2 + nanoid: 3.3.7 + path-to-regexp: 6.3.0 + resolve: 1.22.8 + selfsigned: 2.4.1 + source-map: 0.6.1 + unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0 + workerd: 1.20241106.2 + xxhash-wasm: 1.0.2 + optionalDependencies: + '@cloudflare/workers-types': 4.20241205.0 + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + wrangler@3.99.0(@cloudflare/workers-types@4.20241205.0): +>>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: '@cloudflare/kv-asset-handler': 0.3.4 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) From aaa0cf4876b304bcc235f7ec23525a691da34907 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 2 Jan 2025 19:24:55 +0100 Subject: [PATCH 73/83] chore: sql implementation of meta-merge --- README.md | 10 + package.json | 11 +- pnpm-lock.yaml | 848 ++++++++---------- src/cloud/backend/wrangler.toml | 5 + src/cloud/client/index.ts | 2 +- src/cloud/meta-merger/create-schema-cli.ts | 9 + .../meta-merger/meta-by-tenant-ledger.ts | 158 ++++ src/cloud/meta-merger/meta-merger.test.ts | 120 +++ src/cloud/meta-merger/meta-merger.ts | 114 +++ src/cloud/meta-merger/meta-send.ts | 124 +++ src/cloud/meta-merger/sql-border.ts | 18 + src/cloud/meta-merger/tenant-ledger.ts | 58 ++ src/cloud/meta-merger/tenant.ts | 47 + src/cloud/msg-processor.ts | 259 ------ src/ucan/ucan-gateway.ts | 1 - tests/docker-compose.ts | 2 +- 16 files changed, 1046 insertions(+), 740 deletions(-) create mode 100644 src/cloud/meta-merger/create-schema-cli.ts create mode 100644 src/cloud/meta-merger/meta-by-tenant-ledger.ts create mode 100644 src/cloud/meta-merger/meta-merger.test.ts create mode 100644 src/cloud/meta-merger/meta-merger.ts create mode 100644 src/cloud/meta-merger/meta-send.ts create mode 100644 src/cloud/meta-merger/sql-border.ts create mode 100644 src/cloud/meta-merger/tenant-ledger.ts create mode 100644 src/cloud/meta-merger/tenant.ts delete mode 100644 src/cloud/msg-processor.ts diff --git a/README.md b/README.md index 89cebffa..b0545673 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,13 @@ To run a single test by its full name, you can use the `-t` flag followed by the ```console $ pnpm test-gateways --project partykit -t "should sync to an empty db" ``` + +Cloud Meta Merge Datastructure: + +1. PK(reqId,resId,tenant,ledger) accessed(date) (delete after x of time) +2. PK(tenant,ledger,reqId,resId) meta deliveryCount (delete if deiveryCount > y) + if meta is updated deliveryCount = 0 + +getMeta updates deliveryCount +getMeta on stream starts updates stream of resGetMeta +avoid subscribe method diff --git a/package.json b/package.json index b777e426..d69032df 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,6 @@ "wait-on": "^8.0.1", "wrangler": "^3.99.0", "ws": "^8.18.0", - "vitest": "^2.1.8", "zx": "^8.2.4" }, "repository": { @@ -89,10 +88,10 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.3.0" + "@adviser/cement": "^0.3.2" }, "dependencies": { - "@adviser/cement": "^0.3.0", + "@adviser/cement": "^0.3.2", "@aws-sdk/client-s3": "^3.717.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", @@ -101,12 +100,6 @@ "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@ipld/dag-ucan": "^3.4.0", - "@cloudflare/vitest-pool-workers": "^0.5.30", - "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "^0.19.119", - "@fireproof/vendor": "^1.0.0", - "@hono/node-server": "^1.13.7", - "@hono/node-ws": "^1.0.4", "@jspm/core": "^2.1.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6fa9a48..c24bd33b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,46 +9,20 @@ importers: .: dependencies: '@adviser/cement': -<<<<<<< HEAD - specifier: ^0.3.0 + specifier: ^0.3.2 version: 0.3.4(typescript@5.7.2) -||||||| parent of b1f796c (chore: intro of local cloud tests) - specifier: ^0.2.44 - version: 0.2.44(typescript@5.7.2) -======= - specifier: ^0.2.44 - version: 0.2.45(typescript@5.7.2) ->>>>>>> b1f796c (chore: intro of local cloud tests) '@aws-sdk/client-s3': specifier: ^3.717.0 version: 3.717.0 -<<<<<<< HEAD '@cloudflare/vitest-pool-workers': specifier: ^0.5.30 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241205.0 -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/vitest-pool-workers': - specifier: ^0.5.30 - version: 0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) - '@cloudflare/workers-types': - specifier: ^4.20241127.0 - version: 4.20241205.0 ->>>>>>> b1f796c (chore: intro of local cloud tests) '@fireproof/core': -<<<<<<< HEAD specifier: ^0.19.119 version: 0.19.121(react@18.3.1)(typescript@5.7.2) -||||||| parent of b1f796c (chore: intro of local cloud tests) - specifier: 0.19.118 - version: 0.19.118(react@18.3.1)(typescript@5.7.2) -======= - specifier: ^0.19.119 - version: 0.19.119(react@18.3.1)(typescript@5.7.2) ->>>>>>> b1f796c (chore: intro of local cloud tests) '@fireproof/vendor': specifier: ^1.0.0 version: 1.0.0 @@ -187,7 +161,7 @@ importers: version: 8.5.13 '@typescript-eslint/typescript-estree': specifier: ^8.18.1 - version: 8.18.2(typescript@5.7.2) + version: 8.18.1(typescript@5.7.2) esbuild: specifier: ^0.24.2 version: 0.24.2 @@ -220,13 +194,13 @@ importers: version: 5.7.2 typescript-eslint: specifier: ^8.18.1 - version: 8.18.2(eslint@9.17.0)(typescript@5.7.2) + version: 8.18.1(eslint@9.17.0)(typescript@5.7.2) vite: specifier: ^6.0.5 - version: 6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + version: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)) vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.2) @@ -242,23 +216,9 @@ importers: packages: -<<<<<<< HEAD '@adviser/cement@0.3.4': resolution: {integrity: sha512-wG0rIHej2uvXGknp0mokM/8reXXtFg9wiWDzuXXmaxzjaae4cVG4og76SeQf9suWb+MiyPsn19B7HX+gFvIs7A==} engines: {node: '>=20'} -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@adviser/cement@0.2.44': - resolution: {integrity: sha512-IxmNkCSpST2FBeHqhk1RGxcb6pF8FZMSFbPpNUi0Drx3v219gNl5Q1gOQ2TWPqblTvMO942MqSE/QlgEppshgg==} - engines: {node: '>=16'} -======= - '@adviser/cement@0.2.45': - resolution: {integrity: sha512-322C+IWgUhjomzTKohy86maLoOASUf5ZrIAs01dfZF2NLey/6GlUi3vehR4MpDXo/8lceuvemVCw/wd7kmWOtg==} - engines: {node: '>=16'} ->>>>>>> b1f796c (chore: intro of local cloud tests) - - '@adviser/cement@0.3.3': - resolution: {integrity: sha512-yCkdozDJsqWF++f8CMTapDo5D/DZ5ssVSU/CRjxVe9pOngi8rWK/OWG8CIVVAQq+ODwWmBfy8OajF5l9wNEWUQ==} - engines: {node: '>=20'} '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} @@ -427,7 +387,6 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} -<<<<<<< HEAD '@cloudflare/vitest-pool-workers@0.5.34': resolution: {integrity: sha512-OoC51MBgz0z/SNG5GnvE9VAyBB/xxJODb7OazoWyZlMWe8HIGjg/Dti1hyn18dugJeIL6WiT11E90CLVbNl48g==} peerDependencies: @@ -435,38 +394,18 @@ packages: '@vitest/snapshot': 2.0.x - 2.1.x vitest: 2.0.x - 2.1.x -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/vitest-pool-workers@0.5.33': - resolution: {integrity: sha512-gsMArZ7fN9WB8blVIK8kVPXV8zI7JuoQN6n4grBYMmJgqfLrWE5N8NnEz0O5qagyLQJvD9TxD16WZOzVT/fbzw==} - peerDependencies: - '@vitest/runner': 2.0.x - 2.1.x - '@vitest/snapshot': 2.0.x - 2.1.x - vitest: 2.0.x - 2.1.x - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20240718.0': resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} engines: {node: '>=16'} cpu: [x64] os: [darwin] -<<<<<<< HEAD '@cloudflare/workerd-darwin-64@1.20241205.0': resolution: {integrity: sha512-TArEZkSZkHJyEwnlWWkSpCI99cF6lJ14OVeEoI9Um/+cD9CKZLM9vCmsLeKglKheJ0KcdCnkA+DbeD15t3VaWg==} engines: {node: '>=16'} cpu: [x64] os: [darwin] -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-darwin-64@1.20241106.2': - resolution: {integrity: sha512-p3PzgiMBp9xKo4dMINM1RkrC+miUtz65IuuMCEdCa5QZTM0eyEGcBj1A9/lmS3wW72oMfRTo6CxCkqPteFJeBA==} - engines: {node: '>=16'} - cpu: [x64] - os: [darwin] - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20241218.0': resolution: {integrity: sha512-8rveQoxtUvlmORKqTWgjv2ycM8uqWox0u9evn3zd2iWKdou5sncFwH517ZRLI3rq9P31ZLmCQBZ0gloFsTeY6w==} engines: {node: '>=16'} @@ -479,22 +418,12 @@ packages: cpu: [arm64] os: [darwin] -<<<<<<< HEAD '@cloudflare/workerd-darwin-arm64@1.20241205.0': resolution: {integrity: sha512-u5eqKa9QRdA8MugfgCoD+ADDjY6EpKbv3hSYJETmmUh17l7WXjWBzv4pUvOKIX67C0UzMUy4jZYwC53MymhX3w==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-darwin-arm64@1.20241106.2': - resolution: {integrity: sha512-AZQTAKG6bP9z0SKSXQGlXR2K2MQnDMtKC78NGjN0NOcjALTsFlLFhczaLvmuJjsT16k9yJUq2Gl+NG4ao/qgvg==} - engines: {node: '>=16'} - cpu: [arm64] - os: [darwin] - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-arm64@1.20241218.0': resolution: {integrity: sha512-be59Ad9nmM9lCkhHqmTs/uZ3JVZt8NJ9Z0PY+B0xnc5z6WwmV2lj0RVLtq7xJhQsQJA189zt5rXqDP6J+2mu7Q==} engines: {node: '>=16'} @@ -507,22 +436,12 @@ packages: cpu: [x64] os: [linux] -<<<<<<< HEAD '@cloudflare/workerd-linux-64@1.20241205.0': resolution: {integrity: sha512-OYA7S5zpumMamWEW+IhhBU6YojIEocyE5X/YFPiTOCrDE3dsfr9t6oqNE7hxGm1VAAu+Irtl+a/5LwmBOU681w==} engines: {node: '>=16'} cpu: [x64] os: [linux] -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-linux-64@1.20241106.2': - resolution: {integrity: sha512-TWIcVdUzU7w7YP2OEIgTDtNl9jyzjxOptjRDw7jhSUsQy/02IjBLP+ZnNpgB5CUJ1tCbcOp1L2IGhZmayd7OEQ==} - engines: {node: '>=16'} - cpu: [x64] - os: [linux] - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-64@1.20241218.0': resolution: {integrity: sha512-MzpSBcfZXRxrYWxQ4pVDYDrUbkQuM62ssl4ZtHH8J35OAeGsWFAYji6MkS2SpVwVcvacPwJXIF4JSzp4xKImKw==} engines: {node: '>=16'} @@ -535,22 +454,12 @@ packages: cpu: [arm64] os: [linux] -<<<<<<< HEAD '@cloudflare/workerd-linux-arm64@1.20241205.0': resolution: {integrity: sha512-qAzecONjFJGIAVJZKExQ5dlbic0f3d4A+GdKa+H6SoUJtPaWiE3K6WuePo4JOT7W3/Zfh25McmX+MmpMUUcM5Q==} engines: {node: '>=16'} cpu: [arm64] os: [linux] -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-linux-arm64@1.20241106.2': - resolution: {integrity: sha512-f5Mn9IzfLs9yGjB2UCcKh+I7Ahiw6xqiQ9f/FGsHjsgLELjJ8JCKBwXmc9WdfNmVPae5jNCg2N5qVfDoWBKbCA==} - engines: {node: '>=16'} - cpu: [arm64] - os: [linux] - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-arm64@1.20241218.0': resolution: {integrity: sha512-RIuJjPxpNqvwIs52vQsXeRMttvhIjgg9NLjjFa3jK8Ijnj8c3ZDru9Wqi48lJP07yDFIRr4uDMMqh/y29YQi2A==} engines: {node: '>=16'} @@ -563,40 +472,22 @@ packages: cpu: [x64] os: [win32] -<<<<<<< HEAD '@cloudflare/workerd-windows-64@1.20241205.0': resolution: {integrity: sha512-BEab+HiUgCdl6GXAT7EI2yaRtDPiRJlB94XLvRvXi1ZcmQqsrq6awGo6apctFo4WUL29V7c09LxmN4HQ3X2Tvg==} engines: {node: '>=16'} cpu: [x64] os: [win32] -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-windows-64@1.20241106.2': - resolution: {integrity: sha512-kdLExN3rktax23iHUKP7AHQP0HT0yGHik58fMP4kExjsMnwxw92TLI3n4HlmEqsbtMtwr9rhTJVaMBRUXq0aXw==} - engines: {node: '>=16'} - cpu: [x64] - os: [win32] - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-windows-64@1.20241218.0': resolution: {integrity: sha512-tO1VjlvK3F6Yb2d1jgEy/QBYl//9Pyv3K0j+lq8Eu7qdfm0IgKwSRgDWLept84/qmNsQfausZ4JdNGxTf9xsxQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] -<<<<<<< HEAD '@cloudflare/workers-shared@0.10.0': resolution: {integrity: sha512-j3EwZBc9ctavmFVOQT1gqztRO/Plx4ZR0LMEEOif+5YoCcuD1P7/NEjlODPMc5a1w+8+7A/H+Ci8Ihd55+x0Zw==} engines: {node: '>=16.7.0'} -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workers-shared@0.9.1': - resolution: {integrity: sha512-56w4pL5D6ODw7+SieMgdwrwNyyT7tY8H4UPD4/95TSBVjqDcMPq0Dr+D4rJ+nHK+290o4ZnSiOOiKqRMqy6tPg==} - engines: {node: '>=16.7.0'} - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workers-types@4.20240718.0': resolution: {integrity: sha512-7RqxXIM9HyhjfZ9ztXjITuc7mL0w4s+zXgypqKmMuvuObC3DgXutJ3bOYbQ+Ss5QbywrzWSNMlmGdL/ldg/yZg==} @@ -629,6 +520,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -653,6 +550,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.24.2': resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} @@ -677,6 +580,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.24.2': resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} @@ -701,6 +610,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.24.2': resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} @@ -725,6 +640,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.24.2': resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} @@ -749,6 +670,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.24.2': resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} @@ -773,6 +700,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} @@ -797,6 +730,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} @@ -821,6 +760,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.24.2': resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} @@ -845,6 +790,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.24.2': resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} @@ -869,6 +820,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.24.2': resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} @@ -893,6 +850,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.24.2': resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} @@ -917,6 +880,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.24.2': resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} @@ -941,6 +910,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.24.2': resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} @@ -965,6 +940,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.24.2': resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} @@ -989,6 +970,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.24.2': resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} @@ -1013,6 +1000,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.24.2': resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} @@ -1043,6 +1036,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} @@ -1055,6 +1054,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.24.2': resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} @@ -1079,6 +1084,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} @@ -1103,6 +1114,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.24.2': resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} @@ -1127,6 +1144,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.24.2': resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} @@ -1151,6 +1174,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.24.2': resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} @@ -1175,6 +1204,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.24.2': resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} @@ -1219,16 +1254,8 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} -<<<<<<< HEAD '@fireproof/core@0.19.121': resolution: {integrity: sha512-HTHM9MXPEvby66h2I4zGT7VqFVpJMzcd3xiGeInzAwwO8mFB5ZQ6ic/i/P+5R6iN0ZNucGMKVOUAh2+XysxmHQ==} -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@fireproof/core@0.19.118': - resolution: {integrity: sha512-lyK0Aj7t0acLz9x8i1s12GwBNkOuEeRPg5eS6MhMn5uYTi1p0kWvJHn+pb3hRFG5sP7zmjp5/obeHtTKGDTLGA==} -======= - '@fireproof/core@0.19.119': - resolution: {integrity: sha512-PSluwTsob3i5+tnrxGIQDNGsJJZ2xzs1uxAaBHyPoeo+wqoDkH86XTJTDpIR2SuL2RfMhX2t8EvtsF5sz4C8/Q==} ->>>>>>> b1f796c (chore: intro of local cloud tests) peerDependencies: react: ^18.3.1 @@ -1528,8 +1555,8 @@ packages: resolution: {integrity: sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==} engines: {node: '>=16.0.0'} - '@smithy/core@2.5.6': - resolution: {integrity: sha512-w494xO+CPwG/5B/N2l0obHv2Fi9U4DAY+sTi1GWT3BVvGpZetJjJXAynIO9IHp4zS1PinGhXtRSZydUXbJO4ag==} + '@smithy/core@2.5.5': + resolution: {integrity: sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==} engines: {node: '>=16.0.0'} '@smithy/credential-provider-imds@3.2.8': @@ -1587,12 +1614,12 @@ packages: resolution: {integrity: sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==} engines: {node: '>=16.0.0'} - '@smithy/middleware-endpoint@3.2.7': - resolution: {integrity: sha512-GTxSKf280aJBANGN97MomUQhW1VNxZ6w7HAj/pvZM5MUHbMPOGnWOp1PRYKi4czMaHNj9bdiA+ZarmT3Wkdqiw==} + '@smithy/middleware-endpoint@3.2.6': + resolution: {integrity: sha512-WAqzyulvvSKrT5c6VrQelgNVNNO7BlTQW9Z+s9tcG6G5CaBS1YBpPtT3VuhXLQbewSiGi7oXQROwpw26EG9PLQ==} engines: {node: '>=16.0.0'} - '@smithy/middleware-retry@3.0.32': - resolution: {integrity: sha512-v8gVA9HqibuZkFuFpfkC/EcHE8no/3Mv3JvRUGly63Axt4yyas1WDVOasFSdiqm2hZVpY7/k8mRT1Wd5k7r3Yw==} + '@smithy/middleware-retry@3.0.31': + resolution: {integrity: sha512-yq9wawrJLYHAYFpChLujxRN4My+SiKXvZk9Ml/CvTdRSA8ew+hvuR5LT+mjSlSBv3c4XJrkN8CWegkBaeD0Vrg==} engines: {node: '>=16.0.0'} '@smithy/middleware-serde@3.0.11': @@ -1607,8 +1634,8 @@ packages: resolution: {integrity: sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==} engines: {node: '>=16.0.0'} - '@smithy/node-http-handler@3.3.3': - resolution: {integrity: sha512-BrpZOaZ4RCbcJ2igiSNG16S+kgAc65l/2hmxWdmhyoGWHTLlzQzr06PXavJp9OBlPEG/sHlqdxjWmjzV66+BSQ==} + '@smithy/node-http-handler@3.3.2': + resolution: {integrity: sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==} engines: {node: '>=16.0.0'} '@smithy/property-provider@3.1.11': @@ -1639,8 +1666,8 @@ packages: resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} - '@smithy/smithy-client@3.5.2': - resolution: {integrity: sha512-h7xn+1wlpbXyLrtvo/teHR1SFGIIrQ3imzG0nz43zVLAJgvfC1Mtdwa1pFhoIOYrt/TiNjt4pD0gSYQEdZSBtg==} + '@smithy/smithy-client@3.5.1': + resolution: {integrity: sha512-PmjskH4Os1Eh3rd5vSsa5uVelZ4DRu+N5CBEgb9AT96hQSJGWSEb6pGxKV/PtKQSIp9ft3+KvnT8ViMKaguzgA==} engines: {node: '>=16.0.0'} '@smithy/types@3.7.2': @@ -1673,12 +1700,12 @@ packages: resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} engines: {node: '>=16.0.0'} - '@smithy/util-defaults-mode-browser@3.0.32': - resolution: {integrity: sha512-FAGsnm/xJ19SZeoqGyo9CosqjUlm+XJTmygDMktebvDKw3bKiIiZ40O1MA6Z52KLmekYU2GO7BEK7u6e7ZORKw==} + '@smithy/util-defaults-mode-browser@3.0.31': + resolution: {integrity: sha512-eO+zkbqrPnmsagqzrmF7IJrCoU2wTQXWVYxMPqA9Oue55kw9WEvhyuw2XQzTVTCRcYsg6KgmV3YYhLlWQJfK1A==} engines: {node: '>= 10.0.0'} - '@smithy/util-defaults-mode-node@3.0.32': - resolution: {integrity: sha512-2CzKhkPFCVdd15f3+0D1rldNlvJME8pVRBtVVsea2hy7lcOn0bGB0dTVUwzgfM4LW/aU4IOg3jWf25ZWaxbOiw==} + '@smithy/util-defaults-mode-node@3.0.31': + resolution: {integrity: sha512-0/nJfpSpbGZOs6qs42wCe2TdjobbnnD4a3YUUlvTXSQqLy4qa63luDaV04hGvqSHP7wQ7/WGehbvHkDhMZd1MQ==} engines: {node: '>= 10.0.0'} '@smithy/util-endpoints@2.1.7': @@ -1697,8 +1724,8 @@ packages: resolution: {integrity: sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==} engines: {node: '>=16.0.0'} - '@smithy/util-stream@3.3.3': - resolution: {integrity: sha512-bOm0YMMxRjbI3X6QkWwADPFkh2AH2xBMQIB1IQgCsCRqXXpSJatgjUR3oxHthpYwFkw3WPkOt8VgMpJxC0rFqg==} + '@smithy/util-stream@3.3.2': + resolution: {integrity: sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==} engines: {node: '>=16.0.0'} '@smithy/util-uri-escape@3.0.0': @@ -1762,51 +1789,51 @@ packages: '@types/ws@8.5.13': resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==} - '@typescript-eslint/eslint-plugin@8.18.2': - resolution: {integrity: sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==} + '@typescript-eslint/eslint-plugin@8.18.1': + resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.18.2': - resolution: {integrity: sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==} + '@typescript-eslint/parser@8.18.1': + resolution: {integrity: sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.18.2': - resolution: {integrity: sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==} + '@typescript-eslint/scope-manager@8.18.1': + resolution: {integrity: sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.18.2': - resolution: {integrity: sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==} + '@typescript-eslint/type-utils@8.18.1': + resolution: {integrity: sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.18.2': - resolution: {integrity: sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==} + '@typescript-eslint/types@8.18.1': + resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.18.2': - resolution: {integrity: sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==} + '@typescript-eslint/typescript-estree@8.18.1': + resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.18.2': - resolution: {integrity: sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==} + '@typescript-eslint/utils@8.18.1': + resolution: {integrity: sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@8.18.2': - resolution: {integrity: sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==} + '@typescript-eslint/visitor-keys@8.18.1': + resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ucanto/client@9.0.1': @@ -2342,6 +2369,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.24.2: resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} @@ -3092,20 +3124,11 @@ packages: engines: {node: '>=16.13'} hasBin: true -<<<<<<< HEAD miniflare@3.20241205.0: resolution: {integrity: sha512-Z0cTtIf6ZrcAJ3SrOI9EUM3s4dkGhNeU6Ubl8sroYhsPVD+rtz3m5+p6McHFWCkcMff1o60X5XEKVTmkz0gbpA==} engines: {node: '>=16.13'} hasBin: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - miniflare@3.20241106.2: - resolution: {integrity: sha512-40JAPtNFMFrSW41CSxPgDykX4CgDokDfTZgDYYL8dsODb7pdAlj/dvlDPnaonkyXjRO7svyDwAavQT6IdagMwA==} - engines: {node: '>=16.13'} - hasBin: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) miniflare@3.20241218.0: resolution: {integrity: sha512-spYFDArH0wd+wJSTrzBrWrXJrbyJhRMJa35mat947y1jYhVV8I5V8vnD3LwjfpLr0SaEilojz1OIW7ekmnRe+w==} engines: {node: '>=16.13'} @@ -3919,8 +3942,8 @@ packages: type@2.7.3: resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - typescript-eslint@8.18.2: - resolution: {integrity: sha512-KuXezG6jHkvC3MvizeXgupZzaG5wjhU3yE8E7e6viOvAvD9xAWYp8/vy0WULTGe9DYDWcQu7aW03YIV3mSitrQ==} + typescript-eslint@8.18.1: + resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3953,9 +3976,6 @@ packages: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} - unenv-nightly@2.0.0-20241121-161142-806b5c0: - resolution: {integrity: sha512-RnFOasE/O0Q55gBkNB1b84OgKttgLEijGO0JCWpbn+O4XxpyCQg89NmcqQ5RGUiy4y+rMIrKzePTquQcLQF5pQ==} - unenv-nightly@2.0.0-20241204-140205-a5d5190: resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} @@ -4038,8 +4058,8 @@ packages: terser: optional: true - vite@6.0.6: - resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==} + vite@6.0.5: + resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -4156,26 +4176,16 @@ packages: engines: {node: '>=16'} hasBin: true -<<<<<<< HEAD workerd@1.20241205.0: resolution: {integrity: sha512-vso/2n0c5SdBDWiD+Sx5gM7unA6SiZXRVUHDqH1euoP/9mFVHZF8icoYsNLB87b/TX8zNgpae+I5N/xFpd9v0g==} engines: {node: '>=16'} hasBin: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - workerd@1.20241106.2: - resolution: {integrity: sha512-Xw2hVIXA9MvDSHx3IX55ouGRPsQUzG0oadRVeQRs5xwgmiKshR0ompyYDO1JUvozJazfjcCSdgV8jyLcPqNIDA==} - engines: {node: '>=16'} - hasBin: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) workerd@1.20241218.0: resolution: {integrity: sha512-7Z3D4vOVChMz9mWDffE299oQxUWm/pbkeAWx1btVamPcAK/2IuoNBhwflWo3jyuKuxvYuFAdIucgYxc8ICqXiA==} engines: {node: '>=16'} hasBin: true -<<<<<<< HEAD wrangler@3.93.0: resolution: {integrity: sha512-+wfxjOrtm6YgDS+NdJkB6aiBIS3ED97mNRQmfrEShRJW4pVo4sWY6oQ1FsGT+j4tGHplrTbWCE6U5yTgjNW/lw==} engines: {node: '>=16.17.0'} @@ -4186,19 +4196,6 @@ packages: '@cloudflare/workers-types': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - wrangler@3.92.0: - resolution: {integrity: sha512-MC+s+stSYQKXEn7ucENhzrw+RyMc5bSIRQ2EVcjCtqjAtO82uKQBatW2YXK5hkQOZg9Kfcdqgkcnpf/Bn94FiA==} - engines: {node: '>=16.17.0'} - hasBin: true - peerDependencies: - '@cloudflare/workers-types': ^4.20241106.0 - peerDependenciesMeta: - '@cloudflare/workers-types': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) wrangler@3.99.0: resolution: {integrity: sha512-k0x4rT3G/QCbxcoZY7CHRVlAIS8WMmKdga6lf4d2c3gXFqssh44vwlTDuARA9QANBxKJTcA7JPTJRfUDhd9QBA==} engines: {node: '>=16.17.0'} @@ -4264,20 +4261,7 @@ packages: snapshots: -<<<<<<< HEAD '@adviser/cement@0.3.4(typescript@5.7.2)': -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@adviser/cement@0.2.44(typescript@5.7.2)': -======= - '@adviser/cement@0.2.45(typescript@5.7.2)': - dependencies: - ts-essentials: 10.0.2(typescript@5.7.2) - yaml: 2.5.1 - transitivePeerDependencies: - - typescript - - '@adviser/cement@0.3.3(typescript@5.7.2)': ->>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -4358,7 +4342,7 @@ snapshots: '@aws-sdk/util-user-agent-node': 3.716.0 '@aws-sdk/xml-builder': 3.709.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/eventstream-serde-browser': 3.0.14 '@smithy/eventstream-serde-config-resolver': 3.0.11 '@smithy/eventstream-serde-node': 3.0.13 @@ -4369,25 +4353,25 @@ snapshots: '@smithy/invalid-dependency': 3.0.11 '@smithy/md5-js': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.7 - '@smithy/middleware-retry': 3.0.32 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.32 - '@smithy/util-defaults-mode-node': 3.0.32 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 - '@smithy/util-stream': 3.3.3 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 '@smithy/util-waiter': 3.2.0 tslib: 2.8.1 @@ -4411,26 +4395,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.7 - '@smithy/middleware-retry': 3.0.32 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.32 - '@smithy/util-defaults-mode-node': 3.0.32 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4454,26 +4438,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.7 - '@smithy/middleware-retry': 3.0.32 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.32 - '@smithy/util-defaults-mode-node': 3.0.32 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4499,26 +4483,26 @@ snapshots: '@aws-sdk/util-user-agent-browser': 3.714.0 '@aws-sdk/util-user-agent-node': 3.716.0 '@smithy/config-resolver': 3.0.13 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/fetch-http-handler': 4.1.2 '@smithy/hash-node': 3.0.11 '@smithy/invalid-dependency': 3.0.11 '@smithy/middleware-content-length': 3.0.13 - '@smithy/middleware-endpoint': 3.2.7 - '@smithy/middleware-retry': 3.0.32 + '@smithy/middleware-endpoint': 3.2.6 + '@smithy/middleware-retry': 3.0.31 '@smithy/middleware-serde': 3.0.11 '@smithy/middleware-stack': 3.0.11 '@smithy/node-config-provider': 3.1.12 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/url-parser': 3.0.11 '@smithy/util-base64': 3.0.0 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.32 - '@smithy/util-defaults-mode-node': 3.0.32 + '@smithy/util-defaults-mode-browser': 3.0.31 + '@smithy/util-defaults-mode-node': 3.0.31 '@smithy/util-endpoints': 2.1.7 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -4530,12 +4514,12 @@ snapshots: '@aws-sdk/core@3.716.0': dependencies: '@aws-sdk/types': 3.714.0 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 fast-xml-parser: 4.4.1 @@ -4554,21 +4538,13 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@smithy/fetch-http-handler': 4.1.2 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/property-provider': 3.1.11 '@smithy/protocol-http': 4.1.8 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 -<<<<<<< HEAD '@smithy/util-stream': 3.3.2 tslib: 2.8.1 -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@smithy/util-stream': 3.3.2 - tslib: 2.7.0 -======= - '@smithy/util-stream': 3.3.3 - tslib: 2.8.1 ->>>>>>> b1f796c (chore: intro of local cloud tests) '@aws-sdk/credential-provider-ini@3.716.0(@aws-sdk/client-sso-oidc@3.716.0(@aws-sdk/client-sts@3.716.0))(@aws-sdk/client-sts@3.716.0)': dependencies: @@ -4669,7 +4645,7 @@ snapshots: '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.3 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -4704,15 +4680,15 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@aws-sdk/util-arn-parser': 3.693.0 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/signature-v4': 4.2.4 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.3 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -4727,7 +4703,7 @@ snapshots: '@aws-sdk/core': 3.716.0 '@aws-sdk/types': 3.714.0 '@aws-sdk/util-endpoints': 3.714.0 - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -4803,7 +4779,6 @@ snapshots: dependencies: mime: 3.0.0 -<<<<<<< HEAD '@cloudflare/vitest-pool-workers@0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))': dependencies: '@vitest/runner': 2.1.8 @@ -4823,122 +4798,56 @@ snapshots: - supports-color - utf-8-validate -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/vitest-pool-workers@0.5.33(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))': - dependencies: - '@vitest/runner': 2.1.8 - '@vitest/snapshot': 2.1.8 - birpc: 0.2.14 - cjs-module-lexer: 1.4.1 - devalue: 4.3.3 - esbuild: 0.17.19 - miniflare: 3.20241106.2 - semver: 7.6.3 - vitest: 2.1.8(@types/node@22.10.2) - wrangler: 3.92.0(@cloudflare/workers-types@4.20241205.0) - zod: 3.23.8 - transitivePeerDependencies: - - '@cloudflare/workers-types' - - bufferutil - - supports-color - - utf-8-validate - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20240718.0': optional: true -<<<<<<< HEAD '@cloudflare/workerd-darwin-64@1.20241205.0': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-darwin-64@1.20241106.2': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-64@1.20241218.0': optional: true '@cloudflare/workerd-darwin-arm64@1.20240718.0': optional: true -<<<<<<< HEAD '@cloudflare/workerd-darwin-arm64@1.20241205.0': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-darwin-arm64@1.20241106.2': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-darwin-arm64@1.20241218.0': optional: true '@cloudflare/workerd-linux-64@1.20240718.0': optional: true -<<<<<<< HEAD '@cloudflare/workerd-linux-64@1.20241205.0': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-linux-64@1.20241106.2': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-64@1.20241218.0': optional: true '@cloudflare/workerd-linux-arm64@1.20240718.0': optional: true -<<<<<<< HEAD '@cloudflare/workerd-linux-arm64@1.20241205.0': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-linux-arm64@1.20241106.2': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-linux-arm64@1.20241218.0': optional: true '@cloudflare/workerd-windows-64@1.20240718.0': optional: true -<<<<<<< HEAD '@cloudflare/workerd-windows-64@1.20241205.0': optional: true -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workerd-windows-64@1.20241106.2': - optional: true - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workerd-windows-64@1.20241218.0': optional: true -<<<<<<< HEAD '@cloudflare/workers-shared@0.10.0': dependencies: mime: 3.0.0 zod: 3.23.8 -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - '@cloudflare/workers-shared@0.9.1': - dependencies: - mime: 3.0.0 - zod: 3.23.8 - ->>>>>>> b1f796c (chore: intro of local cloud tests) '@cloudflare/workers-types@4.20240718.0': {} '@cloudflare/workers-types@4.20241205.0': {} @@ -4963,6 +4872,9 @@ snapshots: '@esbuild/aix-ppc64@0.23.1': optional: true + '@esbuild/aix-ppc64@0.24.0': + optional: true + '@esbuild/aix-ppc64@0.24.2': optional: true @@ -4975,6 +4887,9 @@ snapshots: '@esbuild/android-arm64@0.23.1': optional: true + '@esbuild/android-arm64@0.24.0': + optional: true + '@esbuild/android-arm64@0.24.2': optional: true @@ -4987,6 +4902,9 @@ snapshots: '@esbuild/android-arm@0.23.1': optional: true + '@esbuild/android-arm@0.24.0': + optional: true + '@esbuild/android-arm@0.24.2': optional: true @@ -4999,6 +4917,9 @@ snapshots: '@esbuild/android-x64@0.23.1': optional: true + '@esbuild/android-x64@0.24.0': + optional: true + '@esbuild/android-x64@0.24.2': optional: true @@ -5011,6 +4932,9 @@ snapshots: '@esbuild/darwin-arm64@0.23.1': optional: true + '@esbuild/darwin-arm64@0.24.0': + optional: true + '@esbuild/darwin-arm64@0.24.2': optional: true @@ -5023,6 +4947,9 @@ snapshots: '@esbuild/darwin-x64@0.23.1': optional: true + '@esbuild/darwin-x64@0.24.0': + optional: true + '@esbuild/darwin-x64@0.24.2': optional: true @@ -5035,6 +4962,9 @@ snapshots: '@esbuild/freebsd-arm64@0.23.1': optional: true + '@esbuild/freebsd-arm64@0.24.0': + optional: true + '@esbuild/freebsd-arm64@0.24.2': optional: true @@ -5047,6 +4977,9 @@ snapshots: '@esbuild/freebsd-x64@0.23.1': optional: true + '@esbuild/freebsd-x64@0.24.0': + optional: true + '@esbuild/freebsd-x64@0.24.2': optional: true @@ -5059,6 +4992,9 @@ snapshots: '@esbuild/linux-arm64@0.23.1': optional: true + '@esbuild/linux-arm64@0.24.0': + optional: true + '@esbuild/linux-arm64@0.24.2': optional: true @@ -5071,6 +5007,9 @@ snapshots: '@esbuild/linux-arm@0.23.1': optional: true + '@esbuild/linux-arm@0.24.0': + optional: true + '@esbuild/linux-arm@0.24.2': optional: true @@ -5083,6 +5022,9 @@ snapshots: '@esbuild/linux-ia32@0.23.1': optional: true + '@esbuild/linux-ia32@0.24.0': + optional: true + '@esbuild/linux-ia32@0.24.2': optional: true @@ -5095,6 +5037,9 @@ snapshots: '@esbuild/linux-loong64@0.23.1': optional: true + '@esbuild/linux-loong64@0.24.0': + optional: true + '@esbuild/linux-loong64@0.24.2': optional: true @@ -5107,6 +5052,9 @@ snapshots: '@esbuild/linux-mips64el@0.23.1': optional: true + '@esbuild/linux-mips64el@0.24.0': + optional: true + '@esbuild/linux-mips64el@0.24.2': optional: true @@ -5119,6 +5067,9 @@ snapshots: '@esbuild/linux-ppc64@0.23.1': optional: true + '@esbuild/linux-ppc64@0.24.0': + optional: true + '@esbuild/linux-ppc64@0.24.2': optional: true @@ -5131,6 +5082,9 @@ snapshots: '@esbuild/linux-riscv64@0.23.1': optional: true + '@esbuild/linux-riscv64@0.24.0': + optional: true + '@esbuild/linux-riscv64@0.24.2': optional: true @@ -5143,6 +5097,9 @@ snapshots: '@esbuild/linux-s390x@0.23.1': optional: true + '@esbuild/linux-s390x@0.24.0': + optional: true + '@esbuild/linux-s390x@0.24.2': optional: true @@ -5155,6 +5112,9 @@ snapshots: '@esbuild/linux-x64@0.23.1': optional: true + '@esbuild/linux-x64@0.24.0': + optional: true + '@esbuild/linux-x64@0.24.2': optional: true @@ -5170,12 +5130,18 @@ snapshots: '@esbuild/netbsd-x64@0.23.1': optional: true + '@esbuild/netbsd-x64@0.24.0': + optional: true + '@esbuild/netbsd-x64@0.24.2': optional: true '@esbuild/openbsd-arm64@0.23.1': optional: true + '@esbuild/openbsd-arm64@0.24.0': + optional: true + '@esbuild/openbsd-arm64@0.24.2': optional: true @@ -5188,6 +5154,9 @@ snapshots: '@esbuild/openbsd-x64@0.23.1': optional: true + '@esbuild/openbsd-x64@0.24.0': + optional: true + '@esbuild/openbsd-x64@0.24.2': optional: true @@ -5200,6 +5169,9 @@ snapshots: '@esbuild/sunos-x64@0.23.1': optional: true + '@esbuild/sunos-x64@0.24.0': + optional: true + '@esbuild/sunos-x64@0.24.2': optional: true @@ -5212,6 +5184,9 @@ snapshots: '@esbuild/win32-arm64@0.23.1': optional: true + '@esbuild/win32-arm64@0.24.0': + optional: true + '@esbuild/win32-arm64@0.24.2': optional: true @@ -5224,6 +5199,9 @@ snapshots: '@esbuild/win32-ia32@0.23.1': optional: true + '@esbuild/win32-ia32@0.24.0': + optional: true + '@esbuild/win32-ia32@0.24.2': optional: true @@ -5236,6 +5214,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true + '@esbuild/win32-x64@0.24.0': + optional: true + '@esbuild/win32-x64@0.24.2': optional: true @@ -5280,24 +5261,10 @@ snapshots: '@fastify/busboy@2.1.1': {} -<<<<<<< HEAD '@fireproof/core@0.19.121(react@18.3.1)(typescript@5.7.2)': -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@fireproof/core@0.19.118(react@18.3.1)(typescript@5.7.2)': -======= - '@fireproof/core@0.19.119(react@18.3.1)(typescript@5.7.2)': ->>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: -<<<<<<< HEAD '@adviser/cement': 0.3.4(typescript@5.7.2) '@fireproof/vendor': 1.0.4 -||||||| parent of b1f796c (chore: intro of local cloud tests) - '@adviser/cement': 0.2.44(typescript@5.7.2) - '@fireproof/vendor': 1.0.0 -======= - '@adviser/cement': 0.3.3(typescript@5.7.2) - '@fireproof/vendor': 1.0.0 ->>>>>>> b1f796c (chore: intro of local cloud tests) '@ipld/unixfs': 3.0.0 charwise: 3.0.1 idb: 8.0.1 @@ -5624,14 +5591,14 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/core@2.5.6': + '@smithy/core@2.5.5': dependencies: '@smithy/middleware-serde': 3.0.11 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 '@smithy/util-body-length-browser': 3.0.0 '@smithy/util-middleware': 3.0.11 - '@smithy/util-stream': 3.3.3 + '@smithy/util-stream': 3.3.2 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 @@ -5726,9 +5693,9 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/middleware-endpoint@3.2.7': + '@smithy/middleware-endpoint@3.2.6': dependencies: - '@smithy/core': 2.5.6 + '@smithy/core': 2.5.5 '@smithy/middleware-serde': 3.0.11 '@smithy/node-config-provider': 3.1.12 '@smithy/shared-ini-file-loader': 3.1.12 @@ -5737,12 +5704,12 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 - '@smithy/middleware-retry@3.0.32': + '@smithy/middleware-retry@3.0.31': dependencies: '@smithy/node-config-provider': 3.1.12 '@smithy/protocol-http': 4.1.8 '@smithy/service-error-classification': 3.0.11 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 '@smithy/util-middleware': 3.0.11 '@smithy/util-retry': 3.0.11 @@ -5766,7 +5733,7 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/node-http-handler@3.3.3': + '@smithy/node-http-handler@3.3.2': dependencies: '@smithy/abort-controller': 3.1.9 '@smithy/protocol-http': 4.1.8 @@ -5815,27 +5782,19 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 - '@smithy/smithy-client@3.5.2': + '@smithy/smithy-client@3.5.1': dependencies: - '@smithy/core': 2.5.6 - '@smithy/middleware-endpoint': 3.2.7 + '@smithy/core': 2.5.5 + '@smithy/middleware-endpoint': 3.2.6 '@smithy/middleware-stack': 3.0.11 '@smithy/protocol-http': 4.1.8 '@smithy/types': 3.7.2 -<<<<<<< HEAD - '@smithy/util-stream': 3.3.2 - tslib: 2.8.1 -||||||| parent of b1f796c (chore: intro of local cloud tests) '@smithy/util-stream': 3.3.2 - tslib: 2.7.0 -======= - '@smithy/util-stream': 3.3.3 tslib: 2.8.1 ->>>>>>> b1f796c (chore: intro of local cloud tests) '@smithy/types@3.7.2': dependencies: - tslib: 2.8.1 + tslib: 2.7.0 '@smithy/url-parser@3.0.11': dependencies: @@ -5871,21 +5830,21 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@3.0.32': + '@smithy/util-defaults-mode-browser@3.0.31': dependencies: '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 bowser: 2.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@3.0.32': + '@smithy/util-defaults-mode-node@3.0.31': dependencies: '@smithy/config-resolver': 3.0.13 '@smithy/credential-provider-imds': 3.2.8 '@smithy/node-config-provider': 3.1.12 '@smithy/property-provider': 3.1.11 - '@smithy/smithy-client': 3.5.2 + '@smithy/smithy-client': 3.5.1 '@smithy/types': 3.7.2 tslib: 2.8.1 @@ -5910,10 +5869,10 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 - '@smithy/util-stream@3.3.3': + '@smithy/util-stream@3.3.2': dependencies: '@smithy/fetch-http-handler': 4.1.2 - '@smithy/node-http-handler': 3.3.3 + '@smithy/node-http-handler': 3.3.2 '@smithy/types': 3.7.2 '@smithy/util-base64': 3.0.0 '@smithy/util-buffer-from': 3.0.0 @@ -5993,14 +5952,14 @@ snapshots: dependencies: '@types/node': 22.10.2 - '@typescript-eslint/eslint-plugin@8.18.2(@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.18.2(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.18.2 - '@typescript-eslint/type-utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.2 + '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/type-utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.1 eslint: 9.17.0 graphemer: 1.4.0 ignore: 5.3.2 @@ -6010,27 +5969,27 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.18.2 - '@typescript-eslint/types': 8.18.2 - '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.18.2 + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.18.1 debug: 4.3.7 eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.18.2': + '@typescript-eslint/scope-manager@8.18.1': dependencies: - '@typescript-eslint/types': 8.18.2 - '@typescript-eslint/visitor-keys': 8.18.2 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/visitor-keys': 8.18.1 - '@typescript-eslint/type-utils@8.18.2(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) debug: 4.3.7 eslint: 9.17.0 ts-api-utils: 1.3.0(typescript@5.7.2) @@ -6038,12 +5997,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.18.2': {} + '@typescript-eslint/types@8.18.1': {} - '@typescript-eslint/typescript-estree@8.18.2(typescript@5.7.2)': + '@typescript-eslint/typescript-estree@8.18.1(typescript@5.7.2)': dependencies: - '@typescript-eslint/types': 8.18.2 - '@typescript-eslint/visitor-keys': 8.18.2 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/visitor-keys': 8.18.1 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 @@ -6054,20 +6013,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.18.2(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.18.1(eslint@9.17.0)(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.17.0) - '@typescript-eslint/scope-manager': 8.18.2 - '@typescript-eslint/types': 8.18.2 - '@typescript-eslint/typescript-estree': 8.18.2(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.18.1 + '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.18.2': + '@typescript-eslint/visitor-keys@8.18.1': dependencies: - '@typescript-eslint/types': 8.18.2 + '@typescript-eslint/types': 8.18.1 eslint-visitor-keys: 4.2.0 '@ucanto/client@9.0.1': @@ -6875,6 +6834,33 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + esbuild@0.24.2: optionalDependencies: '@esbuild/aix-ppc64': 0.24.2 @@ -7766,7 +7752,6 @@ snapshots: - supports-color - utf-8-validate -<<<<<<< HEAD miniflare@3.20241205.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -7786,28 +7771,6 @@ snapshots: - supports-color - utf-8-validate -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - miniflare@3.20241106.2: - dependencies: - '@cspotcode/source-map-support': 0.8.1 - acorn: 8.14.0 - acorn-walk: 8.3.4 - capnp-ts: 0.7.0 - exit-hook: 2.2.1 - glob-to-regexp: 0.4.1 - stoppable: 1.1.0 - undici: 5.28.4 - workerd: 1.20241106.2 - ws: 8.18.0 - youch: 3.3.4 - zod: 3.23.8 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - ->>>>>>> b1f796c (chore: intro of local cloud tests) miniflare@3.20241218.0: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -8677,11 +8640,11 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.18.2(eslint@9.17.0)(typescript@5.7.2): + typescript-eslint@8.18.1(eslint@9.17.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.18.2(@typescript-eslint/parser@8.18.2(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.18.2(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.18.2(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/eslint-plugin': 8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.18.1(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.18.1(eslint@9.17.0)(typescript@5.7.2) eslint: 9.17.0 typescript: 5.7.2 transitivePeerDependencies: @@ -8714,13 +8677,6 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - unenv-nightly@2.0.0-20241121-161142-806b5c0: - dependencies: - defu: 6.1.4 - ohash: 1.1.4 - pathe: 1.1.2 - ufo: 1.5.4 - unenv-nightly@2.0.0-20241204-140205-a5d5190: dependencies: defu: 6.1.4 @@ -8786,13 +8742,13 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.2) optionalDependencies: - vite: 6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) + vite: 6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -8806,9 +8762,9 @@ snapshots: '@types/node': 22.10.2 fsevents: 2.3.3 - vite@6.0.6(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): + vite@6.0.5(@types/node@22.10.2)(tsx@4.19.2)(yaml@2.5.1): dependencies: - esbuild: 0.24.2 + esbuild: 0.24.0 postcss: 8.4.49 rollup: 4.24.0 optionalDependencies: @@ -8918,7 +8874,6 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20240718.0 '@cloudflare/workerd-windows-64': 1.20240718.0 -<<<<<<< HEAD workerd@1.20241205.0: optionalDependencies: '@cloudflare/workerd-darwin-64': 1.20241205.0 @@ -8927,17 +8882,6 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241205.0 '@cloudflare/workerd-windows-64': 1.20241205.0 -||||||| parent of b1f796c (chore: intro of local cloud tests) -======= - workerd@1.20241106.2: - optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20241106.2 - '@cloudflare/workerd-darwin-arm64': 1.20241106.2 - '@cloudflare/workerd-linux-64': 1.20241106.2 - '@cloudflare/workerd-linux-arm64': 1.20241106.2 - '@cloudflare/workerd-windows-64': 1.20241106.2 - ->>>>>>> b1f796c (chore: intro of local cloud tests) workerd@1.20241218.0: optionalDependencies: '@cloudflare/workerd-darwin-64': 1.20241218.0 @@ -8946,7 +8890,6 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20241218.0 '@cloudflare/workerd-windows-64': 1.20241218.0 -<<<<<<< HEAD wrangler@3.93.0(@cloudflare/workers-types@4.20241205.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -8976,39 +8919,6 @@ snapshots: - utf-8-validate wrangler@3.99.0(@cloudflare/workers-types@4.20241205.0): -||||||| parent of b1f796c (chore: intro of local cloud tests) - wrangler@3.99.0: -======= - wrangler@3.92.0(@cloudflare/workers-types@4.20241205.0): - dependencies: - '@cloudflare/kv-asset-handler': 0.3.4 - '@cloudflare/workers-shared': 0.9.1 - '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) - '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) - blake3-wasm: 2.1.5 - chokidar: 4.0.1 - date-fns: 4.1.0 - esbuild: 0.17.19 - itty-time: 1.0.6 - miniflare: 3.20241106.2 - nanoid: 3.3.7 - path-to-regexp: 6.3.0 - resolve: 1.22.8 - selfsigned: 2.4.1 - source-map: 0.6.1 - unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0 - workerd: 1.20241106.2 - xxhash-wasm: 1.0.2 - optionalDependencies: - '@cloudflare/workers-types': 4.20241205.0 - fsevents: 2.3.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - wrangler@3.99.0(@cloudflare/workers-types@4.20241205.0): ->>>>>>> b1f796c (chore: intro of local cloud tests) dependencies: '@cloudflare/kv-asset-handler': 0.3.4 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index dfd0dfc9..65448b46 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -9,6 +9,11 @@ bindings = [ { name = "FP_META_GROUPS", class_name = "FPMetaGroups"}, ] +[[d1_databases]] +binding = "DB" +database_name = "test-meta-merge" +database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" + [[migrations]] tag = "v1" # Should be unique for each entry diff --git a/src/cloud/client/index.ts b/src/cloud/client/index.ts index 2c2610e6..48804cd3 100644 --- a/src/cloud/client/index.ts +++ b/src/cloud/client/index.ts @@ -1,7 +1,7 @@ import { BuildURI, CoerceURI, KeyedResolvOnce, runtimeFn, URI } from "@adviser/cement"; import { bs, Database, fireproof } from "@fireproof/core"; import { ConnectFunction, connectionFactory, makeKeyBagUrlExtractable } from "../../connection-from-store.js"; -import { registerFireproofCloudStoreProtocol } from "./gateway.ts-off"; +import { registerFireproofCloudStoreProtocol } from "./gateway.js"; interface ConnectData { readonly remoteName: string; diff --git a/src/cloud/meta-merger/create-schema-cli.ts b/src/cloud/meta-merger/create-schema-cli.ts new file mode 100644 index 00000000..85527333 --- /dev/null +++ b/src/cloud/meta-merger/create-schema-cli.ts @@ -0,0 +1,9 @@ +import { MetaSendSql } from "./meta-send.js"; + +async function main() { + // eslint-disable-next-line no-console + console.log(MetaSendSql.schema()); +} + +// eslint-disable-next-line no-console +main().catch(console.error); diff --git a/src/cloud/meta-merger/meta-by-tenant-ledger.ts b/src/cloud/meta-merger/meta-by-tenant-ledger.ts new file mode 100644 index 00000000..f1e90e26 --- /dev/null +++ b/src/cloud/meta-merger/meta-by-tenant-ledger.ts @@ -0,0 +1,158 @@ +import { ResolveOnce } from "@adviser/cement"; +import { CRDTEntry } from "@fireproof/core"; +import { TenantLedgerSql } from "./tenant-ledger.js"; +import { ByConnection } from "./meta-merger.js"; +import type { Database, Statement } from "better-sqlite3"; + +export interface MetaByTenantLedgerRow { + readonly tenant: string; + readonly ledger: string; + readonly reqId: string; + readonly resId: string; + readonly metaCID: string; + readonly meta: CRDTEntry; + readonly updateAt: Date; +} + +interface SQLMetaByTenantLedgerRow { + readonly tenant: string; + readonly ledger: string; + readonly reqId: string; + readonly resId: string; + readonly metaCID: string; + readonly meta: string; + readonly updateAt: string; +} + +/* +SELECT * FROM Mitarbeiter e1 +WHERE NOT EXISTS +( + SELECT 1 FROM Mitarbeiter e2 + WHERE e1.employee_id=e2.employee_id und e2.employee_name LIKE 'A%' +); + */ + +export class MetaByTenantLedgerSql { + static schema() { + return [ + ...TenantLedgerSql.schema(), + ` + CREATE TABLE IF NOT EXISTS MetaByTenantLedger( + tenant TEXT NOT NULL, + ledger TEXT NOT NULL, + reqId TEXT NOT NULL, + resId TEXT NOT NULL, + metaCID TEXT NOT NULL, + meta TEXT NOT NULL, + updatedAt TEXT NOT NULL, + PRIMARY KEY (tenant, ledger, reqId, resId, metaCID), + UNIQUE(metaCID), + FOREIGN KEY (tenant, ledger) REFERENCES TenantLedger(tenant, ledger) + ) + `, + ]; + } + + readonly db: Database; + readonly tenantLedgerSql: TenantLedgerSql; + constructor(db: Database, tenantLedgerSql: TenantLedgerSql) { + this.db = db; + this.tenantLedgerSql = tenantLedgerSql; + } + + readonly #sqlCreateMetaByTenantLedger = new ResolveOnce(); + sqlCreateMetaByTenantLedger(): Statement[] { + return this.#sqlCreateMetaByTenantLedger.once(() => { + return MetaByTenantLedgerSql.schema().map((i) => this.db.prepare(i)); + }); + } + + readonly #sqlInsertMetaByTenantLedger = new ResolveOnce(); + sqlEnsureMetaByTenantLedger(): Statement<[string, string, string, string, string, string, string]> { + return this.#sqlInsertMetaByTenantLedger.once(() => { + return this.db.prepare(` + INSERT INTO MetaByTenantLedger(tenant, ledger, reqId, resId, metaCID, meta, updatedAt) + VALUES(?, ?, ?, ?, ?, ?, ?) + `); + }); + } + + readonly #sqlDeleteByConnection = new ResolveOnce(); + sqlDeleteByConnection(): Statement<[string, string, string, string, string]> { + return this.#sqlDeleteByConnection.once(() => { + return this.db.prepare(` + DELETE FROM MetaByTenantLedger + WHERE + tenant = ? + AND + ledger = ? + AND + reqId = ? + AND + resId = ? + AND + metaCID NOT IN (SELECT value FROM json_each(?)) + `); + }); + } + + /* + * select * from MetaByTenantLedger where tenant = 'tenant' and ledger = 'ledger' group by metaCID + */ + + // readonly #sqlSelectByMetaCIDs = new ResolveOnce() + // sqlSelectByMetaCIDs(): Statement { + // return this.#sqlSelectByMetaCIDs.once(() => { + // return this.db.prepare(` + // SELECT tenant, ledger, reqId, resId, metaCID, meta, updatedAt + // FROM MetaByTenantLedger + // WHERE metaCID in ? + // `); + // }) + // } + // async selectByMetaCIDs(metaCIDs: string[]): Promise { + // const stmt = this.sqlSelectByMetaCIDs(); + // const rows = await stmt.all(metaCIDs) + // return rows.map(row => ({ + // ...row, + // meta: JSON.parse(row.meta), + // updateAt: new Date(row.updateAt) + // } satisfies MetaByTenantLedgerRow)) + // } + + async deleteByConnection(t: ByConnection & { metaCIDs: string[] }) { + const stmt = this.sqlDeleteByConnection(); + return stmt.run(t.tenant, t.ledger, t.reqId, t.resId, JSON.stringify(t.metaCIDs)); + } + + async ensure(t: MetaByTenantLedgerRow) { + const stmt = this.sqlEnsureMetaByTenantLedger(); + return stmt.run(t.tenant, t.ledger, t.reqId, t.resId, t.metaCID, JSON.stringify(t.meta), t.updateAt.toISOString()); + } + + readonly #sqlSelectByConnection = new ResolveOnce(); + sqlSelectByConnection(): Statement<[string, string, string, string], SQLMetaByTenantLedgerRow> { + return this.#sqlSelectByConnection.once(() => { + return this.db.prepare(` + SELECT tenant, ledger, reqId, resId, metaCID, meta, updatedAt + FROM MetaByTenantLedger + WHERE tenant = ? AND ledger = ? AND reqId = ? AND resId = ? + ORDER BY updatedAt + `); + }); + } + + async selectByConnection(conn: ByConnection): Promise { + const stmt = this.sqlSelectByConnection(); + const rows = await stmt.all(conn.tenant, conn.ledger, conn.reqId, conn.resId); + return rows.map( + (row) => + ({ + ...row, + meta: JSON.parse(row.meta), + updateAt: new Date(row.updateAt), + }) satisfies MetaByTenantLedgerRow + ); + } +} diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts new file mode 100644 index 00000000..b9001176 --- /dev/null +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -0,0 +1,120 @@ +import Database from "better-sqlite3"; +import { MetaMerger } from "./meta-merger.js"; +import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; +import { Connection } from "../msg-types.js"; + +function sortCRDTEntries(rows: CRDTEntry[]) { + return rows.sort((a, b) => a.cid.localeCompare(b.cid)); +} + +describe("MetaMerger", () => { + let db: Database.Database; + const sthis = ensureSuperThis(); + let mm: MetaMerger; + beforeAll(async () => { + // db = new Database(':memory:'); + db = new Database("./dist/test.db"); + mm = new MetaMerger(sthis, db); + await mm.createSchema(); + }); + afterAll(() => { + db.close(); + }); + + let connection: Connection; + beforeEach(() => { + connection = { + key: { + tenant: `tenant${sthis.timeOrderedNextId().str}`, + ledger: "ledger", + }, + reqId: "reqId", + resId: "resId", + } satisfies Connection; + }); + + it("insert nothing", async () => { + await mm.addMeta({ + connection, + metas: [], + now: new Date(), + }); + const rows = await mm.metaToSend(connection); + expect(rows).toEqual([]); + }); + + it("insert one multiple", async () => { + const cid = sthis.timeOrderedNextId().str; + for (let i = 0; i < 10; i++) { + const metas = Array(i).fill({ + cid: cid, + parents: [], + data: "MomRkYXRho", + }); + await mm.addMeta({ + connection, + metas, + now: new Date(), + }); + const rows = await mm.metaToSend(connection); + if (i === 1) { + expect(rows).toEqual(metas); + } else { + expect(rows).toEqual([]); + } + } + }); + + it("insert multiple", async () => { + for (let i = 0; i < 10; i++) { + const metas = Array(i) + .fill({ + cid: "x", + parents: [], + data: "MomRkYXRho", + }) + .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); + await mm.addMeta({ + connection: { ...connection, reqId: sthis.timeOrderedNextId().str } satisfies Connection, + metas, + now: new Date(), + }); + const rows = await mm.metaToSend(connection); + expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(metas)); + } + }); + + it("metaToSend to sink", async () => { + const connections = Array(2) + .fill(connection) + .map((c) => ({ ...c, reqId: sthis.timeOrderedNextId().str })); + const ref: CRDTEntry[] = []; + for (const connection of connections) { + const metas = Array(2) + .fill({ + cid: "x", + parents: [], + data: "MomRkYXRho", + }) + .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); + ref.push(...metas); + await mm.addMeta({ + connection, + metas, + now: new Date(), + }); + } + // wrote 10 connections with 3 metas each + for (const connection of connections) { + const rows = await mm.metaToSend(connection); + expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(ref)); + } + const newConnections = Array(2) + .fill(connection) + .map((c) => ({ ...c, reqId: sthis.timeOrderedNextId().str })); + for (const connection of newConnections) { + const rows = await mm.metaToSend(connection); + expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(ref)); + } + }); +}); diff --git a/src/cloud/meta-merger/meta-merger.ts b/src/cloud/meta-merger/meta-merger.ts new file mode 100644 index 00000000..99c747d9 --- /dev/null +++ b/src/cloud/meta-merger/meta-merger.ts @@ -0,0 +1,114 @@ +/* +class MetaMerger { + mergeMeta(meta) { + } + + getMeta() { + } +} +*/ + +import { CRDTEntry, SuperThis } from "@fireproof/core"; +import { Connection } from "../msg-types.js"; +import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; +import { MetaSendSql } from "./meta-send.js"; +import { TenantLedgerSql } from "./tenant-ledger.js"; +import { TenantSql } from "./tenant.js"; +import type { Database } from "better-sqlite3"; + +export interface MetaMerge { + readonly connection: Connection; + readonly metas: CRDTEntry[]; + readonly now?: Date; +} + +export interface ByConnection { + readonly tenant: string; + readonly ledger: string; + readonly reqId: string; + readonly resId: string; +} + +function toByConnection(connection: Connection): ByConnection { + return { + tenant: connection.key.tenant, + ledger: connection.key.ledger, + reqId: connection.reqId, + resId: connection.resId, + }; +} + +export class MetaMerger { + readonly db: Database; + readonly sthis: SuperThis; + readonly sql: { + readonly tenant: TenantSql; + readonly tenantLedger: TenantLedgerSql; + readonly metaByTenantLedger: MetaByTenantLedgerSql; + readonly metaSend: MetaSendSql; + }; + + constructor(sthis: SuperThis, db: Database) { + this.db = db; + this.sthis = sthis; + const tenant = new TenantSql(db); + const tenantLedger = new TenantLedgerSql(db, tenant); + this.sql = { + tenant, + tenantLedger, + metaByTenantLedger: new MetaByTenantLedgerSql(db, tenantLedger), + metaSend: new MetaSendSql(db), + }; + } + + async createSchema() { + for (const i of this.sql.metaSend.sqlCreateMetaSend()) { + await i.run(); + } + } + + async addMeta(mm: MetaMerge) { + if (!mm.metas.length) { + return; + } + const now = mm.now || new Date(); + const byConnection = toByConnection(mm.connection); + const connCIDs = { + ...byConnection, + metaCIDs: mm.metas.map((meta) => meta.cid), + }; + await this.sql.metaSend.deleteByConnection(connCIDs); + await this.sql.metaByTenantLedger.deleteByConnection(connCIDs); + await this.sql.tenantLedger.ensure({ + tenant: mm.connection.key.tenant, + ledger: mm.connection.key.ledger, + createdAt: now, + }); + for (const meta of mm.metas) { + try { + await this.sql.metaByTenantLedger.ensure({ + ...byConnection, + metaCID: meta.cid, + meta: meta, + updateAt: now, + }); + } catch (e) { + this.sthis.logger.Warn().Err(e).Str("metaCID", meta.cid).Msg("addMeta"); + } + } + } + + async metaToSend(sink: Connection, now = new Date()): Promise { + const bySink = toByConnection(sink); + const rows = await this.sql.metaSend.selectToAddSend({ ...bySink, now }); + await this.sql.metaSend.insert( + rows.map((row) => ({ + metaCID: row.metaCID, + reqId: row.reqId, + resId: row.resId, + sendAt: row.sendAt, + })) + ); + return rows.map((row) => row.meta); + } +} diff --git a/src/cloud/meta-merger/meta-send.ts b/src/cloud/meta-merger/meta-send.ts new file mode 100644 index 00000000..9c1fdce6 --- /dev/null +++ b/src/cloud/meta-merger/meta-send.ts @@ -0,0 +1,124 @@ +import { ResolveOnce } from "@adviser/cement"; +import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; +import { ByConnection } from "./meta-merger.js"; +import { Statement, type Database } from "better-sqlite3"; +import { CRDTEntry } from "@fireproof/core"; + +export interface MetaSendRow { + readonly metaCID: string; + readonly reqId: string; + readonly resId: string; + readonly sendAt: Date; +} + +type SQLMetaSendRowWithMeta = MetaSendRow & { meta: string }; +export type MetaSendRowWithMeta = MetaSendRow & { meta: CRDTEntry }; + +export class MetaSendSql { + static schema() { + return [ + ...MetaByTenantLedgerSql.schema(), + ` + CREATE TABLE IF NOT EXISTS MetaSend ( + metaCID TEXT NOT NULL, + reqId TEXT NOT NULL, + resId TEXT NOT NULL, + sendAt TEXT NOT NULL, + PRIMARY KEY(metaCID,reqId,resId), + FOREIGN KEY(metaCID) REFERENCES MetaByTenantLedger(metaCID) + ); + `, + ]; + } + + readonly db: Database; + constructor(db: Database) { + this.db = db; + } + + readonly #sqlCreateMetaSend = new ResolveOnce(); + sqlCreateMetaSend(): Statement[] { + return this.#sqlCreateMetaSend.once(() => { + return MetaSendSql.schema().map((i) => this.db.prepare(i)); + }); + } + + readonly #sqlInsertMetaSend = new ResolveOnce<[string, string, string, string]>(); + sqlInsertMetaSend(): Statement<[string, string, string, string]> { + return this.#sqlInsertMetaSend.once(() => { + return this.db.prepare(` + INSERT INTO MetaSend(metaCID, reqId, resId, sendAt) VALUES(?, ?, ?, ?) + `); + }); + } + + readonly #sqlSelectToAddSend = new ResolveOnce(); + sqlSelectToAddSend(): Statement<[string, string, string, string, string, string, string], SQLMetaSendRowWithMeta> { + return this.#sqlSelectToAddSend.once(() => { + return this.db.prepare(` + SELECT t.metaCID, ? as reqId, ? as resId, ? as sendAt, t.meta FROM MetaByTenantLedger as t + WHERE + t.tenant = ? + AND + t.ledger = ? + AND + NOT EXISTS (SELECT 1 FROM MetaSend AS s WHERE t.metaCID = s.metaCID and s.reqId = ? and s.resId = ?) + `); + }); + } + + async selectToAddSend(conn: ByConnection & { now: Date }): Promise { + const stmt = this.sqlSelectToAddSend(); + const rows = await stmt.all( + conn.reqId, + conn.resId, + conn.now.toISOString(), + conn.tenant, + conn.ledger, + conn.reqId, + conn.resId + ); + return rows.map( + (i) => + ({ + metaCID: i.metaCID, + reqId: i.reqId, + resId: i.resId, + sendAt: new Date(i.sendAt), + meta: JSON.parse(i.meta) as CRDTEntry, + }) satisfies MetaSendRowWithMeta + ); + } + + async insert(t: MetaSendRow[]) { + const stmt = this.sqlInsertMetaSend(); + for (const i of t) { + await stmt.run(i.metaCID, i.reqId, i.resId, i.sendAt.toISOString()); + } + } + + readonly #sqlDeleteByConnection = new ResolveOnce(); + sqlDeleteByMetaCID(): Statement<[string, string, string, string, string], void> { + return this.#sqlDeleteByConnection.once(() => { + return this.db.prepare(` + DELETE FROM MetaSend + WHERE metaCID in (SELECT metaCID FROM MetaByTenantLedger + WHERE + tenant = ? + AND + ledger = ? + AND + reqId = ? + AND + resId = ? + AND + metaCID NOT IN (SELECT value FROM json_each(?))) + `); + }); + } + + async deleteByConnection(dmi: ByConnection & { metaCIDs: string[] }) { + const stmt = this.sqlDeleteByMetaCID(); + return stmt.run(dmi.tenant, dmi.ledger, dmi.reqId, dmi.resId, JSON.stringify(dmi.metaCIDs)); + } +} diff --git a/src/cloud/meta-merger/sql-border.ts b/src/cloud/meta-merger/sql-border.ts new file mode 100644 index 00000000..0a10dd50 --- /dev/null +++ b/src/cloud/meta-merger/sql-border.ts @@ -0,0 +1,18 @@ +import { RunResult } from "better-sqlite3"; + +export function now() { + return new Date().toISOString(); +} + +export interface SqlLiteStmt { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + bind(...args: any[]): any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + run(...args: any[]): Promise; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get(...args: any[]): Promise; +} + +export interface SqlLite { + prepare(sql: string): SqlLiteStmt; +} diff --git a/src/cloud/meta-merger/tenant-ledger.ts b/src/cloud/meta-merger/tenant-ledger.ts new file mode 100644 index 00000000..a8f97e95 --- /dev/null +++ b/src/cloud/meta-merger/tenant-ledger.ts @@ -0,0 +1,58 @@ +import { ResolveOnce } from "@adviser/cement"; +import { TenantSql } from "./tenant.js"; + +import type { Database, Statement } from "better-sqlite3"; + +export interface TenantLedgerRow { + readonly tenant: string; + readonly ledger: string; + readonly createdAt: Date; +} + +export class TenantLedgerSql { + static schema() { + return [ + ...TenantSql.schema(), + ` + CREATE TABLE IF NOT EXISTS TenantLedger( + tenant TEXT NOT NULL, + ledger TEXT NOT NULL, + createdAt TEXT NOT NULL, + PRIMARY KEY(tenant, ledger), + FOREIGN KEY(tenant) REFERENCES Tenant(tenant) + ) + `, + ]; + } + + readonly db: Database; + readonly tenantSql: TenantSql; + constructor(db: Database, tenantSql: TenantSql) { + this.db = db; + this.tenantSql = tenantSql; + } + + readonly #sqlCreateTenantLedger = new ResolveOnce(); + sqlCreateTenantLedger(): Statement[] { + return this.#sqlCreateTenantLedger.once(() => { + return TenantLedgerSql.schema().map((i) => this.db.prepare(i)); + }); + } + + readonly #sqlInsertTenantLedger = new ResolveOnce>(); + sqlEnsureTenantLedger(): Statement<[string, string, string, string, string]> { + return this.#sqlInsertTenantLedger.once(() => { + return this.db.prepare(` + INSERT INTO TenantLedger(tenant, ledger, createdAt) + SELECT ?, ?, ? WHERE + NOT EXISTS(SELECT 1 FROM TenantLedger WHERE tenant = ? and ledger = ?) + `); + }); + } + + async ensure(t: TenantLedgerRow) { + await this.tenantSql.ensure(t); + const stmt = this.sqlEnsureTenantLedger(); + return stmt.run(t.tenant, t.ledger, t.createdAt.toISOString(), t.tenant, t.ledger); + } +} diff --git a/src/cloud/meta-merger/tenant.ts b/src/cloud/meta-merger/tenant.ts new file mode 100644 index 00000000..e9479c28 --- /dev/null +++ b/src/cloud/meta-merger/tenant.ts @@ -0,0 +1,47 @@ +import { ResolveOnce } from "@adviser/cement"; +import type { Database, Statement } from "better-sqlite3"; + +export interface TenantRow { + readonly tenant: string; + readonly createdAt: Date; +} + +export class TenantSql { + static schema(): string[] { + return [ + ` + CREATE TABLE IF NOT EXISTS Tenant( + tenant TEXT NOT NULL PRIMARY KEY, + createdAt TEXT NOT NULL + ) + `, + ]; + } + + readonly db: Database; + constructor(db: Database) { + this.db = db; + } + + readonly #sqlCreateTenant = new ResolveOnce(); + sqlCreateTenant(): Statement[] { + return this.#sqlCreateTenant.once(() => { + return TenantSql.schema().map((i) => this.db.prepare(i)); + }); + } + + readonly #sqlInsertTenant = new ResolveOnce(); + sqlEnsureTenant(): Statement<[string, string, string], void> { + return this.#sqlInsertTenant.once(() => { + return this.db.prepare(` + INSERT INTO Tenant(tenant, createdAt) + SELECT ?, ? WHERE NOT EXISTS(SELECT 1 FROM Tenant WHERE tenant = ?) + `); + }); + } + + async ensure(t: TenantRow) { + const stmt = this.sqlEnsureTenant(); + return stmt.run(t.tenant, t.createdAt.toISOString(), t.tenant); + } +} diff --git a/src/cloud/msg-processor.ts b/src/cloud/msg-processor.ts deleted file mode 100644 index bded0854..00000000 --- a/src/cloud/msg-processor.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { exception2Result, Logger } from "@adviser/cement"; -import { - buildErrorMsg, - buildResDelMeta, - buildResGestalt, - buildResGetMeta, - buildResPutMeta, - defaultGestalt, - ErrorMsg, - getStoreFromType, - MsgBase, - MsgIsReqDelData, - MsgIsReqDelMeta, - MsgIsReqDelWAL, - MsgIsReqGestalt, - MsgIsReqGetData, - MsgIsReqGetMeta, - MsgIsReqGetWAL, - MsgIsReqPutData, - MsgIsReqPutMeta, - MsgIsReqPutWAL, - MsgIsReqSubscribeMeta, - ReqDelMeta, - ReqGetMeta, - ReqOptRes, - ReqPutMeta, - ReqRes, - ResDelMeta, - ResGetMeta, - ResPutMeta, -} from "./msg-types.js"; -import { calculatePreSignedUrl } from "./pre-signed-url.js"; -import { SuperThis } from "@fireproof/core"; - -export interface CtxBase { - readonly logger: Logger; -} - -export interface ReqOptResCtx extends ReqOptRes { - readonly ctx?: C; -} - -export interface ReqResCtx extends ReqRes { - readonly ctx: C; -} - -export interface MsgProcessor { - dispatch( - decodeFn: () => Promise - ): Promise, O>>; - - // signedUrl(req: ReqSignedUrl, ctx: CtxBase): Promise>; - // subscribeMeta(req: ReqSubscribeMeta, ctx: CtxBase): Promise>; - - // delMeta(req: ReqDelMeta, ctx: CtxBase): Promise>; - // putMeta(req: ReqPutMeta, ctx: CtxBase): Promise>; - // getMeta(req: ReqGetMeta, ctx: CtxBase): Promise>; -} - -export interface RequestOpts { - readonly waitFor: (msg: MsgBase) => boolean; - readonly timeout?: number; // ms -} -// export interface Connection { -// readonly ws: WebSocket; -// readonly key: ConnectionKey; -// request(msg: MsgBase, opts: RequestOpts): Promise>; -// onMessage(msgFn: (msg: MsgBase) => void): () => void; -// close(): Promise; -// } - -export abstract class MsgProcessorBase implements MsgProcessor { - readonly logger: Logger; - readonly serverId: string; - readonly ctx: O; - readonly sthis: SuperThis; - constructor(sthis: SuperThis, logger: Logger, ctx: O, serverId: string) { - this.serverId = serverId; - this.logger = logger; - this.ctx = ctx; - this.sthis = sthis; - } - - async dispatch( - decodeFn: () => Promise, - reqFn: (msg: Q, ctx: O) => Promise> = async (req) => ({ req }) - ): Promise> { - const rReqMsg = await exception2Result(async () => (await decodeFn()) as Q); - if (rReqMsg.isErr()) { - const errMsg = buildErrorMsg(this.sthis, this.logger, { tid: "internal" } as MsgBase, rReqMsg.Err()); - return { - req: errMsg as unknown as Q, - res: errMsg, - ctx: this.ctx, - }; - } - const { req, ctx: optCtx } = await reqFn(rReqMsg.Ok() as Q, this.ctx); - const ctx = { ...(optCtx || this.ctx) }; - switch (true) { - case MsgIsReqGestalt(req): - return { - req, - res: buildResGestalt(req, defaultGestalt(this.serverId, true)) as S | ErrorMsg, - ctx, - }; - - case MsgIsReqGetData(req): - case MsgIsReqGetWAL(req): - return { - req, - res: (await this.signedUrl( - { - ...req, - params: { - ...req.params, - method: "GET", - store: getStoreFromType(req).store, - }, - }, - ctx - )) as S | ErrorMsg, - ctx, - }; - - case MsgIsReqPutData(req): - case MsgIsReqPutWAL(req): - if (req.payload) { - return { - req, - res: buildErrorMsg(this.logger, req, new Error("inband payload not implemented")) as S | ErrorMsg, - ctx, - }; - } - return { - req, - res: (await this.signedUrl( - { - ...req, - params: { - ...req.params, - method: "PUT", - store: getStoreFromType(req).store, - }, - }, - ctx - )) as S | ErrorMsg, - ctx, - }; - - case MsgIsReqDelData(req): - case MsgIsReqDelWAL(req): - return { - req, - res: (await this.signedUrl( - { - ...req, - params: { - ...req.params, - method: "DELETE", - store: getStoreFromType(req).store, - }, - }, - ctx - )) as S | ErrorMsg, - ctx, - }; - - // case MsgIsReqSignedUrl(req): - // return { - // req, - // res: (await this.signedUrl(req, ctx)) as S | ErrorMsg, - // ctx, - // }; - case MsgIsReqSubscribeMeta(req): - return { - req, - res: (await this.subscribeMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqPutMeta(req): - return { - req, - res: (await this.putMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqGetMeta(req): - return { - req, - res: (await this.getMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - case MsgIsReqDelMeta(req): - return { - req, - res: (await this.delMeta(req, ctx)) as S | ErrorMsg, - ctx, - }; - } - return { - req: req, - res: buildErrorMsg(this.logger, req, new Error(`unknown msg.type=${req.type}`)) as S | ErrorMsg, - ctx, - }; - } - - async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { - // delete meta does nothing in this implementation - // if you delete meta basically you are deleting the whole ledger - return buildResDelMeta(req, { - params: req.params, - status: "unsupported", - connId: ctx.group.connId, - }); - } - - async getMeta(req: ReqGetMeta, ctx: CF): Promise { - const rSignedUrl = await calculatePreSignedUrl( - { - tid: req.tid, - type: "reqSignedUrl", - version: req.version, - params: { ...req.params, method: "GET" }, - }, - ctx.env - ); - if (rSignedUrl.isErr()) { - return buildErrorMsg(this.logger, req, rSignedUrl.Err()); - } - return buildResGetMeta(req, { - signedGetUrl: rSignedUrl.Ok().toString(), - status: "found", - metas: [], - connId: "", - }); - } - - async putMeta(req: ReqPutMeta, ctx: CtxHasGroup): Promise { - const rSignedUrl = await calculatePreSignedUrl( - { - tid: req.tid, - type: "reqSignedUrl", - version: req.version, - params: { ...req.params, method: "PUT" }, - }, - ctx.env - ); - if (rSignedUrl.isErr()) { - return buildErrorMsg(this.logger, req, rSignedUrl.Err()); - } - // roughly time ordered - return buildResPutMeta(req, { - // metaId should be a hash of metas. - metaId: new Date().getTime().toString(), - metas: req.metas, - signedPutUrl: rSignedUrl.Ok().toString(), - connId: ctx.group.connId, - }); - } -} diff --git a/src/ucan/ucan-gateway.ts b/src/ucan/ucan-gateway.ts index c3ee9ca8..6a3f8c53 100644 --- a/src/ucan/ucan-gateway.ts +++ b/src/ucan/ucan-gateway.ts @@ -293,7 +293,6 @@ export class UCANGateway implements bs.Gateway { try { callback(data); } catch (error) { - console.error(error); this.logger.Error().Err(error).Msg("Error in subscriber callback execution"); } } diff --git a/tests/docker-compose.ts b/tests/docker-compose.ts index 2cbce6a5..3da5be93 100644 --- a/tests/docker-compose.ts +++ b/tests/docker-compose.ts @@ -8,8 +8,8 @@ async function main() { process.exit(res.exitCode); } -// eslint-disable-next-line no-console main().catch((e) => { + // eslint-disable-next-line no-console console.error(e); process.exit(2); }); From b4398c8318682ead655daee1c27bfe23d61285e1 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 3 Jan 2025 08:50:02 +0100 Subject: [PATCH 74/83] chore: run tests on node and cf-worker --- package.json | 4 +- pnpm-lock.yaml | 27 ++-------- src/cloud/backend/env.d.ts | 2 + src/cloud/backend/wrangler.toml | 2 +- src/cloud/meta-merger/abstract-sql.ts | 53 +++++++++++++++++++ .../meta-merger/bettersql-abstract-sql.ts | 32 +++++++++++ .../meta-merger/cf-worker-abstract-sql.ts | 29 ++++++++++ src/cloud/meta-merger/create-schema-cli.ts | 2 +- .../meta-merger/meta-by-tenant-ledger.ts | 30 ++++++----- src/cloud/meta-merger/meta-merger.test.ts | 19 ++++--- src/cloud/meta-merger/meta-merger.ts | 10 ++-- src/cloud/meta-merger/meta-send.ts | 40 +++++++------- src/cloud/meta-merger/sql-border.ts | 18 ------- src/cloud/meta-merger/tenant-ledger.ts | 31 ++++++----- src/cloud/meta-merger/tenant.ts | 26 +++++---- src/sql/sqlite.test.ts | 5 +- src/sql/v0.19/sqlite_factory.ts | 5 +- tsconfig.json | 4 +- ...kv.config.ts => vitest.cf-worker.config.ts | 6 +-- vitest.workspace.ts | 4 +- 20 files changed, 226 insertions(+), 123 deletions(-) create mode 100644 src/cloud/meta-merger/abstract-sql.ts create mode 100644 src/cloud/meta-merger/bettersql-abstract-sql.ts create mode 100644 src/cloud/meta-merger/cf-worker-abstract-sql.ts delete mode 100644 src/cloud/meta-merger/sql-border.ts rename vitest.cf-kv.config.ts => vitest.cf-worker.config.ts (68%) diff --git a/package.json b/package.json index d69032df..9602295b 100644 --- a/package.json +++ b/package.json @@ -95,8 +95,8 @@ "@aws-sdk/client-s3": "^3.717.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "^0.19.119", - "@fireproof/vendor": "^1.0.0", + "@fireproof/core": "^0.19.121", + "@fireproof/vendor": "^1.0.4", "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@ipld/dag-ucan": "^3.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c24bd33b..f857f4d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,11 +21,11 @@ importers: specifier: ^4.20241127.0 version: 4.20241205.0 '@fireproof/core': - specifier: ^0.19.119 + specifier: ^0.19.121 version: 0.19.121(react@18.3.1)(typescript@5.7.2) '@fireproof/vendor': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.4 + version: 1.0.4 '@hono/node-server': specifier: ^1.13.7 version: 1.13.7(hono@4.6.13) @@ -1259,9 +1259,6 @@ packages: peerDependencies: react: ^18.3.1 - '@fireproof/vendor@1.0.0': - resolution: {integrity: sha512-ucN0ICj7xbpbO3NWjAKKjMHkBn4vSRUdKn14LLaA0MILJowty+H4XBB8dCobwKemhW49ha5p520NOLRzJSKsow==} - '@fireproof/vendor@1.0.4': resolution: {integrity: sha512-F8yYaYGRNrtYo4KyMzMuKwI5mGieYMkI23KnYkQ3ixKhIu3J6qRGZsuROFjOv2zWjQvtPronvqyxNc9P5km31g==} @@ -5278,24 +5275,6 @@ snapshots: transitivePeerDependencies: - typescript - '@fireproof/vendor@1.0.0': - dependencies: - '@ipld/dag-pb': 4.1.2 - '@multiformats/murmur3': 2.1.8 - hamt-sharding: 3.0.6 - interface-blockstore: 5.3.1 - ipfs-unixfs: 11.2.0 - it-filter: 3.1.1 - it-last: 3.0.6 - it-map: 3.1.1 - it-parallel: 3.0.8 - it-pipe: 3.0.1 - it-pushable: 3.2.3 - multiformats: 13.3.1 - p-queue: 8.0.1 - progress-events: 1.0.1 - varint: 6.0.0 - '@fireproof/vendor@1.0.4': dependencies: '@ipld/dag-pb': 4.1.2 diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index b7cc3bf5..4c5bca7b 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -33,6 +33,8 @@ export interface Env { FP_META_GROUPS: DurableObjectNamespace; + DB: D1Database; + WS_EVENTS: WSEvents; } diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 65448b46..e0e244d6 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -1,7 +1,7 @@ name = "fireproof-cloud" main = "server.ts" compatibility_date = "2024-04-19" -# compatibility_flags = ["nodejs_compat"] +compatibility_flags = ["nodejs_compat"] # upload_source_maps = true [durable_objects] diff --git a/src/cloud/meta-merger/abstract-sql.ts b/src/cloud/meta-merger/abstract-sql.ts new file mode 100644 index 00000000..445c5d2a --- /dev/null +++ b/src/cloud/meta-merger/abstract-sql.ts @@ -0,0 +1,53 @@ +// import { RunResult } from "better-sqlite3"; + +// export function now() { +// return new Date().toISOString(); +// } + +// export interface SqlLiteStmt { +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// bind(...args: any[]): any; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// run(...args: any[]): Promise; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// get(...args: any[]): Promise; +// } + +// export interface SqlLite { +// prepare(sql: string): SqlLiteStmt; +// } + +// export interface SqlLiteDBDialect { + +// } + +// export type SQLLiteFlavor = BaseSQLiteDatabase<'async', unknown>; + +export interface SQLDatabase { + prepare(sql: string): SQLStatement; +} + +export type SQLParams = (string | number | Date)[]; + +// export type SQLRow = Record; + +export interface SQLStatement { + run(...params: SQLParams): Promise; + all(...params: SQLParams): Promise; +} + +export function conditionalDrop(drop: boolean, tabName: string, create: string): string[] { + if (!drop) { + return [create]; + } + return [`DROP TABLE IF EXISTS ${tabName}`, create]; +} + +export function sqliteCoerceParams(params: SQLParams): (string | number)[] { + return params.map((i) => { + if (i instanceof Date) { + return i.toISOString(); + } + return i; + }); +} diff --git a/src/cloud/meta-merger/bettersql-abstract-sql.ts b/src/cloud/meta-merger/bettersql-abstract-sql.ts new file mode 100644 index 00000000..68dc0a19 --- /dev/null +++ b/src/cloud/meta-merger/bettersql-abstract-sql.ts @@ -0,0 +1,32 @@ +import { SQLDatabase, sqliteCoerceParams, SQLParams, SQLStatement } from "./abstract-sql.js"; + +import Database from "better-sqlite3"; + +export class BetterSQLStatement implements SQLStatement { + readonly stmt: Database.Statement; + constructor(stmt: Database.Statement) { + this.stmt = stmt; + } + + async run(...iparams: SQLParams): Promise { + return this.stmt.run(...sqliteCoerceParams(iparams)) as T; + } + async all(...params: SQLParams): Promise { + return this.stmt.all(...sqliteCoerceParams(params)) as T[]; + } +} + +export class BetterSQLDatabase implements SQLDatabase { + readonly db: Database.Database; + constructor(dbOrPath: Database.Database | string) { + if (typeof dbOrPath === "string") { + this.db = new Database(dbOrPath); + } else { + this.db = dbOrPath; + } + } + + prepare(sql: string): SQLStatement { + return new BetterSQLStatement(this.db.prepare(sql)); + } +} diff --git a/src/cloud/meta-merger/cf-worker-abstract-sql.ts b/src/cloud/meta-merger/cf-worker-abstract-sql.ts new file mode 100644 index 00000000..a3ff80ae --- /dev/null +++ b/src/cloud/meta-merger/cf-worker-abstract-sql.ts @@ -0,0 +1,29 @@ +import { SQLDatabase, sqliteCoerceParams, SQLParams, SQLStatement } from "./abstract-sql.js"; + +import type { D1Database } from "@cloudflare/workers-types"; + +export class CFWorkerSQLStatement implements SQLStatement { + readonly stmt: D1PreparedStatement; + constructor(stmt: D1PreparedStatement) { + this.stmt = stmt; + } + + async run(...iparams: SQLParams): Promise { + return this.stmt.bind(...sqliteCoerceParams(iparams)).run() as T; + } + async all(...params: SQLParams): Promise { + const rows = await this.stmt.bind(...sqliteCoerceParams(params)).run(); + return rows.results as T[]; + } +} + +export class CFWorkerSQLDatabase implements SQLDatabase { + readonly db: D1Database; + constructor(db: D1Database) { + this.db = db; + } + + prepare(sql: string): SQLStatement { + return new CFWorkerSQLStatement(this.db.prepare(sql)); + } +} diff --git a/src/cloud/meta-merger/create-schema-cli.ts b/src/cloud/meta-merger/create-schema-cli.ts index 85527333..7ebd858e 100644 --- a/src/cloud/meta-merger/create-schema-cli.ts +++ b/src/cloud/meta-merger/create-schema-cli.ts @@ -2,7 +2,7 @@ import { MetaSendSql } from "./meta-send.js"; async function main() { // eslint-disable-next-line no-console - console.log(MetaSendSql.schema()); + console.log(MetaSendSql.schema(true).join(";\n")); } // eslint-disable-next-line no-console diff --git a/src/cloud/meta-merger/meta-by-tenant-ledger.ts b/src/cloud/meta-merger/meta-by-tenant-ledger.ts index f1e90e26..0fd213f7 100644 --- a/src/cloud/meta-merger/meta-by-tenant-ledger.ts +++ b/src/cloud/meta-merger/meta-by-tenant-ledger.ts @@ -2,7 +2,7 @@ import { ResolveOnce } from "@adviser/cement"; import { CRDTEntry } from "@fireproof/core"; import { TenantLedgerSql } from "./tenant-ledger.js"; import { ByConnection } from "./meta-merger.js"; -import type { Database, Statement } from "better-sqlite3"; +import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js"; export interface MetaByTenantLedgerRow { readonly tenant: string; @@ -34,10 +34,13 @@ WHERE NOT EXISTS */ export class MetaByTenantLedgerSql { - static schema() { + static schema(drop = false) { return [ - ...TenantLedgerSql.schema(), - ` + ...TenantLedgerSql.schema(drop), + ...conditionalDrop( + drop, + "MetaByTenantLedger", + ` CREATE TABLE IF NOT EXISTS MetaByTenantLedger( tenant TEXT NOT NULL, ledger TEXT NOT NULL, @@ -50,26 +53,27 @@ export class MetaByTenantLedgerSql { UNIQUE(metaCID), FOREIGN KEY (tenant, ledger) REFERENCES TenantLedger(tenant, ledger) ) - `, + ` + ), ]; } - readonly db: Database; + readonly db: SQLDatabase; readonly tenantLedgerSql: TenantLedgerSql; - constructor(db: Database, tenantLedgerSql: TenantLedgerSql) { + constructor(db: SQLDatabase, tenantLedgerSql: TenantLedgerSql) { this.db = db; this.tenantLedgerSql = tenantLedgerSql; } readonly #sqlCreateMetaByTenantLedger = new ResolveOnce(); - sqlCreateMetaByTenantLedger(): Statement[] { + sqlCreateMetaByTenantLedger(): SQLStatement[] { return this.#sqlCreateMetaByTenantLedger.once(() => { return MetaByTenantLedgerSql.schema().map((i) => this.db.prepare(i)); }); } readonly #sqlInsertMetaByTenantLedger = new ResolveOnce(); - sqlEnsureMetaByTenantLedger(): Statement<[string, string, string, string, string, string, string]> { + sqlEnsureMetaByTenantLedger(): SQLStatement { return this.#sqlInsertMetaByTenantLedger.once(() => { return this.db.prepare(` INSERT INTO MetaByTenantLedger(tenant, ledger, reqId, resId, metaCID, meta, updatedAt) @@ -79,7 +83,7 @@ export class MetaByTenantLedgerSql { } readonly #sqlDeleteByConnection = new ResolveOnce(); - sqlDeleteByConnection(): Statement<[string, string, string, string, string]> { + sqlDeleteByConnection(): SQLStatement { return this.#sqlDeleteByConnection.once(() => { return this.db.prepare(` DELETE FROM MetaByTenantLedger @@ -131,8 +135,8 @@ export class MetaByTenantLedgerSql { return stmt.run(t.tenant, t.ledger, t.reqId, t.resId, t.metaCID, JSON.stringify(t.meta), t.updateAt.toISOString()); } - readonly #sqlSelectByConnection = new ResolveOnce(); - sqlSelectByConnection(): Statement<[string, string, string, string], SQLMetaByTenantLedgerRow> { + readonly #sqlSelectByConnection = new ResolveOnce(); + sqlSelectByConnection(): SQLStatement { return this.#sqlSelectByConnection.once(() => { return this.db.prepare(` SELECT tenant, ledger, reqId, resId, metaCID, meta, updatedAt @@ -145,7 +149,7 @@ export class MetaByTenantLedgerSql { async selectByConnection(conn: ByConnection): Promise { const stmt = this.sqlSelectByConnection(); - const rows = await stmt.all(conn.tenant, conn.ledger, conn.reqId, conn.resId); + const rows = await stmt.all(conn.tenant, conn.ledger, conn.reqId, conn.resId); return rows.map( (row) => ({ diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index b9001176..2a8796a8 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -1,25 +1,32 @@ -import Database from "better-sqlite3"; +// import type { Database } from "better-sqlite3"; import { MetaMerger } from "./meta-merger.js"; import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; import { Connection } from "../msg-types.js"; +import { runtimeFn } from "@adviser/cement"; +import { SQLDatabase } from "./abstract-sql.js"; +import type { Env } from '../backend/env.js' function sortCRDTEntries(rows: CRDTEntry[]) { return rows.sort((a, b) => a.cid.localeCompare(b.cid)); } describe("MetaMerger", () => { - let db: Database.Database; + let db: SQLDatabase; const sthis = ensureSuperThis(); let mm: MetaMerger; beforeAll(async () => { // db = new Database(':memory:'); - db = new Database("./dist/test.db"); + if (runtimeFn().isCFWorker) { + const { CFWorkerSQLDatabase } = await import("./cf-worker-abstract-sql.js"); + const { env } = await import("cloudflare:test"); + db = new CFWorkerSQLDatabase((env as Env).DB); + } else { + const { BetterSQLDatabase } = await import("./bettersql-abstract-sql.js"); + db = new BetterSQLDatabase("./dist/test.db"); + } mm = new MetaMerger(sthis, db); await mm.createSchema(); }); - afterAll(() => { - db.close(); - }); let connection: Connection; beforeEach(() => { diff --git a/src/cloud/meta-merger/meta-merger.ts b/src/cloud/meta-merger/meta-merger.ts index 99c747d9..f312a67f 100644 --- a/src/cloud/meta-merger/meta-merger.ts +++ b/src/cloud/meta-merger/meta-merger.ts @@ -14,7 +14,7 @@ import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; import { MetaSendSql } from "./meta-send.js"; import { TenantLedgerSql } from "./tenant-ledger.js"; import { TenantSql } from "./tenant.js"; -import type { Database } from "better-sqlite3"; +import { SQLDatabase } from "./abstract-sql.js"; export interface MetaMerge { readonly connection: Connection; @@ -39,7 +39,7 @@ function toByConnection(connection: Connection): ByConnection { } export class MetaMerger { - readonly db: Database; + readonly db: SQLDatabase; readonly sthis: SuperThis; readonly sql: { readonly tenant: TenantSql; @@ -48,7 +48,7 @@ export class MetaMerger { readonly metaSend: MetaSendSql; }; - constructor(sthis: SuperThis, db: Database) { + constructor(sthis: SuperThis, db: SQLDatabase) { this.db = db; this.sthis = sthis; const tenant = new TenantSql(db); @@ -61,8 +61,8 @@ export class MetaMerger { }; } - async createSchema() { - for (const i of this.sql.metaSend.sqlCreateMetaSend()) { + async createSchema(drop = false) { + for (const i of this.sql.metaSend.sqlCreateMetaSend(drop)) { await i.run(); } } diff --git a/src/cloud/meta-merger/meta-send.ts b/src/cloud/meta-merger/meta-send.ts index 9c1fdce6..2debc00a 100644 --- a/src/cloud/meta-merger/meta-send.ts +++ b/src/cloud/meta-merger/meta-send.ts @@ -1,8 +1,8 @@ import { ResolveOnce } from "@adviser/cement"; import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; import { ByConnection } from "./meta-merger.js"; -import { Statement, type Database } from "better-sqlite3"; import { CRDTEntry } from "@fireproof/core"; +import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js"; export interface MetaSendRow { readonly metaCID: string; @@ -15,10 +15,13 @@ type SQLMetaSendRowWithMeta = MetaSendRow & { meta: string }; export type MetaSendRowWithMeta = MetaSendRow & { meta: CRDTEntry }; export class MetaSendSql { - static schema() { + static schema(drop = false) { return [ - ...MetaByTenantLedgerSql.schema(), - ` + ...MetaByTenantLedgerSql.schema(drop), + ...conditionalDrop( + drop, + "MetaSend", + ` CREATE TABLE IF NOT EXISTS MetaSend ( metaCID TEXT NOT NULL, reqId TEXT NOT NULL, @@ -27,24 +30,25 @@ export class MetaSendSql { PRIMARY KEY(metaCID,reqId,resId), FOREIGN KEY(metaCID) REFERENCES MetaByTenantLedger(metaCID) ); - `, + ` + ), ]; } - readonly db: Database; - constructor(db: Database) { + readonly db: SQLDatabase; + constructor(db: SQLDatabase) { this.db = db; } - readonly #sqlCreateMetaSend = new ResolveOnce(); - sqlCreateMetaSend(): Statement[] { + readonly #sqlCreateMetaSend = new ResolveOnce(); + sqlCreateMetaSend(drop: boolean): SQLStatement[] { return this.#sqlCreateMetaSend.once(() => { - return MetaSendSql.schema().map((i) => this.db.prepare(i)); + return MetaSendSql.schema(drop).map((i) => this.db.prepare(i)); }); } - readonly #sqlInsertMetaSend = new ResolveOnce<[string, string, string, string]>(); - sqlInsertMetaSend(): Statement<[string, string, string, string]> { + readonly #sqlInsertMetaSend = new ResolveOnce(); + sqlInsertMetaSend(): SQLStatement { return this.#sqlInsertMetaSend.once(() => { return this.db.prepare(` INSERT INTO MetaSend(metaCID, reqId, resId, sendAt) VALUES(?, ?, ?, ?) @@ -52,8 +56,8 @@ export class MetaSendSql { }); } - readonly #sqlSelectToAddSend = new ResolveOnce(); - sqlSelectToAddSend(): Statement<[string, string, string, string, string, string, string], SQLMetaSendRowWithMeta> { + readonly #sqlSelectToAddSend = new ResolveOnce(); + sqlSelectToAddSend(): SQLStatement { return this.#sqlSelectToAddSend.once(() => { return this.db.prepare(` SELECT t.metaCID, ? as reqId, ? as resId, ? as sendAt, t.meta FROM MetaByTenantLedger as t @@ -69,10 +73,10 @@ export class MetaSendSql { async selectToAddSend(conn: ByConnection & { now: Date }): Promise { const stmt = this.sqlSelectToAddSend(); - const rows = await stmt.all( + const rows = await stmt.all( conn.reqId, conn.resId, - conn.now.toISOString(), + conn.now, conn.tenant, conn.ledger, conn.reqId, @@ -97,8 +101,8 @@ export class MetaSendSql { } } - readonly #sqlDeleteByConnection = new ResolveOnce(); - sqlDeleteByMetaCID(): Statement<[string, string, string, string, string], void> { + readonly #sqlDeleteByConnection = new ResolveOnce(); + sqlDeleteByMetaCID(): SQLStatement { return this.#sqlDeleteByConnection.once(() => { return this.db.prepare(` DELETE FROM MetaSend diff --git a/src/cloud/meta-merger/sql-border.ts b/src/cloud/meta-merger/sql-border.ts deleted file mode 100644 index 0a10dd50..00000000 --- a/src/cloud/meta-merger/sql-border.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { RunResult } from "better-sqlite3"; - -export function now() { - return new Date().toISOString(); -} - -export interface SqlLiteStmt { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - bind(...args: any[]): any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - run(...args: any[]): Promise; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - get(...args: any[]): Promise; -} - -export interface SqlLite { - prepare(sql: string): SqlLiteStmt; -} diff --git a/src/cloud/meta-merger/tenant-ledger.ts b/src/cloud/meta-merger/tenant-ledger.ts index a8f97e95..7e6bd226 100644 --- a/src/cloud/meta-merger/tenant-ledger.ts +++ b/src/cloud/meta-merger/tenant-ledger.ts @@ -1,8 +1,7 @@ import { ResolveOnce } from "@adviser/cement"; +import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js"; import { TenantSql } from "./tenant.js"; -import type { Database, Statement } from "better-sqlite3"; - export interface TenantLedgerRow { readonly tenant: string; readonly ledger: string; @@ -10,10 +9,13 @@ export interface TenantLedgerRow { } export class TenantLedgerSql { - static schema() { + static schema(drop = false) { return [ - ...TenantSql.schema(), - ` + ...TenantSql.schema(drop), + ...conditionalDrop( + drop, + "TenantLedger", + ` CREATE TABLE IF NOT EXISTS TenantLedger( tenant TEXT NOT NULL, ledger TEXT NOT NULL, @@ -21,26 +23,27 @@ export class TenantLedgerSql { PRIMARY KEY(tenant, ledger), FOREIGN KEY(tenant) REFERENCES Tenant(tenant) ) - `, + ` + ), ]; } - readonly db: Database; + readonly db: SQLDatabase; readonly tenantSql: TenantSql; - constructor(db: Database, tenantSql: TenantSql) { + constructor(db: SQLDatabase, tenantSql: TenantSql) { this.db = db; this.tenantSql = tenantSql; } - readonly #sqlCreateTenantLedger = new ResolveOnce(); - sqlCreateTenantLedger(): Statement[] { + readonly #sqlCreateTenantLedger = new ResolveOnce(); + sqlCreateTenantLedger(): SQLStatement[] { return this.#sqlCreateTenantLedger.once(() => { return TenantLedgerSql.schema().map((i) => this.db.prepare(i)); }); } - readonly #sqlInsertTenantLedger = new ResolveOnce>(); - sqlEnsureTenantLedger(): Statement<[string, string, string, string, string]> { + readonly #sqlInsertTenantLedger = new ResolveOnce(); + sqlEnsureTenantLedger(): SQLStatement { return this.#sqlInsertTenantLedger.once(() => { return this.db.prepare(` INSERT INTO TenantLedger(tenant, ledger, createdAt) @@ -51,8 +54,8 @@ export class TenantLedgerSql { } async ensure(t: TenantLedgerRow) { - await this.tenantSql.ensure(t); + this.tenantSql.ensure({ tenant: t.tenant, createdAt: t.createdAt }); const stmt = this.sqlEnsureTenantLedger(); - return stmt.run(t.tenant, t.ledger, t.createdAt.toISOString(), t.tenant, t.ledger); + return stmt.run(t.tenant, t.ledger, t.createdAt, t.tenant, t.ledger); } } diff --git a/src/cloud/meta-merger/tenant.ts b/src/cloud/meta-merger/tenant.ts index e9479c28..3ee67001 100644 --- a/src/cloud/meta-merger/tenant.ts +++ b/src/cloud/meta-merger/tenant.ts @@ -1,5 +1,5 @@ import { ResolveOnce } from "@adviser/cement"; -import type { Database, Statement } from "better-sqlite3"; +import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js"; export interface TenantRow { readonly tenant: string; @@ -7,31 +7,35 @@ export interface TenantRow { } export class TenantSql { - static schema(): string[] { + static schema(drop = false): string[] { return [ - ` + ...conditionalDrop( + drop, + "Tenant", + ` CREATE TABLE IF NOT EXISTS Tenant( tenant TEXT NOT NULL PRIMARY KEY, createdAt TEXT NOT NULL ) - `, + ` + ), ]; } - readonly db: Database; - constructor(db: Database) { + readonly db: SQLDatabase; + constructor(db: SQLDatabase) { this.db = db; } - readonly #sqlCreateTenant = new ResolveOnce(); - sqlCreateTenant(): Statement[] { + readonly #sqlCreateTenant = new ResolveOnce(); + sqlCreateTenant(): SQLStatement[] { return this.#sqlCreateTenant.once(() => { return TenantSql.schema().map((i) => this.db.prepare(i)); }); } - readonly #sqlInsertTenant = new ResolveOnce(); - sqlEnsureTenant(): Statement<[string, string, string], void> { + readonly #sqlInsertTenant = new ResolveOnce(); + sqlEnsureTenant(): SQLStatement { return this.#sqlInsertTenant.once(() => { return this.db.prepare(` INSERT INTO Tenant(tenant, createdAt) @@ -42,6 +46,6 @@ export class TenantSql { async ensure(t: TenantRow) { const stmt = this.sqlEnsureTenant(); - return stmt.run(t.tenant, t.createdAt.toISOString(), t.tenant); + return stmt.run(t.tenant, t.createdAt, t.tenant); } } diff --git a/src/sql/sqlite.test.ts b/src/sql/sqlite.test.ts index 34e7cba2..a41f9891 100644 --- a/src/sql/sqlite.test.ts +++ b/src/sql/sqlite.test.ts @@ -1,4 +1,5 @@ -import { ensureSuperThis, fireproof, SysFileSystem, rt } from "@fireproof/core"; +import { ensureSuperThis, fireproof, SysFileSystem } from "@fireproof/core"; +import { getFileSystem } from "@fireproof/core/node"; import { registerSqliteStoreProtocol } from "./gateway-sql.js"; import { V0_19SQL_VERSION } from "./v0.19/version.js"; import { URI } from "@adviser/cement"; @@ -27,7 +28,7 @@ describe("sqlite", () => { beforeAll(async () => { await sthis.start(); - fsx = await rt.getFileSystem(URI.from("file:///")); + fsx = await getFileSystem(URI.from("file:///")); registerSqliteStoreProtocol(); const url = URI.from(process.env.FP_STORAGE_URL || "dummy://"); taste = url.getParam("taste") || "better-sqlite3"; diff --git a/src/sql/v0.19/sqlite_factory.ts b/src/sql/v0.19/sqlite_factory.ts index 3bce90b5..3bc9e871 100644 --- a/src/sql/v0.19/sqlite_factory.ts +++ b/src/sql/v0.19/sqlite_factory.ts @@ -1,4 +1,5 @@ -import { Logger, SuperThis, SysFileSystem, rt } from "@fireproof/core"; +import { Logger, SuperThis, SysFileSystem } from "@fireproof/core"; +import { getFileSystem } from "@fireproof/core/node"; import { DataSQLStore, DBConnection, MetaSQLStore, SQLOpts, WalSQLStore } from "../types.js"; import { ResolveOnce, URI } from "@adviser/cement"; import { SQLConnectionResult } from "../sql-connection-factory.js"; @@ -55,7 +56,7 @@ export abstract class Sqlite3Connection implements DBConnection { private readonly _fs = new ResolveOnce(); async fs(): Promise { return this._fs.once(async () => { - return rt.getFileSystem(URI.from("file:///")); + return getFileSystem(URI.from("file:///")); }); } } diff --git a/tsconfig.json b/tsconfig.json index 2fc28ed2..f5f728c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -41,7 +41,9 @@ "types": [ "vitest/globals", "@cloudflare/workers-types", - "@cloudflare/workers-types/2023-07-01" + "@cloudflare/workers-types/2023-07-01", + "@cloudflare/vitest-pool-workers" + // node_modules/@cloudflare/workers-types/2023-07-01/index.d.ts // "@cloudflare/vitest-pool-workers" ], diff --git a/vitest.cf-kv.config.ts b/vitest.cf-worker.config.ts similarity index 68% rename from vitest.cf-kv.config.ts rename to vitest.cf-worker.config.ts index 65b18bea..a32f73ca 100644 --- a/vitest.cf-kv.config.ts +++ b/vitest.cf-worker.config.ts @@ -6,12 +6,12 @@ export default defineWorkersConfig({ test: { poolOptions: { workers: { - wrangler: { configPath: "./wrangler.toml" }, + wrangler: { configPath: "./src/cloud/backend/wrangler.toml" }, }, }, - name: "cf-kv", + name: "cf-worker", exclude: ["node_modules/@fireproof/core/tests/react/**"], - include: ["src/cf-inde*.test.ts", "node_modules/@fireproof/core/tests/**/*test.?(c|m)[jt]s?(x)"], + include: ["src/cloud/meta-merger/*.test.ts"], globals: true, setupFiles: "./setup.cf-kv.ts", }, diff --git a/vitest.workspace.ts b/vitest.workspace.ts index bcb837c4..eea2d793 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -9,7 +9,7 @@ import s3 from "./vitest.s3.config.ts"; // import connector from "./vitest.connector.config.ts"; import netlify from "./vitest.netlify.config.ts"; import ucan from "./vitest.ucan.config.ts"; -// import cf_kv from "./vitest.cf-kv.config.ts"; +import cfWorker from "./vitest.cf-worker.config.ts"; export default defineWorkspace([ nodeSqlite3Wasm, @@ -20,6 +20,6 @@ export default defineWorkspace([ netlify, partykit, cloud, - //cf_kv + cfWorker, ucan, ]); From a36355661e2f005e535a604dfa48f25d43b1c782 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 3 Jan 2025 11:07:03 +0100 Subject: [PATCH 75/83] chore: stablize the tests --- src/cloud/backend/cf-hono-server.ts | 59 +++++++++++++++++++---- src/cloud/backend/server.ts | 5 +- src/cloud/backend/wrangler.toml | 11 +++++ src/cloud/connection.test.ts | 4 +- src/cloud/hono-server.ts | 15 +++--- src/cloud/meta-merger/meta-merger.test.ts | 2 +- src/cloud/msg-dispatch.ts | 39 +++++++++++---- src/cloud/node-hono-server.ts | 1 + src/cloud/test-helper.ts | 11 +++++ 9 files changed, 114 insertions(+), 33 deletions(-) diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index af3c7a86..ef09bb61 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -1,11 +1,11 @@ import { HttpHeader, Logger, Result, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; import { HonoServerImpl, CORS, ConnMiddleware } from "../hono-server.js"; -import { WSEvents } from "hono/ws"; +import { WSContext, WSContextInit, WSEvents } from "hono/ws"; import { buildErrorMsg, EnDeCoder } from "../msg-types.js"; import { ensureLogger, SuperThis } from "@fireproof/core"; import { Env } from "./env.js"; -import { RequestInfo as CFRequestInfo } from "@cloudflare/workers-types"; +// import { RequestInfo as CFRequestInfo } from "@cloudflare/workers-types"; import { calculatePreSignedUrl, PreSignedConnMsg } from "../pre-signed-url.js"; export class CFHonoServer implements HonoServerImpl { @@ -16,6 +16,7 @@ export class CFHonoServer implements HonoServerImpl { readonly logger: Logger; readonly ende: EnDeCoder; readonly env: Env; + // readonly wsConnections = new Map() constructor(sthis: SuperThis, ende: EnDeCoder, env: Env, headers?: HttpHeader) { this.headers = HttpHeader.from(headers).Merge(CORS); this.sthis = sthis; @@ -47,18 +48,56 @@ export class CFHonoServer implements HonoServerImpl { const upgradeHeader = c.req.header("Upgrade"); if (!upgradeHeader || upgradeHeader !== "websocket") { return new Response( - this.ende.encode( - buildErrorMsg(this.sthis, this.logger, {}, new Error("Durable Object expected Upgrade: websocket")) - ), + this.ende.encode(buildErrorMsg(this.sthis, this.logger, {}, new Error("expected Upgrade: websocket"))), { status: 426 } ); } - const env = c.env as Env; - const id = env.FP_META_GROUPS.idFromName([conn.key.tenant, conn.key.ledger].join(":")); - const dObj = env.FP_META_GROUPS.get(id); - c.env.WS_EVENTS = createEvents(c); - return dObj.fetch(c.req.raw as unknown as CFRequestInfo) as unknown as Promise; + // const env = c.env as Env; + // const id = env.FP_META_GROUPS.idFromName([conn.key.tenant, conn.key.ledger].join(":")); + // const dObj = env.FP_META_GROUPS.get(id); + // c.env.WS_EVENTS = createEvents(c); + // return dObj.fetch(c.req.raw as unknown as CFRequestInfo) as unknown as Promise; // this._upgradeWebSocket!(createEvents)(c, next); + + const { 0: client, 1: server } = new WebSocketPair(); + conn.attachWSPair({ client, server }); + + const wsEvents = await createEvents(c); + // console.log("upgradeWebSocket", c.req.url); + + const wsCtx = new WSContext(server as WSContextInit); + + // server.onopen = (ev) => { + // console.log("onopen", ev); + // wsEvents.onOpen?.(ev, wsCtx); + // } + server.onerror = (err) => { + // console.log("onerror", err); + wsEvents.onError?.(err, wsCtx); + }; + server.onclose = (ev) => { + // console.log("onclose", ev); + wsEvents.onClose?.(ev, wsCtx); + }; + server.onmessage = (evt) => { + // console.log("onmessage", evt); + // wsCtx.send("Hellox from server"); + wsEvents.onMessage?.(evt, wsCtx); + }; + server.accept(); + + wsEvents.onOpen?.({} as Event, wsCtx); + + // server.send("Hello from server"); + + // this.wsConnections.set(this.sthis.nextId().str, { client, server }); + // const client = webSocketPair[0], + // server = webSocketPair[1]; + + return new Response(null, { + status: 101, + webSocket: client, + }); }; } diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 44d0efb2..9a237100 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -408,10 +408,9 @@ const once = new ResolveOnce(); export default { fetch: async (req, env, ctx): Promise => { + const logger = ensureLogger(env, "CF-Fireproof"); await once.once(() => { - const sthis = ensureSuperThis({ - logger: ensureLogger(env, "CF-Fireproof"), - }); + const sthis = ensureSuperThis({ logger }); const msgP = defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: env.FP_PROTOCOL diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index e0e244d6..a4ad5341 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -38,6 +38,12 @@ bindings = [ { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, ] +[[env.test-reqRes.d1_databases]] +binding = "DB" +database_name = "test-meta-merge" +database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" + + [env.test-stream.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" @@ -52,3 +58,8 @@ FP_PROTOCOL = "ws" bindings = [ { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, ] + +[[env.test-stream.d1_databases]] +binding = "DB" +database_name = "test-meta-merge" +database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" \ No newline at end of file diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index c5877a81..3a82b538 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -54,7 +54,7 @@ const sthis = ensureSuperThis(); const msgP = defaultMsgParams(sthis, { hasPersistent: true }); for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { describe(`${honoServer.name} - Connection`, () => { - const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); + const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { key: { ledger: "test", @@ -141,7 +141,7 @@ for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { assert.fail(JSON.stringify(r)); } expect(r).toEqual({ - conn: c.conn, + conn: { ...c.conn, resId: r.conn?.resId }, tid: req.tid, type: "resOpen", version: "FP-MSG-1.0", diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index 804c9361..ff7c941b 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -2,13 +2,13 @@ import { exception2Result, HttpHeader, Result, URI } from "@adviser/cement"; import { ensureLogger, Logger, SuperThis } from "@fireproof/core"; import { Context, Hono, Next } from "hono"; import { top_uint8 } from "../coerce-binary.js"; -import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg, Connection, MsgBase, buildResOpen } from "./msg-types.js"; -import { MsgDispatcher } from "./msg-dispatch.js"; +import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg, MsgBase, buildResOpen } from "./msg-types.js"; +import { MsgDispatcher, WSConnection } from "./msg-dispatch.js"; import { WSEvents } from "hono/ws"; import { PreSignedConnMsg } from "./pre-signed-url.js"; // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -export type ConnMiddleware = (conn: Connection, c: Context, next: Next) => Promise; +export type ConnMiddleware = (conn: WSConnection, c: Context, next: Next) => Promise; export interface HonoServerImpl { start(app: Hono): Promise; serve(app: Hono, port?: number): Promise; @@ -43,7 +43,6 @@ export class HonoServer { await this.impl.start(app); // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) - const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); app.put("/fp", async (c) => { this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); const rMsg = await exception2Result(() => c.req.json() as Promise); @@ -51,6 +50,7 @@ export class HonoServer { c.status(400); return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rMsg.Err())); } + const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); return dispatcher.dispatch(this.impl, rMsg.Ok(), (msg) => c.json(msg)); }); app.get("/ws", async (c, next) => { @@ -77,7 +77,7 @@ export class HonoServer { if (rConn.isErr()) { ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rConn.Err()))); } else { - ws.send(this.msgP.ende.encode(buildResOpen(this.sthis, reqOpen, rConn.Ok().resId))); + ws.send(this.msgP.ende.encode(buildResOpen(this.sthis, reqOpen, rConn.Ok().conn.resId))); } }, onError: (error) => { @@ -90,17 +90,18 @@ export class HonoServer { if (rMsg.isErr()) { ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rMsg.Err()))); } else { - dp.dispatch(this.impl, rMsg.Ok(), (msg) => { + await dp.dispatch(this.impl, rMsg.Ok(), (msg) => { const str = this.msgP.ende.encode(msg); ws.send(str); }); } }, onClose: () => { + dp = undefined as unknown as MsgDispatcher; // console.log('Connection closed') }, }; - })(reqOpen.conn, c, next); + })(new WSConnection(reqOpen.conn), c, next); }); await this.impl.serve(app, port); return this; diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index 2a8796a8..ed69c47a 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -4,7 +4,7 @@ import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; import { Connection } from "../msg-types.js"; import { runtimeFn } from "@adviser/cement"; import { SQLDatabase } from "./abstract-sql.js"; -import type { Env } from '../backend/env.js' +import type { Env } from "../backend/env.js"; function sortCRDTEntries(rows: CRDTEntry[]) { return rows.sort((a, b) => a.cid.localeCompare(b.cid)); diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts index efe41ca4..5fdf60c6 100644 --- a/src/cloud/msg-dispatch.ts +++ b/src/cloud/msg-dispatch.ts @@ -33,10 +33,30 @@ export interface MsgContext { calculatePreSignedUrl(p: PreSignedMsg): Promise; } +export interface WSPair { + readonly client: WebSocket; + readonly server: WebSocket; +} + +export class WSConnection { + readonly conn: Connection; + wspair?: WSPair; + constructor(conn: Connection) { + this.conn = conn; + } + attachWSPair(wsp: WSPair) { + if (!this.wspair) { + this.wspair = wsp; + } else { + throw new Error("wspair already set"); + } + } +} + export class MsgDispatcher { readonly sthis: SuperThis; readonly logger: Logger; - conn?: Connection; + wsConn?: WSConnection; readonly gestalt: Gestalt; readonly id: string; @@ -47,15 +67,15 @@ export class MsgDispatcher { this.id = sthis.nextId().str; } - addConn(aConn: Connection): Result { - if (!this.conn) { - this.conn = { ...aConn, resId: this.sthis.nextId().str }; - return Result.Ok(this.conn); + addConn(aConn: Connection): Result { + if (!this.wsConn) { + this.wsConn = new WSConnection({ ...aConn, resId: this.sthis.nextId().str }); + return Result.Ok(this.wsConn); } - if (aConn.reqId === this.conn.reqId) { - return Result.Ok(this.conn); + if (aConn.reqId === this.wsConn.conn.reqId) { + return Result.Ok(this.wsConn); } - return this.logger.Error().Msg(`unexpected reqId: ${aConn.reqId}!==${this.conn.reqId}`).ResultError(); + return this.logger.Error().Msg(`unexpected reqId: ${aConn.reqId}!==${this.wsConn.conn.reqId}`).ResultError(); } async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => void) { @@ -71,9 +91,8 @@ export class MsgDispatcher { if (rConn.isErr()) { return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); } - return send(buildResOpen(this.sthis, msg, rConn.Ok().resId)); + return send(buildResOpen(this.sthis, msg, rConn.Ok().conn.resId)); } - case MsgIsReqGetData(msg): { return send(await buildResGetData(this.sthis, this.logger, msg, ctx)); } diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 743fc482..e90969d2 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -37,6 +37,7 @@ export class NodeHonoServer implements HonoServerImpl { upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { return async (_conn, c, next) => { + // conn.attachWSPair({ client: c.req, server: c.res }); return this._upgradeWebSocket(createEvents)(c, next); }; } diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts index 1e162fdf..801df87d 100644 --- a/src/cloud/test-helper.ts +++ b/src/cloud/test-helper.ts @@ -152,6 +152,17 @@ export function CFHonoServerFactory() { return { name: "CFHonoServer", factory: async (_sthis: SuperThis, _msgP: MsgerParams, remoteGestalt: Gestalt, port: number) => { + if (process.env.FP_WRANGLER_PORT) { + const hs = { + start: async () => { + return hs; + }, + close: async () => { + /* */ + }, + } as unknown as HonoServer; + return hs; + } const { tomlFile } = await resolveToml(); $.verbose = !!process.env.FP_DEBUG; const runningWrangler = $` From 3e0be90b17067a9096198ccf6ea1b66c7827154f Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Mon, 6 Jan 2025 09:56:07 +0100 Subject: [PATCH 76/83] WIP --- package.json | 4 +- pnpm-lock.yaml | 12 +- setup.cloud.ts | 5 +- src/cloud/backend/cf-hono-server.ts | 110 ++++--- src/cloud/backend/server.ts | 70 +---- src/cloud/client/cloud-gateway.test.ts | 192 ++++++------ src/cloud/connection.test.ts | 390 +++++++++++++------------ src/cloud/hono-server.ts | 229 +++++++++------ src/cloud/http-connection.ts | 50 ++-- src/cloud/msg-dispatch.ts | 71 +++-- src/cloud/msg-types.ts | 16 +- src/cloud/msger.ts | 39 ++- src/cloud/node-hono-server.ts | 75 +++-- src/cloud/test-helper.ts | 34 +-- src/cloud/ws-connection.ts | 23 +- 15 files changed, 713 insertions(+), 607 deletions(-) diff --git a/package.json b/package.json index 9602295b..9790b835 100644 --- a/package.json +++ b/package.json @@ -88,10 +88,10 @@ }, "homepage": "https://github.com/fireproof-storage/connect#readme", "peerDependencies": { - "@adviser/cement": "^0.3.2" + "@adviser/cement": "^0.3.5" }, "dependencies": { - "@adviser/cement": "^0.3.2", + "@adviser/cement": "^0.3.5", "@aws-sdk/client-s3": "^3.717.0", "@cloudflare/vitest-pool-workers": "^0.5.30", "@cloudflare/workers-types": "^4.20241127.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f857f4d9..36e47dc6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adviser/cement': - specifier: ^0.3.2 - version: 0.3.4(typescript@5.7.2) + specifier: ^0.3.5 + version: 0.3.5(typescript@5.7.2) '@aws-sdk/client-s3': specifier: ^3.717.0 version: 3.717.0 @@ -216,8 +216,8 @@ importers: packages: - '@adviser/cement@0.3.4': - resolution: {integrity: sha512-wG0rIHej2uvXGknp0mokM/8reXXtFg9wiWDzuXXmaxzjaae4cVG4og76SeQf9suWb+MiyPsn19B7HX+gFvIs7A==} + '@adviser/cement@0.3.5': + resolution: {integrity: sha512-U3BFsID8Fhe5ARmBEXQKw2yPyP1egT2LX8/gNCa8ZCobQjA52RkbEWwL0l8Gs6kDUqay1xhsKbQ9O7cYxLFnSg==} engines: {node: '>=20'} '@aws-crypto/crc32@5.2.0': @@ -4258,7 +4258,7 @@ packages: snapshots: - '@adviser/cement@0.3.4(typescript@5.7.2)': + '@adviser/cement@0.3.5(typescript@5.7.2)': dependencies: ts-essentials: 10.0.2(typescript@5.7.2) yaml: 2.5.1 @@ -5260,7 +5260,7 @@ snapshots: '@fireproof/core@0.19.121(react@18.3.1)(typescript@5.7.2)': dependencies: - '@adviser/cement': 0.3.4(typescript@5.7.2) + '@adviser/cement': 0.3.5(typescript@5.7.2) '@fireproof/vendor': 1.0.4 '@ipld/unixfs': 3.0.0 charwise: 3.0.1 diff --git a/setup.cloud.ts b/setup.cloud.ts index eb624898..fbe41c0d 100644 --- a/setup.cloud.ts +++ b/setup.cloud.ts @@ -1,10 +1,11 @@ import { BuildURI } from "@adviser/cement"; + // import { registerFireproofCloudStoreProtocol } from "./src/cloud/client/gateway.ts"; -import dotenv from "dotenv"; +// import dotenv from "dotenv"; // registerFireproofCloudStoreProtocol(); -dotenv.config(); +// dotenv.config(); process.env.FP_STORAGE_URL = BuildURI.from("fireproof://localhost:1968") // .setParam("testMode", "true") diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index ef09bb61..b1886240 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -1,44 +1,94 @@ -import { HttpHeader, Logger, Result, URI } from "@adviser/cement"; +import { HttpHeader, Logger, LoggerImpl, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; -import { HonoServerImpl, CORS, ConnMiddleware } from "../hono-server.js"; +import { CORS, ConnMiddleware, HonoServerFactory, RunTimeParams, HonoServerBase } from "../hono-server.js"; import { WSContext, WSContextInit, WSEvents } from "hono/ws"; -import { buildErrorMsg, EnDeCoder } from "../msg-types.js"; -import { ensureLogger, SuperThis } from "@fireproof/core"; -import { Env } from "./env.js"; +import { buildErrorMsg, defaultGestalt, EnDeCoder, Gestalt } from "../msg-types.js"; // import { RequestInfo as CFRequestInfo } from "@cloudflare/workers-types"; -import { calculatePreSignedUrl, PreSignedConnMsg } from "../pre-signed-url.js"; +import { defaultMsgParams, jsonEnDe } from "../msger.js"; +import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; -export class CFHonoServer implements HonoServerImpl { +// function ensureLogger(env: Env, module = "Fireproof"): Logger { +// const logger = new LoggerImpl() +// .With() +// .Module(module) +// .SetDebug(env.FP_DEBUG) +// .SetExposeStack(!!env.FP_STACK || false); +// switch (env.FP_FORMAT) { +// case "jsonice": +// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); +// break; +// case "yaml": +// logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); +// break; +// case "json": +// default: +// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); +// break; +// } +// return logger.Logger(); +// } + +export class CFHonoFactory implements HonoServerFactory { + readonly _onClose: () => void; + constructor(onClose: () => void = () => { /* */ }) { + this._onClose = onClose; + } + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + inject(c: Context, fn: (rt: RunTimeParams) => Promise): Promise { + // this._env = c.env + const sthis = ensureSuperThis({ + logger: new LoggerImpl(), + }); + sthis.env.sets(c.env); + const logger = ensureLogger(sthis, `CFHono[${URI.from(c.req.url).pathname}]`); + const ende = jsonEnDe(sthis); + // this.sthis.env. + const fpProtocol = sthis.env.get("FP_PROTOCOL"); + const msgP = defaultMsgParams(sthis, { + hasPersistent: true, + protocolCapabilities: fpProtocol ? (fpProtocol === "ws" ? ["stream"] : ["reqRes"]) : ["reqRes", "stream"], + }); + const gs = defaultGestalt(msgP, { + id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", + }); + + const ret = fn({ sthis, logger, ende, impl: new CFHonoServer(sthis, logger, ende, gs) }); + return ret // .then((v) => sthis.logger.Flush().then(() => v)) + } + + async start(_app: Hono): Promise { + // const { upgradeWebSocket } = await import("hono/cloudflare-workers"); + // this._upgradeWebSocket = upgradeWebSocket; + } + + async serve(_app: Hono, _port?: number): Promise { + return {} as T; + } + async close(): Promise { + this._onClose() + return; + } +} + +export class CFHonoServer extends HonoServerBase { // _upgradeWebSocket?: UpgradeWebSocket readonly headers: HttpHeader; - readonly sthis: SuperThis; - readonly logger: Logger; readonly ende: EnDeCoder; - readonly env: Env; + // readonly env: Env; // readonly wsConnections = new Map() - constructor(sthis: SuperThis, ende: EnDeCoder, env: Env, headers?: HttpHeader) { + constructor(sthis: SuperThis, logger: Logger, ende: EnDeCoder, gs: Gestalt, headers?: HttpHeader) { + super(sthis, logger, gs) this.headers = HttpHeader.from(headers).Merge(CORS); - this.sthis = sthis; - this.logger = ensureLogger(sthis, "CFHonoServer"); this.ende = ende; - this.env = env; + // this.env = env; } // getDurableObject(conn: Connection) { // const id = env.FP_META_GROUPS.idFromName("fireproof"); // const stub = env.FP_META_GROUPS.get(id); // } - calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { - return calculatePreSignedUrl(p, { - storageUrl: URI.from(this.env.STORAGE_URL), - aws: { - accessKeyId: this.env.ACCESS_KEY_ID, - secretAccessKey: this.env.SECRET_ACCESS_KEY, - region: this.env.REGION, - }, - }); - } + upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { // if (!this._upgradeWebSocket) { @@ -100,16 +150,4 @@ export class CFHonoServer implements HonoServerImpl { }); }; } - - async start(_app: Hono): Promise { - // const { upgradeWebSocket } = await import("hono/cloudflare-workers"); - // this._upgradeWebSocket = upgradeWebSocket; - } - - async serve(_app: Hono, _port?: number): Promise { - return {} as T; - } - async close(): Promise { - return; - } } diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 9a237100..a8fb40b1 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,41 +1,17 @@ // / -import { JSONFormatter, Logger, LoggerImpl, ResolveOnce, YAMLFormatter } from "@adviser/cement"; -import { defaultGestalt } from "../msg-types.js"; +import { Logger } from "@adviser/cement"; // import { Hono } from "hono"; -import { ensureSuperThis } from "@fireproof/core"; import { DurableObject } from "cloudflare:workers"; import { HonoServer } from "../hono-server.js"; import { Hono } from "hono"; -import { defaultMsgParams } from "../msger.js"; import { Env } from "./env.js"; -import { CFHonoServer } from "./cf-hono-server.js"; +import { CFHonoFactory } from "./cf-hono-server.js"; import { WSContext, WSEvents } from "hono/ws"; // function json(data: T, status = 200) { // return Response.json(data, { status, headers: CORS }); // } -function ensureLogger(env: Env, module = "Fireproof"): Logger { - const logger = new LoggerImpl() - .With() - .Module(module) - .SetDebug(env.FP_DEBUG) - .SetExposeStack(!!env.FP_STACK || false); - switch (env.FP_FORMAT) { - case "jsonice": - logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); - break; - case "yaml": - logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); - break; - case "json": - default: - logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); - break; - } - return logger.Logger(); -} - // interface MsgStats { // readonly msgSeq: number; // } @@ -71,20 +47,20 @@ export class FPMetaGroups extends DurableObject { // readonly sessions: Map = new Map(); // readonly lastMetaByTendant = new Map[]>(); - readonly logger: Logger; + logger!: Logger; readonly wsEvents: WSEvents = {}; - constructor(ctx: DurableObjectState, env: Env) { - super(ctx, env); - this.logger = ensureLogger(env, "FPMetaGroups"); - // this.ctx.getWebSockets().forEach((webSocket) => { - // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; - // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { - // this.sessions.set(webSocket, fpMetaGroup); - // } - // }); - } + // constructor(ctx: DurableObjectState, env: Env) { + // super(ctx, env); + // // this.logger = ensureLogger(env, "FPMetaGroups"); + // // this.ctx.getWebSockets().forEach((webSocket) => { + // // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; + // // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { + // // this.sessions.set(webSocket, fpMetaGroup); + // // } + // // }); + // } // injectWSEvents(wsEvents: WSEvents): void { // Object.assign(this.wsEvents, wsEvents); @@ -404,27 +380,11 @@ export class FPMetaGroups extends DurableObject { // } const app = new Hono(); -const once = new ResolveOnce(); +const honoServer = new HonoServer(new CFHonoFactory()); export default { fetch: async (req, env, ctx): Promise => { - const logger = ensureLogger(env, "CF-Fireproof"); - await once.once(() => { - const sthis = ensureSuperThis({ logger }); - const msgP = defaultMsgParams(sthis, { - hasPersistent: true, - protocolCapabilities: env.FP_PROTOCOL - ? env.FP_PROTOCOL === "ws" - ? ["stream"] - : ["reqRes"] - : ["reqRes", "stream"], - }); - const gs = defaultGestalt(msgP, { - id: env.FP_PROTOCOL ? (env.FP_PROTOCOL === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", - }); - const honoServer = new HonoServer(sthis, msgP, gs, new CFHonoServer(sthis, msgP.ende, env)); - return honoServer.start(app); - }); + await honoServer.register(app); return app.fetch(req, env, ctx); }, } satisfies ExportedHandler; diff --git a/src/cloud/client/cloud-gateway.test.ts b/src/cloud/client/cloud-gateway.test.ts index 8567450a..26df9a00 100644 --- a/src/cloud/client/cloud-gateway.test.ts +++ b/src/cloud/client/cloud-gateway.test.ts @@ -10,7 +10,8 @@ import { BuildURI } from "@adviser/cement"; const sthis = ensureSuperThis(); const msgP = defaultMsgParams(sthis, { hasPersistent: true }); const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); -for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { + +describe.each([NodeHonoServerFactory(), CFHonoServerFactory()])("$name - Gateway", ({ factory }) => { const qOpen = buildReqOpen(sthis, { key: { ledger: "test", @@ -19,111 +20,110 @@ for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { }); const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); const style = wsStyle(sthis, port, msgP, qOpen, my); - describe(`${honoServer.name} - Gateway`, () => { - let server: HonoServer; - let gw: bs.Gateway; - let unregister: () => void; - let url: BuildURI; - beforeAll(async () => { - const app = new Hono(); - server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).start(app, port); - unregister = registerFireproofCloudStoreProtocol("fireproof:"); - gw = new FireproofCloudGateway(sthis); - url = BuildURI.from(`fireproof://localhost:${port}/`) - .setParam("protocol", "http") - .setParam("name", "ledger-name") - .setParam("tenant", "tendant"); - }); - afterAll(async () => { - await server.close(); - unregister(); + + let server: HonoServer; + let gw: bs.Gateway; + let unregister: () => void; + let url: BuildURI; + beforeAll(async () => { + const app = new Hono(); + server = await factory(sthis, msgP, style.remoteGestalt, port).then((srv) => srv.register(app, port)); + unregister = registerFireproofCloudStoreProtocol("fireproof:"); + gw = new FireproofCloudGateway(sthis); + url = BuildURI.from(`fireproof://localhost:${port}/`) + .setParam("protocol", "http") + .setParam("name", "ledger-name") + .setParam("tenant", "tendant"); + }); + afterAll(async () => { + await server.close(); + unregister(); + }); + describe("data", () => { + it("get not found", async () => { + await Promise.all( + Array(20) + .fill(async () => { + url.setParam("store", "data"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); }); - describe("data", () => { - it("get not found", async () => { - await Promise.all( - Array(20) - .fill(async () => { - url.setParam("store", "data"); - const key = `theDataKey-${sthis.nextId().str}`; - const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); - const res = await gw.get(kurl); - expect(res.isErr()).toBeTruthy(); - expect(res.Err()).toBeInstanceOf(NotFoundError); - }) - .map((f) => f()) - ); - }); - it("put - get - del - get", async () => { - await Promise.all( - Array(20) - .fill(async () => { - const resStart = await gw.start(url.URI()); - expect(resStart.isOk()).toBeTruthy(); + it("put - get - del - get", async () => { + await Promise.all( + Array(20) + .fill(async () => { + const resStart = await gw.start(url.URI()); + expect(resStart.isOk()).toBeTruthy(); - url.setParam("store", "data"); - const key = `theDataKey-${sthis.nextId().str}`; - const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + url.setParam("store", "data"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); - const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); - expect(resPut.isOk()).toBeTruthy(); - const resGet = await gw.get(kurl); - expect(resGet.isOk()).toBeTruthy(); - expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); - const resDel = await gw.delete(kurl); - expect(resDel.isOk()).toBeTruthy(); + const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); + expect(resPut.isOk()).toBeTruthy(); + const resGet = await gw.get(kurl); + expect(resGet.isOk()).toBeTruthy(); + expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); + const resDel = await gw.delete(kurl); + expect(resDel.isOk()).toBeTruthy(); - const res = await gw.get(kurl); - expect(res.isErr()).toBeTruthy(); - expect(res.Err()).toBeInstanceOf(NotFoundError); - }) - .map((f) => f()) - ); - }); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); }); + }); - describe("WAL", () => { - it("get not found", async () => { - await Promise.all( - Array(20) - .fill(async () => { - url.setParam("store", "wal"); - const key = `theDataKey-${sthis.nextId().str}`; - const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); - const res = await gw.get(kurl); - expect(res.isErr()).toBeTruthy(); - expect(res.Err()).toBeInstanceOf(NotFoundError); - }) - .map((f) => f()) - ); - }); + describe("WAL", () => { + it("get not found", async () => { + await Promise.all( + Array(20) + .fill(async () => { + url.setParam("store", "wal"); + const key = `theDataKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); + }); - it("put - get - del - get", async () => { - await Promise.all( - Array(20) - .fill(async () => { - const resStart = await gw.start(url.URI()); - expect(resStart.isOk()).toBeTruthy(); + it("put - get - del - get", async () => { + await Promise.all( + Array(20) + .fill(async () => { + const resStart = await gw.start(url.URI()); + expect(resStart.isOk()).toBeTruthy(); - url.setParam("store", "wal"); - const key = `theWALKey-${sthis.nextId().str}`; - const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); + url.setParam("store", "wal"); + const key = `theWALKey-${sthis.nextId().str}`; + const kurl = (await gw.buildUrl(url.URI(), key)).Ok(); - const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); - expect(resPut.isOk()).toBeTruthy(); - const resGet = await gw.get(kurl); - expect(resGet.isOk()).toBeTruthy(); - expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); - const resDel = await gw.delete(kurl); - expect(resDel.isOk()).toBeTruthy(); + const resPut = await gw.put(kurl, sthis.txt.encode("Hello, World!")); + expect(resPut.isOk()).toBeTruthy(); + const resGet = await gw.get(kurl); + expect(resGet.isOk()).toBeTruthy(); + expect(sthis.txt.decode(resGet.Ok())).toBe("Hello, World!"); + const resDel = await gw.delete(kurl); + expect(resDel.isOk()).toBeTruthy(); - const res = await gw.get(kurl); - expect(res.isErr()).toBeTruthy(); - expect(res.Err()).toBeInstanceOf(NotFoundError); - }) - .map((f) => f()) - ); - }); + const res = await gw.get(kurl); + expect(res.isErr()).toBeTruthy(); + expect(res.Err()).toBeInstanceOf(NotFoundError); + }) + .map((f) => f()) + ); }); }); -} +}); diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 3a82b538..b230c817 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -50,216 +50,224 @@ async function refURL(sp: PreSignedMsg) { .asObj(); } -const sthis = ensureSuperThis(); -const msgP = defaultMsgParams(sthis, { hasPersistent: true }); -for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { - describe(`${honoServer.name} - Connection`, () => { - const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); - const qOpen = buildReqOpen(sthis, { - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", - }); - const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); - for (const style of [httpStyle(sthis, port, msgP, qOpen, my), wsStyle(sthis, port, msgP, qOpen, my)]) { - describe(style.name, () => { - let server: HonoServer; - beforeAll(async () => { - const app = new Hono(); - server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).start(app, port); - }); - afterAll(async () => { - await server.close(); - }); - it(`conn refused`, async () => { - const rC = await applyStart(style.connRefused.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/ECONNREFUSED/); - }); +describe("Connection", () => { + const sthis = ensureSuperThis(); + const msgP = defaultMsgParams(sthis, { hasPersistent: true }); - it(`timeout`, async () => { - const rC = await applyStart(style.timeout.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/Timeout/i); - }); + beforeAll(async () => { + sthis.env.sets((await resolveToml()).env as unknown as Record); + }) - describe(`connection`, () => { - let c: MsgConnection; - beforeEach(async () => { - const rC = await style.ok.open(); - expect(rC.isOk()).toBeTruthy(); - c = rC.Ok(); - expect(c.conn).toEqual({ - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", - resId: c.conn.resId, - }); + + for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { + describe(`${honoServer.name} - Connection`, () => { + const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); + const qOpen = buildReqOpen(sthis, { + key: { + ledger: "test", + tenant: "test", + }, + reqId: "req-open-test", + }); + const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); + for (const style of [httpStyle(sthis, port, msgP, qOpen, my), wsStyle(sthis, port, msgP, qOpen, my)]) { + describe(style.name, () => { + let server: HonoServer; + beforeAll(async () => { + const app = new Hono(); + server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).register(app, port); }); - afterEach(async () => { - await c.close(); + afterAll(async () => { + await server.close(); + }); + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/ECONNREFUSED/); + }); + + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/Timeout/i); }); - it("kaputt url http", async () => { - const r = await c.request( - { + describe(`connection`, () => { + let c: MsgConnection; + beforeEach(async () => { + const rC = await style.ok.open(); + expect(rC.isOk()).toBeTruthy(); + c = rC.Ok(); + expect(c.conn).toEqual({ + key: { + ledger: "test", + tenant: "test", + }, + reqId: "req-open-test", + resId: c.conn.resId, + }); + }); + afterEach(async () => { + await c.close(); + }); + + it("kaputt url http", async () => { + const r = await c.request( + { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + { waitFor: () => true } + ); + if (!MsgIsError(r)) { + assert.fail("expected MsgError"); + return; + } + expect(r).toEqual({ + message: "unexpected message", tid: "test", - type: "kaputt", + type: "error", version: "FP-MSG-1.0", - }, - { waitFor: () => true } - ); - if (!MsgIsError(r)) { - assert.fail("expected MsgError"); - return; - } - expect(r).toEqual({ - message: "unexpected message", - tid: "test", - type: "error", - version: "FP-MSG-1.0", + }); + }); + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}); + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); + const r = await c.request(req, { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)); + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); }); - }); - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, {}); - const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); - const r = await c.request(req, { waitFor: MsgIsResGestalt }); - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)); - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); - }); - it("openConnection", async () => { - const req = buildReqOpen(sthis, { ...c.conn }); - const r = await c.request(req, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)); - } - expect(r).toEqual({ - conn: { ...c.conn, resId: r.conn?.resId }, - tid: req.tid, - type: "resOpen", - version: "FP-MSG-1.0", + it("openConnection", async () => { + const req = buildReqOpen(sthis, { ...c.conn }); + const r = await c.request(req, { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)); + } + expect(r).toEqual({ + conn: { ...c.conn, resId: r.conn?.resId }, + tid: req.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); }); }); - }); - it("open", async () => { - const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); - expect(rC.isOk()).toBeTruthy(); - const c = rC.Ok(); - expect(c.conn).toEqual({ - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", - resId: c.conn.resId, - }); - expect(c).toBeInstanceOf(style.cInstance); - expect(c.exchangedGestalt).toEqual({ - my, - remote: style.remoteGestalt, - }); - await c.close(); - }); - describe(`${honoServer.name} - Msgs`, () => { - let conn: MsgConnection; - beforeAll(async () => { + it("open", async () => { const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); expect(rC.isOk()).toBeTruthy(); - conn = rC.Ok(); - }); - afterAll(async () => { - await conn.close(); - }); - it("Open", async () => { - const res = await conn.request(qOpen, { waitFor: MsgIsResOpen }); - expect(MsgIsResOpen(res)).toBeTruthy(); - expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn?.resId }); - }); - - function sup() { - return { - path: "test/me", - key: "key-test", - } satisfies ReqSignedUrlParam; - } - describe("Data", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetData(sthis, sp, conn.conn), { waitFor: MsgIsResGetData }); - if (MsgIsResGetData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetData", JSON.stringify(res)); - } - }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutData(sthis, sp, conn.conn), { waitFor: MsgIsResPutData }); - if (MsgIsResPutData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutData", JSON.stringify(res)); - } + const c = rC.Ok(); + expect(c.conn).toEqual({ + key: { + ledger: "test", + tenant: "test", + }, + reqId: "req-open-test", + resId: c.conn.resId, }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelData(sthis, sp, conn.conn), { waitFor: MsgIsResDelData }); - if (MsgIsResDelData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelData", JSON.stringify(res)); - } + expect(c).toBeInstanceOf(style.cInstance); + expect(c.exchangedGestalt).toEqual({ + my, + remote: style.remoteGestalt, }); + await c.close(); }); - // describe("Meta", async () => { - // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); - // // expect(MsgIsError(res)).toBeTruthy(); - // }); - describe("WAL", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetWAL(sthis, sp, conn.conn), { waitFor: MsgIsResGetWAL }); - if (MsgIsResGetWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetWAL", JSON.stringify(res)); - } + describe(`${honoServer.name} - Msgs`, () => { + let conn: MsgConnection; + beforeAll(async () => { + const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); + expect(rC.isOk()).toBeTruthy(); + conn = rC.Ok(); }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutWAL(sthis, sp, conn.conn), { waitFor: MsgIsResPutWAL }); - if (MsgIsResPutWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutWAL", JSON.stringify(res)); - } + afterAll(async () => { + await conn.close(); }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelWAL(sthis, sp, conn.conn), { waitFor: MsgIsResDelWAL }); - if (MsgIsResDelWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelWAL", JSON.stringify(res)); - } + it("Open", async () => { + const res = await conn.request(qOpen, { waitFor: MsgIsResOpen }); + expect(MsgIsResOpen(res)).toBeTruthy(); + expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn?.resId }); + }); + + function sup() { + return { + path: "test/me", + key: "key-test", + } satisfies ReqSignedUrlParam; + } + describe("Data", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetData(sthis, sp, conn.conn), { waitFor: MsgIsResGetData }); + if (MsgIsResGetData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetData", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutData(sthis, sp, conn.conn), { waitFor: MsgIsResPutData }); + if (MsgIsResPutData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutData", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelData(sthis, sp, conn.conn), { waitFor: MsgIsResDelData }); + if (MsgIsResDelData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelData", JSON.stringify(res)); + } + }); + }); + // describe("Meta", async () => { + // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); + // // expect(MsgIsError(res)).toBeTruthy(); + // }); + describe("WAL", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetWAL(sthis, sp, conn.conn), { waitFor: MsgIsResGetWAL }); + if (MsgIsResGetWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetWAL", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutWAL(sthis, sp, conn.conn), { waitFor: MsgIsResPutWAL }); + if (MsgIsResPutWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutWAL", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelWAL(sthis, sp, conn.conn), { waitFor: MsgIsResDelWAL }); + if (MsgIsResDelWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); }); }); }); - }); - } - }); -} + } + }); + } +}); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index ff7c941b..b0d66a7a 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -1,23 +1,74 @@ -import { exception2Result, HttpHeader, Result, URI } from "@adviser/cement"; -import { ensureLogger, Logger, SuperThis } from "@fireproof/core"; +import { exception2Result, HttpHeader, param, ResolveOnce, Result, URI } from "@adviser/cement"; +import { Logger, SuperThis } from "@fireproof/core"; import { Context, Hono, Next } from "hono"; import { top_uint8 } from "../coerce-binary.js"; -import { MsgerParams, Gestalt, MsgIsReqOpen, buildErrorMsg, MsgBase, buildResOpen } from "./msg-types.js"; +import { Gestalt, MsgIsReqOpen, buildErrorMsg, MsgBase, EnDeCoder } from "./msg-types.js"; import { MsgDispatcher, WSConnection } from "./msg-dispatch.js"; import { WSEvents } from "hono/ws"; -import { PreSignedConnMsg } from "./pre-signed-url.js"; +import { calculatePreSignedUrl, PreSignedConnMsg } from "./pre-signed-url.js"; +export interface RunTimeParams { + readonly sthis: SuperThis; + readonly logger: Logger; + readonly ende: EnDeCoder; + readonly impl: HonoServerImpl; +} // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export type ConnMiddleware = (conn: WSConnection, c: Context, next: Next) => Promise; export interface HonoServerImpl { - start(app: Hono): Promise; - serve(app: Hono, port?: number): Promise; - close(): Promise; + gestalt(): Gestalt; + // msgP(): MsgerParams; calculatePreSignedUrl(p: PreSignedConnMsg): Promise>; upgradeWebSocket: (createEvents: (c: Context) => WSEvents | Promise) => ConnMiddleware; readonly headers: HttpHeader; } +export abstract class HonoServerBase { + + readonly _gs: Gestalt; + readonly sthis: SuperThis; + readonly logger: Logger; + constructor(sthis: SuperThis, logger: Logger, gs: Gestalt) { + this.logger = logger; + this._gs = gs; + this.sthis = sthis; + } + + gestalt(): Gestalt { + return this._gs; + } + + calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { + const rRes = this.sthis.env.gets({ + STORAGE_URL: param.REQUIRED, + ACCESS_KEY_ID: param.REQUIRED, + SECRET_ACCESS_KEY: param.REQUIRED, + REGION: "us-east-1" + }); + if (rRes.isErr()) { + return Promise.resolve(Result.Err(rRes.Err())); + } + const res = rRes.Ok(); + return calculatePreSignedUrl(p, { + storageUrl: URI.from(res.STORAGE_URL), + aws: { + accessKeyId: res.ACCESS_KEY_ID, + secretAccessKey: res.SECRET_ACCESS_KEY, + region: res.REGION, + }, + }); + } +} + +export interface HonoServerFactory { + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + inject(c: Context, fn: (rt: RunTimeParams) => Promise): Promise; + + start(app: Hono): Promise; + serve(app: Hono, port?: number): Promise; + close(): Promise; +} + export const CORS = HttpHeader.from({ // "Accept": "application/json", "Content-Type": "application/json", @@ -26,88 +77,98 @@ export const CORS = HttpHeader.from({ "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours }); +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type +// async function injectRuntime(c: Context, fn: (rt: RunTimeParams) => Promise): Promise { +// const sthis = ensureSuperThis(); +// const logger = ensureLogger(sthis, `HonoServer[${URI.from(c.req.url).pathname}]`); +// const ende = jsonEnDe(sthis) +// return fn({ sthis, logger, ende }); +// } + export class HonoServer { - readonly sthis: SuperThis; - readonly msgP: MsgerParams; - readonly gestalt: Gestalt; - readonly logger: Logger; - readonly impl: HonoServerImpl; - constructor(sthis: SuperThis, msgP: MsgerParams, gestalt: Gestalt, impl: HonoServerImpl) { - this.sthis = sthis; - this.logger = ensureLogger(sthis, "HonoServer"); - this.msgP = msgP; - this.gestalt = gestalt; - this.impl = impl; + // readonly sthis: SuperThis; + // readonly msgP: MsgerParams; + // readonly gestalt: Gestalt; + // readonly logger: Logger; + readonly factory: HonoServerFactory; + constructor(/* sthis: SuperThis, msgP: MsgerParams, gestalt: Gestalt, */ factory: HonoServerFactory) { + // this.sthis = sthis; + // this.logger = ensureLogger(sthis, "HonoServer"); + // this.msgP = msgP; + // this.gestalt = gestalt; + this.factory = factory; } - async start(app: Hono, port?: number): Promise { - await this.impl.start(app); - // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) - // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) - app.put("/fp", async (c) => { - this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); - const rMsg = await exception2Result(() => c.req.json() as Promise); - if (rMsg.isErr()) { - c.status(400); - return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rMsg.Err())); - } - const dispatcher = new MsgDispatcher(this.sthis, this.gestalt); - return dispatcher.dispatch(this.impl, rMsg.Ok(), (msg) => c.json(msg)); - }); - app.get("/ws", async (c, next) => { - this.impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); - const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); - if (rReqOpen.isErr()) { - c.status(400); - return c.json(buildErrorMsg(this.sthis, this.logger, { tid: "internal" }, rReqOpen.Err())); - } - const reqOpen = rReqOpen.Ok(); - if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { - c.status(400); - return c.json( - buildErrorMsg(this.sthis, this.sthis.logger, reqOpen, this.logger.Error().Msg("expected reqOpen").AsError()) - ); - } - return this.impl.upgradeWebSocket((_c) => { - let dp: MsgDispatcher; - return { - onOpen: (_e, ws) => { - dp = new MsgDispatcher(this.sthis, this.gestalt); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const rConn = dp.addConn(reqOpen.conn!); - if (rConn.isErr()) { - ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rConn.Err()))); - } else { - ws.send(this.msgP.ende.encode(buildResOpen(this.sthis, reqOpen, rConn.Ok().conn.resId))); - } - }, - onError: (error) => { - this.logger.Error().Err(error).Msg("WebSocket error"); - }, - onMessage: async (event, ws) => { - const rMsg = await exception2Result( - async () => this.msgP.ende.decode(await top_uint8(event.data)) as MsgBase - ); - if (rMsg.isErr()) { - ws.send(this.msgP.ende.encode(buildErrorMsg(this.sthis, this.logger, reqOpen, rMsg.Err()))); - } else { - await dp.dispatch(this.impl, rMsg.Ok(), (msg) => { - const str = this.msgP.ende.encode(msg); - ws.send(str); - }); - } - }, - onClose: () => { - dp = undefined as unknown as MsgDispatcher; - // console.log('Connection closed') - }, - }; - })(new WSConnection(reqOpen.conn), c, next); + readonly _register = new ResolveOnce(); + async register(app: Hono, port?: number): Promise { + return this._register.once(async () => { + await this.factory.start(app); + // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) + // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) + app.put("/fp", (c) => this.factory.inject(c, async ({ sthis, logger, impl }) => { + impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); + const rMsg = await exception2Result(() => c.req.json() as Promise); + if (rMsg.isErr()) { + c.status(400); + return c.json(buildErrorMsg(sthis, logger, { tid: "internal" }, rMsg.Err())); + } + const dispatcher = new MsgDispatcher(sthis, impl.gestalt()); + return dispatcher.dispatch(impl, rMsg.Ok(), (msg) => c.json(msg)); + }) + ); + app.get("/ws", (c, next) => this.factory.inject(c, async ({ sthis, logger, ende, impl }) => { + impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); + const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); + if (rReqOpen.isErr()) { + c.status(400); + return c.json(buildErrorMsg(sthis, logger, { tid: "internal" }, rReqOpen.Err())); + } + const reqOpen = rReqOpen.Ok(); + if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { + c.status(400); + return c.json(buildErrorMsg(sthis, logger, reqOpen, logger.Error().Msg("expected reqOpen").AsError())); + } + return impl.upgradeWebSocket((_c) => { + let dp: MsgDispatcher; + return { + onOpen: (_e, _ws) => { + dp = new MsgDispatcher(sthis, impl.gestalt()); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + // const rConn = dp.addConn(reqOpen.conn!); + // if (rConn.isErr()) { + // ws.send(ende.encode(buildErrorMsg(sthis, logger, reqOpen, rConn.Err()))); + // } else { + // ws.send(ende.encode(buildResOpen(sthis, reqOpen, rConn.Ok().conn.resId))); + // } + }, + onError: (error) => { + logger.Error().Err(error).Msg("WebSocket error"); + }, + onMessage: async (event, ws) => { + const rMsg = await exception2Result(async () => ende.decode(await top_uint8(event.data)) as MsgBase); + if (rMsg.isErr()) { + ws.send(ende.encode(buildErrorMsg(sthis, logger, reqOpen, rMsg.Err()))); + } else { + await dp.dispatch(impl, rMsg.Ok(), (msg) => { + const str = ende.encode(msg); + ws.send(str); + return new Response(str); + }); + } + }, + onClose: () => { + dp = undefined as unknown as MsgDispatcher; + // console.log('Connection closed') + }, + }; + })(new WSConnection(), c, next); + }) + ); + await this.factory.serve(app, port); + return this; }); - await this.impl.serve(app, port); - return this; } async close() { - const ret = await this.impl.close(); + const ret = await this.factory.close(); return ret; } } diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index dbbd2adc..775e8232 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -2,58 +2,47 @@ import { HttpHeader, Logger, Result, URI, exception2Result } from "@adviser/ceme import { SuperThis, ensureLogger } from "@fireproof/core"; import { MsgBase, - MsgIsResOpen, - ReqOpen, - ResOpen, buildErrorMsg, - MsgerParams, - Connection, - UpdateReqRes, WithErrorMsg, RequestOpts, + ReqResId, } from "./msg-types.js"; -import { ExchangedGestalt, MsgConnection, OnMsgFn, selectRandom, timeout, UnReg } from "./msger.js"; +import { ExchangedGestalt, MsgConnection, MsgerParamsWithEnDe, OnMsgFn, selectRandom, timeout, UnReg } from "./msger.js"; export class HttpConnection implements MsgConnection { readonly sthis: SuperThis; readonly logger: Logger; - readonly msgParam: MsgerParams; + readonly msgP: MsgerParamsWithEnDe; readonly exchangedGestalt: ExchangedGestalt; readonly baseURIs: URI[]; - readonly _qsOpen: Partial>; - - get conn(): Connection { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this._qsOpen.res!.conn; - } + reqResId?: ReqResId readonly #onMsg = new Map(); constructor( sthis: SuperThis, - reqOpen: ReqOpen | undefined, uris: URI[], - msgP: MsgerParams, + msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt ) { this.sthis = sthis; this.logger = ensureLogger(sthis, "HttpConnection"); - this.msgParam = msgP; + // this.msgParam = msgP; this.baseURIs = uris; - this._qsOpen = { req: reqOpen }; this.exchangedGestalt = exGestalt; + this.msgP = msgP; } async start(): Promise> { - if (this._qsOpen.req) { - const sOpen = await this.request(this._qsOpen.req, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(sOpen)) { - return Result.Err(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); - } - this._qsOpen.res = sOpen; - } + // if (this._qsOpen.req) { + // const sOpen = await this.request(this._qsOpen.req, { waitFor: MsgIsResOpen }); + // if (!MsgIsResOpen(sOpen)) { + // return Result.Err(this.logger.Error().Any("Err", sOpen).Msg("unexpected response").AsError()); + // } + // this._qsOpen.res = sOpen; + // } return Result.Ok(undefined); } @@ -75,9 +64,10 @@ export class HttpConnection implements MsgConnection { async request(req: Q, _opts: RequestOpts): Promise> { const headers = HttpHeader.from(); - headers.Set("Content-Type", this.msgParam.mime); - headers.Set("Accept", this.msgParam.mime); - const rReqBody = exception2Result(() => this.msgParam.ende.encode(req)); + headers.Set("Content-Type", this.msgP.mime); + headers.Set("Accept", this.msgP.mime); + + const rReqBody = exception2Result(() => this.msgP.ende.encode(req)); if (rReqBody.isErr()) { return this.toMsg( buildErrorMsg( @@ -93,7 +83,7 @@ export class HttpConnection implements MsgConnection { this.logger.Debug().Url(url).Any("body", req).Msg("request"); const rRes = await exception2Result(() => timeout( - this.msgParam.timeout, + this.msgP.timeout, fetch(url.toString(), { method: "PUT", headers: headers.AsHeaderInit(), @@ -126,7 +116,7 @@ export class HttpConnection implements MsgConnection { ); } const data = new Uint8Array(await res.arrayBuffer()); - const ret = await exception2Result(async () => this.msgParam.ende.decode(data) as S); + const ret = await exception2Result(async () => this.msgP.ende.decode(data) as S); if (ret.isErr()) { return this.toMsg( buildErrorMsg( diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts index 5fdf60c6..732da471 100644 --- a/src/cloud/msg-dispatch.ts +++ b/src/cloud/msg-dispatch.ts @@ -8,7 +8,10 @@ import { MsgIsReqOpen, buildErrorMsg, buildResOpen, - Connection, + WithErrorMsg, + MsgWithConn, + MsgIsWithReqResId, + ResOpen, } from "./msg-types.js"; import { MsgIsReqGetData, @@ -39,11 +42,8 @@ export interface WSPair { } export class WSConnection { - readonly conn: Connection; wspair?: WSPair; - constructor(conn: Connection) { - this.conn = conn; - } + attachWSPair(wsp: WSPair) { if (!this.wspair) { this.wspair = wsp; @@ -53,13 +53,26 @@ export class WSConnection { } } +type Promisable = T | Promise; + + +function WithValidConn(msg: T, rri?: ResOpen): msg is MsgWithConn { + return MsgIsWithReqResId(msg) && + !!rri && + rri.conn.resId === msg.conn.resId && + rri.conn.reqId === msg.conn.reqId; +} + export class MsgDispatcher { readonly sthis: SuperThis; readonly logger: Logger; - wsConn?: WSConnection; + // wsConn?: WSConnection; + myOpen?: ResOpen; readonly gestalt: Gestalt; readonly id: string; + readonly conns = new Map(); + constructor(sthis: SuperThis, gestalt: Gestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "Dispatcher"); @@ -67,18 +80,34 @@ export class MsgDispatcher { this.id = sthis.nextId().str; } - addConn(aConn: Connection): Result { - if (!this.wsConn) { - this.wsConn = new WSConnection({ ...aConn, resId: this.sthis.nextId().str }); - return Result.Ok(this.wsConn); + addConn(msg: MsgBase): Result { + if (!MsgIsReqOpen(msg)) { + return this.logger.Error().Msg("msg missing reqId").ResultError(); } - if (aConn.reqId === this.wsConn.conn.reqId) { - return Result.Ok(this.wsConn); + if (this.myOpen) { + return this.logger.Error().Msg("myConn set").ResultError(); } - return this.logger.Error().Msg(`unexpected reqId: ${aConn.reqId}!==${this.wsConn.conn.reqId}`).ResultError(); + this.myOpen = buildResOpen(this.sthis, msg, this.sthis.nextId(12).str); + return Result.Ok(this.myOpen); } - async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => void) { + async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => Promisable): Promise { + const validateConn = async ( + msg: T, + fn: (msg: MsgWithConn) => Promisable> + ): Promise => { + if (!MsgIsWithReqResId({ ...msg, conn: this.myOpen?.conn })) { + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("dispatch missing connection"))); + } + if (!MsgIsWithReqResId(msg)) { + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("req missing connection"))); + } + if (WithValidConn(msg, this.myOpen)) { + const r = await fn(msg); + return Promise.resolve(send(r)); + } + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("non open connection"))); + }; switch (true) { case MsgIsReqGestalt(msg): return send(buildResGestalt(msg, this.gestalt)); @@ -87,30 +116,30 @@ export class MsgDispatcher { return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); } /* DDoS protection */ - const rConn = this.addConn(msg.conn); + const rConn = this.addConn(msg); if (rConn.isErr()) { return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); } return send(buildResOpen(this.sthis, msg, rConn.Ok().conn.resId)); } case MsgIsReqGetData(msg): { - return send(await buildResGetData(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResGetData(this.sthis, this.logger, msg, ctx)); } case MsgIsReqPutData(msg): { - return send(await buildResPutData(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResPutData(this.sthis, this.logger, msg, ctx)); } case MsgIsReqDelData(msg): { - return send(await buildResDelData(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResDelData(this.sthis, this.logger, msg, ctx)); } case MsgIsReqGetWAL(msg): { - return send(await buildResGetWAL(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResGetWAL(this.sthis, this.logger, msg, ctx)); } case MsgIsReqPutWAL(msg): { - return send(await buildResPutWAL(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResPutWAL(this.sthis, this.logger, msg, ctx)); } case MsgIsReqDelWAL(msg): { - return send(await buildResDelWAL(this.sthis, this.logger, msg, ctx)); + return validateConn(msg, (msg) => buildResDelWAL(this.sthis, this.logger, msg, ctx)); } default: diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index 18195a60..e4d29ae9 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -53,12 +53,15 @@ export function keyTenantLedger(t: TenantLedger): string { return `${t.tenant}:${t.ledger}`; } -export interface Connection { - readonly key: TenantLedger; +export interface ReqResId { readonly reqId: string; readonly resId: string; } +export interface Connection extends ReqResId{ + readonly key: TenantLedger; +} + export interface Connected { readonly conn: Connection; } @@ -71,6 +74,8 @@ export interface MsgBase { readonly conn?: Connection; } +export type MsgWithConn = T & { readonly conn: Connection }; + export interface ErrorMsg extends MsgBase { readonly type: "error"; readonly message: string; @@ -167,7 +172,6 @@ export interface Gestalt { } export interface MsgerParams { - readonly ende: EnDeCoder; readonly mime: string; readonly auth?: AuthType; readonly hasPersistent?: boolean; @@ -314,11 +318,17 @@ export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { return msg.type === "reqOpen" && !!msg.conn && !!msg.conn.reqId; } + export interface ResOpen extends MsgBase { readonly type: "resOpen"; readonly conn: Connection; } +export function MsgIsWithReqResId(msg: T): msg is MsgWithConn { + const mwc = (msg as MsgWithConn).conn; + return !!(mwc as ReqResId).reqId && !!(mwc as ReqResId).resId +} + export function buildResOpen(sthis: NextId, req: ReqOpen, resStreamId?: string): ResOpen { if (!(req.conn && req.conn.reqId)) { throw new Error("req.conn.reqId is required"); diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 54fc0884..1b3c17e0 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -1,7 +1,6 @@ import { BuildURI, CoerceURI, Result, runtimeFn, URI } from "@adviser/cement"; import { buildReqGestalt, - Connection, defaultGestalt, EnDeCoder, Gestalt, @@ -10,6 +9,7 @@ import { MsgIsResGestalt, ReqGestalt, ReqOpen, + ReqResId, RequestOpts, ResGestalt, WithErrorMsg, @@ -51,7 +51,7 @@ export interface MsgConnection { // readonly ws: WebSocket; // readonly params: ConnectionKey; // qsOpen: ReqRes; - conn: Connection; + reqResId?: ReqResId; readonly exchangedGestalt: ExchangedGestalt; request(req: Q, opts: RequestOpts): Promise>; start(): Promise>; @@ -59,21 +59,23 @@ export interface MsgConnection { onMsg(msg: OnMsgFn): UnReg; } -function jsonEnDe(sthis: SuperThis) { +export function jsonEnDe(sthis: SuperThis): EnDeCoder { return { encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)), decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)), - } satisfies EnDeCoder; + } } -export function defaultMsgParams(sthis: SuperThis, igs: Partial): MsgerParams { +export type MsgerParamsWithEnDe = MsgerParams & { readonly ende: EnDeCoder }; + +export function defaultMsgParams(sthis: SuperThis, igs: Partial): MsgerParamsWithEnDe { return { - ende: jsonEnDe(sthis), mime: "application/json", + ende: jsonEnDe(sthis), timeout: 3000, protocolCapabilities: ["reqRes", "stream"], ...igs, - } satisfies MsgerParams; + } satisfies MsgerParamsWithEnDe; } export interface OpenParams { @@ -97,25 +99,25 @@ export async function applyStart(prC: Promise>): Promise> { - return Result.Ok(new HttpConnection(sthis, reqOpen, urls, msgP, exGestalt)); + return Result.Ok(new HttpConnection(sthis, urls, msgP, exGestalt)); } static async openWS( sthis: SuperThis, - qOpen: ReqOpen, + // qOpen: ReqOpen, url: URI, - msgP: MsgerParams, + msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt ): Promise> { let ws: WebSocket; - const { encode } = jsonEnDe(sthis); + // const { encode } = jsonEnDe(sthis); url = url .build() - .setParam("reqOpen", sthis.txt.decode(encode(qOpen))) + // .setParam("reqOpen", sthis.txt.decode(encode(qOpen))) .URI(); if (runtimeFn().isNodeIsh) { const { WebSocket } = await import("ws"); @@ -126,10 +128,7 @@ export class Msger { return Result.Ok( new WSConnection( sthis, - { - reqOpen: qOpen, - ws, - }, + ws, msgP, exGestalt ) @@ -139,10 +138,10 @@ export class Msger { sthis: SuperThis, curl: CoerceURI, qOpen: ReqOpen, - imsgP: Partial = {} + imsgP: Partial = {} ): Promise> { // initial exchange with JSON encoding - const jsGI = defaultMsgParams(sthis, { ...imsgP, ende: jsonEnDe(sthis) }); + const jsGI = defaultMsgParams(sthis, { ...imsgP, mime: "application/json", ende: jsonEnDe(sthis) }); const url = URI.from(curl); const gs = defaultGestalt(defaultMsgParams(sthis, imsgP), { id: "FP-Universal-Client" }); /* diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index e90969d2..53c8742a 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -1,9 +1,10 @@ import { UpgradeWebSocket, WSEvents } from "hono/ws"; -import { ConnMiddleware, CORS, HonoServerImpl } from "./hono-server.js"; -import { HttpHeader, Result, URI } from "@adviser/cement"; +import { ConnMiddleware, CORS, HonoServerBase, HonoServerFactory, RunTimeParams } from "./hono-server.js"; +import { HttpHeader, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; -import { calculatePreSignedUrl, PreSignedConnMsg } from "./pre-signed-url.js"; -import { Env } from "./backend/env.js"; +import { ensureLogger, SuperThis } from "@fireproof/core"; +import { defaultMsgParams, jsonEnDe } from "./msger.js"; +import { defaultGestalt, Gestalt, MsgerParams } from "./msg-types.js"; interface ServerType { close(fn: () => void): void; @@ -11,35 +12,44 @@ interface ServerType { type serveFn = (options: unknown, listeningListener?: ((info: unknown) => void) | undefined) => ServerType; -export class NodeHonoServer implements HonoServerImpl { +export interface NodeHonoFactoryParams { + readonly msgP?: MsgerParams; + readonly gs?: Gestalt; +} + +export class NodeHonoFactory implements HonoServerFactory { _upgradeWebSocket!: UpgradeWebSocket; _injectWebSocket!: (t: unknown) => void; _serve!: serveFn; _server!: ServerType; + // _env!: Env; - readonly headers: HttpHeader; - readonly env: Env; - constructor(env: Env, headers?: HttpHeader) { - this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); - this.env = env; + readonly sthis: SuperThis; + readonly params: NodeHonoFactoryParams; + constructor(sthis: SuperThis, params: NodeHonoFactoryParams = {}) { + this.sthis = sthis; + this.params = params; } - calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { - return calculatePreSignedUrl(p, { - storageUrl: URI.from(this.env.STORAGE_URL), - aws: { - accessKeyId: this.env.ACCESS_KEY_ID, - secretAccessKey: this.env.SECRET_ACCESS_KEY, - region: this.env.REGION, - }, + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + inject(c: Context, fn: (rt: RunTimeParams) => Promise): Promise { + // this._env = c.env; + // const sthis = ensureSuperThis(); + const sthis = this.sthis; + const logger = ensureLogger(sthis, `NodeHono[${URI.from(c.req.url).pathname}]`); + const ende = jsonEnDe(sthis); + + const fpProtocol = sthis.env.get("FP_PROTOCOL"); + const msgP = this.params.msgP || defaultMsgParams(sthis, { + hasPersistent: true, + protocolCapabilities: fpProtocol ? (fpProtocol === "ws" ? ["stream"] : ["reqRes"]) : ["reqRes", "stream"], + }); + const gs = this.params.gs || defaultGestalt(msgP, { + id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - } - upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { - return async (_conn, c, next) => { - // conn.attachWSPair({ client: c.req, server: c.res }); - return this._upgradeWebSocket(createEvents)(c, next); - }; + // this.sthis.env. + return fn({ sthis, logger, ende, impl: new NodeHonoServer(sthis, this, gs) }); } async start(app: Hono): Promise { @@ -64,3 +74,20 @@ export class NodeHonoServer implements HonoServerImpl { // return new Promise((res) => this._server.close(() => res())); } } + +export class NodeHonoServer extends HonoServerBase { + readonly headers: HttpHeader; + readonly _upgradeWebSocket: UpgradeWebSocket; + constructor(sthis: SuperThis, factory: NodeHonoFactory, gs: Gestalt, headers?: HttpHeader) { + super(sthis, sthis.logger, gs); + this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + this._upgradeWebSocket = factory._upgradeWebSocket; + } + + upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { + return async (_conn, c, next) => { + // conn.attachWSPair({ client: c.req, server: c.res }); + return this._upgradeWebSocket(createEvents)(c, next); + }; + } +} diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts index 801df87d..fdc3c7de 100644 --- a/src/cloud/test-helper.ts +++ b/src/cloud/test-helper.ts @@ -3,14 +3,16 @@ import { SuperThis } from "@fireproof/core"; import { $, fs } from "zx"; import { HttpConnection } from "./http-connection.js"; import { MsgerParams, ReqOpen, Gestalt, defaultGestalt } from "./msg-types.js"; -import { defaultMsgParams, applyStart, Msger } from "./msger.js"; +import { defaultMsgParams, applyStart, Msger, MsgerParamsWithEnDe } from "./msger.js"; import { WSConnection } from "./ws-connection.js"; import * as toml from "smol-toml"; import { Env } from "./backend/env.js"; import { HonoServer } from "./hono-server.js"; -import { NodeHonoServer } from "./node-hono-server.js"; +import { NodeHonoFactory } from "./node-hono-server.js"; +import { CFHonoFactory } from "./backend/cf-hono-server.js"; +import { R } from "vitest/dist/chunks/environment.LoooBwUu.js"; -export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { +export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, qOpen: ReqOpen, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["reqRes"] }), { id: "HTTP-server", }); @@ -69,7 +71,7 @@ export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOp }; } -export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParams, qOpen: ReqOpen, my: Gestalt) { +export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, qOpen: ReqOpen, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["stream"] }), { id: "WS-server", }); @@ -144,7 +146,9 @@ export function NodeHonoServerFactory() { return { name: "NodeHonoServer", factory: async (sthis: SuperThis, msgP: MsgerParams, remoteGestalt: Gestalt, _port: number) => { - return new HonoServer(sthis, msgP, remoteGestalt, new NodeHonoServer((await resolveToml()).env)); + const { env } = await resolveToml(); + sthis.env.sets(env as unknown as Record); + return new HonoServer(new NodeHonoFactory(sthis, { msgP, gs: remoteGestalt })) }, }; } @@ -153,15 +157,7 @@ export function CFHonoServerFactory() { name: "CFHonoServer", factory: async (_sthis: SuperThis, _msgP: MsgerParams, remoteGestalt: Gestalt, port: number) => { if (process.env.FP_WRANGLER_PORT) { - const hs = { - start: async () => { - return hs; - }, - close: async () => { - /* */ - }, - } as unknown as HonoServer; - return hs; + return new HonoServer(new CFHonoFactory()); } const { tomlFile } = await resolveToml(); $.verbose = !!process.env.FP_DEBUG; @@ -187,15 +183,9 @@ export function CFHonoServerFactory() { console.error("!!", chunk.toString()); }); await waitReady.asPromise(); - const hs = { - start: async () => { - return hs; - }, - close: async () => { + return new HonoServer(new CFHonoFactory(() => { if (pid) process.kill(pid); - }, - } as unknown as HonoServer; - return hs; + })) }, }; } diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index 36b1b616..bb1340b8 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -7,48 +7,41 @@ import { ReqOpen, ResOpen, MsgIsResOpen, - MsgerParams, WaitForTid, Connection, WithErrorMsg, RequestOpts, + ReqResId, } from "./msg-types.js"; -import { ExchangedGestalt, MsgConnection, OnMsgFn, UnReg } from "./msger.js"; +import { ExchangedGestalt, MsgConnection, MsgerParamsWithEnDe, OnMsgFn, UnReg } from "./msger.js"; export interface WSReqOpen { readonly reqOpen: ReqOpen; readonly ws: WebSocket; // this WS is opened with a specific URL-Param } -interface WSQSOpen extends WSReqOpen { - resOpen?: ResOpen; -} - export class WSConnection implements MsgConnection { readonly sthis: SuperThis; readonly logger: Logger; - readonly msgP: MsgerParams; + readonly msgP: MsgerParamsWithEnDe; readonly exchangedGestalt: ExchangedGestalt; + readonly ws: WebSocket; // readonly baseURI: URI; - readonly wqs: WSQSOpen; readonly #onMsg = new Map(); readonly #onClose = new Map(); readonly waitForTid = new Map(); - opened = false; - get conn(): Connection { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.wqs.resOpen!.conn!; - } + opened = false; - constructor(sthis: SuperThis, wsq: WSReqOpen, msgP: MsgerParams, exGestalt: ExchangedGestalt) { + constructor(sthis: SuperThis, ws: WebSocket, msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "WSConnection"); this.msgP = msgP; this.exchangedGestalt = exGestalt; - this.wqs = { ...wsq }; + this.ws = ws; + // this.wqs = { ...wsq }; } async start(): Promise> { From 952c0020a0b27db3a554e0262ed18f79dc2d4491 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Tue, 7 Jan 2025 10:54:00 +0100 Subject: [PATCH 77/83] WIP --- package.json | 2 +- pnpm-lock.yaml | 2 +- src/cloud/backend/cf-hono-server.ts | 13 +- src/cloud/client/cloud-gateway.test.ts | 10 +- src/cloud/client/gateway.ts | 100 +++--- src/cloud/connection.test.ts | 410 +++++++++++----------- src/cloud/hono-server.ts | 56 ++- src/cloud/http-connection.ts | 37 +- src/cloud/meta-merger/meta-merger.test.ts | 49 ++- src/cloud/meta-merger/meta-merger.ts | 16 +- src/cloud/msg-dispatch.ts | 96 +++-- src/cloud/msg-raw-connection-base.ts | 31 ++ src/cloud/msg-type-meta.ts | 136 +++---- src/cloud/msg-types-data.ts | 38 +- src/cloud/msg-types-wal.ts | 63 +++- src/cloud/msg-types.ts | 106 ++++-- src/cloud/msger.ts | 121 +++++-- src/cloud/node-hono-server.ts | 40 ++- src/cloud/pre-signed-url.ts | 29 +- src/cloud/test-helper.ts | 62 ++-- src/cloud/ws-connection.ts | 66 ++-- 21 files changed, 833 insertions(+), 650 deletions(-) create mode 100644 src/cloud/msg-raw-connection-base.ts diff --git a/package.json b/package.json index 9790b835..e41e5d02 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "dependencies": { "@adviser/cement": "^0.3.5", "@aws-sdk/client-s3": "^3.717.0", - "@cloudflare/vitest-pool-workers": "^0.5.30", + "@cloudflare/vitest-pool-workers": "^0.5.34", "@cloudflare/workers-types": "^4.20241127.0", "@fireproof/core": "^0.19.121", "@fireproof/vendor": "^1.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36e47dc6..b13d8a47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: specifier: ^3.717.0 version: 3.717.0 '@cloudflare/vitest-pool-workers': - specifier: ^0.5.30 + specifier: ^0.5.34 version: 0.5.34(@cloudflare/workers-types@4.20241205.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2)) '@cloudflare/workers-types': specifier: ^4.20241127.0 diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index b1886240..03831ddc 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -30,7 +30,11 @@ import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; export class CFHonoFactory implements HonoServerFactory { readonly _onClose: () => void; - constructor(onClose: () => void = () => { /* */ }) { + constructor( + onClose: () => void = () => { + /* */ + } + ) { this._onClose = onClose; } // eslint-disable-next-line @typescript-eslint/no-invalid-void-type @@ -53,7 +57,7 @@ export class CFHonoFactory implements HonoServerFactory { }); const ret = fn({ sthis, logger, ende, impl: new CFHonoServer(sthis, logger, ende, gs) }); - return ret // .then((v) => sthis.logger.Flush().then(() => v)) + return ret; // .then((v) => sthis.logger.Flush().then(() => v)) } async start(_app: Hono): Promise { @@ -65,7 +69,7 @@ export class CFHonoFactory implements HonoServerFactory { return {} as T; } async close(): Promise { - this._onClose() + this._onClose(); return; } } @@ -78,7 +82,7 @@ export class CFHonoServer extends HonoServerBase { // readonly env: Env; // readonly wsConnections = new Map() constructor(sthis: SuperThis, logger: Logger, ende: EnDeCoder, gs: Gestalt, headers?: HttpHeader) { - super(sthis, logger, gs) + super(sthis, logger, gs); this.headers = HttpHeader.from(headers).Merge(CORS); this.ende = ende; // this.env = env; @@ -89,7 +93,6 @@ export class CFHonoServer extends HonoServerBase { // const stub = env.FP_META_GROUPS.get(id); // } - upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { // if (!this._upgradeWebSocket) { // throw new Error("upgradeWebSocket not implemented"); diff --git a/src/cloud/client/cloud-gateway.test.ts b/src/cloud/client/cloud-gateway.test.ts index 26df9a00..589f6a2f 100644 --- a/src/cloud/client/cloud-gateway.test.ts +++ b/src/cloud/client/cloud-gateway.test.ts @@ -1,6 +1,6 @@ import { Hono } from "hono"; import { HonoServer } from "../hono-server.js"; -import { buildReqOpen, defaultGestalt } from "../msg-types.js"; +import { defaultGestalt } from "../msg-types.js"; import { NodeHonoServerFactory, CFHonoServerFactory, wsStyle } from "../test-helper.js"; import { bs, ensureSuperThis, NotFoundError } from "@fireproof/core"; import { defaultMsgParams } from "../msger.js"; @@ -12,14 +12,8 @@ const msgP = defaultMsgParams(sthis, { hasPersistent: true }); const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); describe.each([NodeHonoServerFactory(), CFHonoServerFactory()])("$name - Gateway", ({ factory }) => { - const qOpen = buildReqOpen(sthis, { - key: { - ledger: "test", - tenant: "test", - }, - }); const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); - const style = wsStyle(sthis, port, msgP, qOpen, my); + const style = wsStyle(sthis, port, msgP, my); let server: HonoServer; let gw: bs.Gateway; diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index ad80affc..f56c70c3 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -4,26 +4,24 @@ import { bs, ensureLogger, Logger, NotFoundError, rt, SuperThis } from "@firepro import { buildErrorMsg, buildReqOpen, - Connection, FPStoreTypes, HttpMethods, - keyTenantLedger, MsgBase, MsgIsError, ReqSignedUrl, - TenantLedger, - WithErrorMsg, + MsgWithError, + ResSignedUrl, } from "../msg-types.js"; import { to_uint8 } from "../../coerce-binary.js"; -import { MsgConnection, Msger } from "../msger.js"; +import { MsgConnected, Msger } from "../msger.js"; import { MsgIsResGetData, MsgIsResPutData, ResDelData, ResGetData, ResPutData } from "../msg-types-data.js"; const VERSION = "v0.1-fp-cloud"; export interface StoreTypeGateway { - get(uri: URI, conn: Promise>): Promise>; - put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; - delete(uri: URI, conn: Promise>): Promise>; + get(uri: URI, conn: Promise>): Promise>; + put(uri: URI, body: Uint8Array, conn: Promise>): Promise>; + delete(uri: URI, conn: Promise>): Promise>; } abstract class BaseGateway { @@ -34,8 +32,8 @@ abstract class BaseGateway { this.logger = ensureLogger(sthis, module); } - abstract getConn(uri: URI, conn: MsgConnection): Promise>; - async get(uri: URI, prConn: Promise>): Promise> { + abstract getConn(uri: URI, conn: MsgConnected): Promise>; + async get(uri: URI, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in getConn").ResultError(); @@ -45,8 +43,8 @@ abstract class BaseGateway { return this.getConn(uri, conn); } - abstract putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise>; - async put(uri: URI, body: Uint8Array, prConn: Promise>): Promise> { + abstract putConn(uri: URI, body: Uint8Array, conn: MsgConnected): Promise>; + async put(uri: URI, body: Uint8Array, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); @@ -56,8 +54,8 @@ abstract class BaseGateway { return this.putConn(uri, body, conn); } - abstract delConn(uri: URI, conn: MsgConnection): Promise>; - async delete(uri: URI, prConn: Promise>): Promise> { + abstract delConn(uri: URI, conn: MsgConnected): Promise>; + async delete(uri: URI, prConn: Promise>): Promise> { const rConn = await prConn; if (rConn.isErr()) { return this.logger.Error().Err(rConn).Msg("Error in putConn").ResultError(); @@ -79,18 +77,20 @@ abstract class BaseGateway { // return Result.Ok(buildReqSignedUrl(this.sthis, type, sig, conn)) // } - async getResSignedUrl( + async getResSignedUrl( type: string, method: HttpMethods, store: FPStoreTypes, waitForFn: (msg: MsgBase) => boolean, uri: URI, - conn: MsgConnection - ): Promise> { + conn: MsgConnected + ): Promise> { const rParams = uri.getParamsResult({ key: key.REQUIRED, store: key.REQUIRED, path: key.OPTIONAL, + tenant: key.REQUIRED, + name: key.REQUIRED, index: key.OPTIONAL, }); if (rParams.isErr()) { @@ -103,7 +103,12 @@ abstract class BaseGateway { const rsu = { tid: this.sthis.nextId().str, type, - conn: conn.conn, + // conn: conn.conn, + tenant: { + tenant: params.tenant, + ledger: params.name, + }, + // tenant: conn.tenant, params: { method, store, @@ -172,7 +177,7 @@ class DataGateway extends BaseGateway implements StoreTypeGateway { constructor(sthis: SuperThis) { super(sthis, "DataGateway"); } - async getConn(uri: URI, conn: MsgConnection): Promise> { + async getConn(uri: URI, conn: MsgConnected): Promise> { // type: string, method: HttpMethods, store: FPStoreTypes, waitForFn: const rResSignedUrl = await this.getResSignedUrl( "reqGetData", @@ -188,7 +193,7 @@ class DataGateway extends BaseGateway implements StoreTypeGateway { const { signedUrl: downloadUrl } = rResSignedUrl; return this.getObject(uri, downloadUrl); } - async putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise> { + async putConn(uri: URI, body: Uint8Array, conn: MsgConnected): Promise> { const rResSignedUrl = await this.getResSignedUrl( "reqPutData", "PUT", @@ -203,7 +208,7 @@ class DataGateway extends BaseGateway implements StoreTypeGateway { const { signedUrl: uploadUrl } = rResSignedUrl; return this.putObject(uri, uploadUrl, body); } - async delConn(uri: URI, conn: MsgConnection): Promise> { + async delConn(uri: URI, conn: MsgConnected): Promise> { const rResSignedUrl = await this.getResSignedUrl( "reqDelData", "DELETE", @@ -226,7 +231,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async getConn(uri: URI, conn: MsgConnection): Promise> { + async getConn(uri: URI, conn: MsgConnected): Promise> { // const rkey = uri.getParamResult("key"); // if (rkey.isErr()) { // return Result.Err(rkey.Err()); @@ -254,7 +259,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { return Result.Ok(new Uint8Array()); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async putConn(uri: URI, body: Uint8Array, conn: MsgConnection): Promise> { + async putConn(uri: URI, body: Uint8Array, conn: MsgConnected): Promise> { // const bodyRes = Result.Ok(body); // await bs.addCryptoKeyToGatewayMetaPayload(uri, this.sthis, body); // if (bodyRes.isErr()) { // return this.logger.Error().Err(bodyRes).Msg("Error in addCryptoKeyToGatewayMetaPayload").ResultError(); @@ -277,7 +282,7 @@ class MetaGateway extends BaseGateway implements StoreTypeGateway { return Result.Ok(undefined); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - async delConn(uri: URI, conn: MsgConnection): Promise> { + async delConn(uri: URI, conn: MsgConnected): Promise> { // const rsu = this.prepareReqSignedUrl(uri, "DELETE", conn.key); // if (rsu.isErr()) { // return Result.Err(rsu.Err()); @@ -362,7 +367,7 @@ function getStoreTypeGateway(sthis: SuperThis, uri: URI): StoreTypeGateway { } } -const keyedConnections = new KeyedResolvOnce(); +// const keyedConnections = new KeyedResolvOnce(); interface Subscription { readonly sid: string; readonly uri: string; // optimization @@ -437,44 +442,41 @@ export class FireproofCloudGateway implements bs.Gateway { } // fireproof://localhost:1999/?name=test-public-api&protocol=ws&store=meta - async getCloudConnection(uri: URI): Promise> { + async getCloudConnection(uri: URI): Promise> { const rParams = uri.getParamsResult({ name: key.REQUIRED, protocol: "https", store: key.REQUIRED, storekey: key.OPTIONAL, - tenant: key.OPTIONAL, + tenant: key.REQUIRED, }); if (rParams.isErr()) { return this.logger.Error().Url(uri).Err(rParams).Msg("getCloudConnection:err").ResultError(); } const params = rParams.Ok(); - let tenant: string; - if (params.tenant) { - tenant = params.tenant; - } else { - if (!params.storekey) { - return this.logger.Error().Url(uri).Msg("no tendant or storekey given").ResultError(); - } - const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); - const kb = await rt.kb.getKeyBag(this.sthis); - const rfingerprint = await kb.getNamedKey(dataKey); - if (rfingerprint.isErr()) { - return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); - } - tenant = rfingerprint.Ok().fingerPrint; - } - const qOpen = buildReqOpen(this.sthis, { - key: { - tenant: tenant, - ledger: params.name, - } satisfies TenantLedger, - }); + // let tenant: string; + // if (params.tenant) { + // tenant = params.tenant; + // } else { + // if (!params.storekey) { + // return this.logger.Error().Url(uri).Msg("no tendant or storekey given").ResultError(); + // } + // const dataKey = params.storekey.replace(/:(meta|wal)@$/, `:data@`); + // const kb = await rt.kb.getKeyBag(this.sthis); + // const rfingerprint = await kb.getNamedKey(dataKey); + // if (rfingerprint.isErr()) { + // return this.logger.Error().Err(rfingerprint).Msg("Error in getNamedKey").ResultError(); + // } + // tenant = rfingerprint.Ok().fingerPrint; + // } + const qOpen = buildReqOpen(this.sthis, {}); + let cUrl = uri.build().protocol(params.protocol).cleanParams().URI(); if (cUrl.pathname === "/") { cUrl = cUrl.build().pathname("/fp").URI(); } - return keyedConnections.get(keyTenantLedger(qOpen.conn.key)).once(async () => Msger.open(this.sthis, cUrl, qOpen)); + return Msger.connect(this.sthis, cUrl, qOpen); + // keyedConnections.get(keyTenantLedger(qOpen.conn.key)).once(async () => Msger.open(this.sthis, cUrl, qOpen)); } // private notifySubscribers(data: Uint8Array, callbacks: ((msg: Uint8Array) => void)[] = []): void { diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index b230c817..c90bd8a8 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -8,6 +8,8 @@ import { MsgIsResOpen, defaultGestalt, ReqSignedUrlParam, + GwCtx, + ResSignedUrl, } from "./msg-types.js"; import { MsgIsResGetData, @@ -25,13 +27,13 @@ import { MsgIsResPutWAL, MsgIsResDelWAL, } from "./msg-types-wal.js"; -import { applyStart, defaultMsgParams, MsgConnection, Msger } from "./msger.js"; +import { applyStart, defaultMsgParams, MsgConnected, Msger } from "./msger.js"; import { HonoServer } from "./hono-server.js"; import { Hono } from "hono"; -import { calculatePreSignedUrl, PreSignedMsg } from "./pre-signed-url.js"; +import { calculatePreSignedUrl } from "./pre-signed-url.js"; import { CFHonoServerFactory, httpStyle, NodeHonoServerFactory, resolveToml, wsStyle } from "./test-helper.js"; -async function refURL(sp: PreSignedMsg) { +async function refURL(sp: ResSignedUrl) { const { env } = await resolveToml(); return ( await calculatePreSignedUrl(sp, { @@ -42,7 +44,7 @@ async function refURL(sp: PreSignedMsg) { region: env.REGION, }, test: { - // amzDate?: string; + amzDate: URI.from(sp.signedUrl).getParam("X-Amz-Date"), }, }) ) @@ -56,218 +58,220 @@ describe("Connection", () => { beforeAll(async () => { sthis.env.sets((await resolveToml()).env as unknown as Record); - }) + }); + describe.each([[NodeHonoServerFactory(), CFHonoServerFactory()]])("$name - Connection", (honoServer) => { + const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); + const qOpen = buildReqOpen(sthis, { reqId: "req-open-test" }); + const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); + describe.each([httpStyle(sthis, port, msgP, my), wsStyle(sthis, port, msgP, my)])("$name", (style) => { + let server: HonoServer; + beforeAll(async () => { + const app = new Hono(); + server = await honoServer + .factory(sthis, msgP, style.remoteGestalt, port) + .then((srv) => srv.register(app, port)); + }); + afterAll(async () => { + // console.log("closing server"); + await server.close(); + }); + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/ECONNREFUSED/); + }); - for (const honoServer of [NodeHonoServerFactory(), CFHonoServerFactory()]) { - describe(`${honoServer.name} - Connection`, () => { - const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); - const qOpen = buildReqOpen(sthis, { - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/Timeout/i); }); - const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); - for (const style of [httpStyle(sthis, port, msgP, qOpen, my), wsStyle(sthis, port, msgP, qOpen, my)]) { - describe(style.name, () => { - let server: HonoServer; - beforeAll(async () => { - const app = new Hono(); - server = await (await honoServer.factory(sthis, msgP, style.remoteGestalt, port)).register(app, port); - }); - afterAll(async () => { - await server.close(); - }); - it(`conn refused`, async () => { - const rC = await applyStart(style.connRefused.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/ECONNREFUSED/); + + describe(`connection`, () => { + let c: MsgConnected; + beforeEach(async () => { + const rC = await style.ok.open().then((r) => MsgConnected.connect(r, { reqId: "req-open-testx" })); + expect(rC.isOk()).toBeTruthy(); + c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testx", + resId: c.conn.resId, }); + }); + afterEach(async () => { + await c.close(); + }); - it(`timeout`, async () => { - const rC = await applyStart(style.timeout.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/Timeout/i); + it("kaputt url http", async () => { + const r = await c.raw.request( + { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + { waitFor: () => true } + ); + if (!MsgIsError(r)) { + assert.fail("expected MsgError"); + return; + } + expect(r).toEqual({ + message: "unexpected message", + tid: "test", + type: "error", + version: "FP-MSG-1.0", + src: { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, }); + }); + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}); + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); + const r = await c.raw.request(req, { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)); + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); + }); - describe(`connection`, () => { - let c: MsgConnection; - beforeEach(async () => { - const rC = await style.ok.open(); - expect(rC.isOk()).toBeTruthy(); - c = rC.Ok(); - expect(c.conn).toEqual({ - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", - resId: c.conn.resId, - }); - }); - afterEach(async () => { - await c.close(); - }); + it("openConnection", async () => { + const req = buildReqOpen(sthis, { ...c.conn }); + const r = await c.raw.request(req, { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)); + } + expect(r).toEqual({ + conn: { ...c.conn, resId: r.conn?.resId }, + tid: req.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); + }); + }); - it("kaputt url http", async () => { - const r = await c.request( - { - tid: "test", - type: "kaputt", - version: "FP-MSG-1.0", - }, - { waitFor: () => true } - ); - if (!MsgIsError(r)) { - assert.fail("expected MsgError"); - return; - } - expect(r).toEqual({ - message: "unexpected message", - tid: "test", - type: "error", - version: "FP-MSG-1.0", - }); - }); - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, {}); - const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); - const r = await c.request(req, { waitFor: MsgIsResGestalt }); - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)); - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); - }); + it("open", async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, { + reqId: "req-open-testy", + }); + expect(rC.isOk()).toBeTruthy(); + const c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testy", + resId: c.conn.resId, + }); + expect(c.raw).toBeInstanceOf(style.cInstance); + expect(c.exchangedGestalt).toEqual({ + my, + remote: style.remoteGestalt, + }); + await c.close(); + }); + describe(`${honoServer.name} - Msgs`, () => { + let gwCtx: GwCtx; + let conn: MsgConnected; + beforeAll(async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, qOpen.conn); + expect(rC.isOk()).toBeTruthy(); + conn = rC.Ok(); + gwCtx = { + conn: conn.conn, + tenant: { + tenant: "Tenant", + ledger: "Ledger", + }, + }; + }); + afterAll(async () => { + await conn.close(); + }); + it("Open", async () => { + const res = await conn.raw.request(buildReqOpen(sthis, conn.conn), { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(res)) { + assert.fail("expected MsgResOpen", JSON.stringify(res)); + } + expect(MsgIsResOpen(res)).toBeTruthy(); + expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn.resId }); + }); - it("openConnection", async () => { - const req = buildReqOpen(sthis, { ...c.conn }); - const r = await c.request(req, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)); - } - expect(r).toEqual({ - conn: { ...c.conn, resId: r.conn?.resId }, - tid: req.tid, - type: "resOpen", - version: "FP-MSG-1.0", - }); - }); + function sup() { + return { + path: "test/me", + key: "key-test", + } satisfies ReqSignedUrlParam; + } + describe("Data", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetData(sthis, sp, gwCtx), { waitFor: MsgIsResGetData }); + if (MsgIsResGetData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetData", JSON.stringify(res)); + } }); - - it("open", async () => { - const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); - expect(rC.isOk()).toBeTruthy(); - const c = rC.Ok(); - expect(c.conn).toEqual({ - key: { - ledger: "test", - tenant: "test", - }, - reqId: "req-open-test", - resId: c.conn.resId, - }); - expect(c).toBeInstanceOf(style.cInstance); - expect(c.exchangedGestalt).toEqual({ - my, - remote: style.remoteGestalt, - }); - await c.close(); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutData(sthis, sp, gwCtx), { waitFor: MsgIsResPutData }); + if (MsgIsResPutData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutData", JSON.stringify(res)); + } }); - describe(`${honoServer.name} - Msgs`, () => { - let conn: MsgConnection; - beforeAll(async () => { - const rC = await Msger.open(sthis, URI.from(`http://localhost:${port}/fp`), qOpen, msgP); - expect(rC.isOk()).toBeTruthy(); - conn = rC.Ok(); - }); - afterAll(async () => { - await conn.close(); - }); - it("Open", async () => { - const res = await conn.request(qOpen, { waitFor: MsgIsResOpen }); - expect(MsgIsResOpen(res)).toBeTruthy(); - expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn?.resId }); - }); - - function sup() { - return { - path: "test/me", - key: "key-test", - } satisfies ReqSignedUrlParam; + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelData(sthis, sp, gwCtx), { waitFor: MsgIsResDelData }); + if (MsgIsResDelData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelData", JSON.stringify(res)); } - describe("Data", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetData(sthis, sp, conn.conn), { waitFor: MsgIsResGetData }); - if (MsgIsResGetData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetData", JSON.stringify(res)); - } - }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutData(sthis, sp, conn.conn), { waitFor: MsgIsResPutData }); - if (MsgIsResPutData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutData", JSON.stringify(res)); - } - }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelData(sthis, sp, conn.conn), { waitFor: MsgIsResDelData }); - if (MsgIsResDelData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelData", JSON.stringify(res)); - } - }); - }); - // describe("Meta", async () => { - // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); - // // expect(MsgIsError(res)).toBeTruthy(); - // }); - describe("WAL", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetWAL(sthis, sp, conn.conn), { waitFor: MsgIsResGetWAL }); - if (MsgIsResGetWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetWAL", JSON.stringify(res)); - } - }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutWAL(sthis, sp, conn.conn), { waitFor: MsgIsResPutWAL }); - if (MsgIsResPutWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutWAL", JSON.stringify(res)); - } - }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelWAL(sthis, sp, conn.conn), { waitFor: MsgIsResDelWAL }); - if (MsgIsResDelWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelWAL", JSON.stringify(res)); - } - }); - }); }); }); - } + // describe("Meta", async () => { + // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); + // // expect(MsgIsError(res)).toBeTruthy(); + // }); + describe("WAL", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetWAL(sthis, sp, gwCtx), { waitFor: MsgIsResGetWAL }); + if (MsgIsResGetWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetWAL", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutWAL(sthis, sp, gwCtx), { waitFor: MsgIsResPutWAL }); + if (MsgIsResPutWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutWAL", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelWAL(sthis, sp, gwCtx), { waitFor: MsgIsResDelWAL }); + if (MsgIsResDelWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); + }); + }); }); - } + }); }); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index b0d66a7a..8f34521c 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -2,10 +2,10 @@ import { exception2Result, HttpHeader, param, ResolveOnce, Result, URI } from "@ import { Logger, SuperThis } from "@fireproof/core"; import { Context, Hono, Next } from "hono"; import { top_uint8 } from "../coerce-binary.js"; -import { Gestalt, MsgIsReqOpen, buildErrorMsg, MsgBase, EnDeCoder } from "./msg-types.js"; +import { Gestalt, buildErrorMsg, MsgBase, EnDeCoder, ErrorMsg } from "./msg-types.js"; import { MsgDispatcher, WSConnection } from "./msg-dispatch.js"; import { WSEvents } from "hono/ws"; -import { calculatePreSignedUrl, PreSignedConnMsg } from "./pre-signed-url.js"; +import { calculatePreSignedUrl, PreSignedMsg } from "./pre-signed-url.js"; export interface RunTimeParams { readonly sthis: SuperThis; @@ -18,13 +18,12 @@ export type ConnMiddleware = (conn: WSConnection, c: Context, next: Next) => Pro export interface HonoServerImpl { gestalt(): Gestalt; // msgP(): MsgerParams; - calculatePreSignedUrl(p: PreSignedConnMsg): Promise>; + calculatePreSignedUrl(p: PreSignedMsg): Promise>; upgradeWebSocket: (createEvents: (c: Context) => WSEvents | Promise) => ConnMiddleware; readonly headers: HttpHeader; } export abstract class HonoServerBase { - readonly _gs: Gestalt; readonly sthis: SuperThis; readonly logger: Logger; @@ -38,12 +37,12 @@ export abstract class HonoServerBase { return this._gs; } - calculatePreSignedUrl(p: PreSignedConnMsg): Promise> { + calculatePreSignedUrl(p: PreSignedMsg): Promise> { const rRes = this.sthis.env.gets({ STORAGE_URL: param.REQUIRED, ACCESS_KEY_ID: param.REQUIRED, SECRET_ACCESS_KEY: param.REQUIRED, - REGION: "us-east-1" + REGION: "us-east-1", }); if (rRes.isErr()) { return Promise.resolve(Result.Err(rRes.Err())); @@ -77,14 +76,6 @@ export const CORS = HttpHeader.from({ "Access-Control-Max-Age": "86400", // Cache pre-flight response for 24 hours }); -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -// async function injectRuntime(c: Context, fn: (rt: RunTimeParams) => Promise): Promise { -// const sthis = ensureSuperThis(); -// const logger = ensureLogger(sthis, `HonoServer[${URI.from(c.req.url).pathname}]`); -// const ende = jsonEnDe(sthis) -// return fn({ sthis, logger, ende }); -// } - export class HonoServer { // readonly sthis: SuperThis; // readonly msgP: MsgerParams; @@ -104,7 +95,8 @@ export class HonoServer { await this.factory.start(app); // app.put('/gestalt', async (c) => c.json(buildResGestalt(await c.req.json(), defaultGestaltItem({ id: "server", hasPersistent: true }).gestalt))) // app.put('/error', async (c) => c.json(buildErrorMsg(sthis, sthis.logger, await c.req.json(), new Error("test error")))) - app.put("/fp", (c) => this.factory.inject(c, async ({ sthis, logger, impl }) => { + app.put("/fp", (c) => + this.factory.inject(c, async ({ sthis, logger, impl }) => { impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); const rMsg = await exception2Result(() => c.req.json() as Promise); if (rMsg.isErr()) { @@ -115,30 +107,13 @@ export class HonoServer { return dispatcher.dispatch(impl, rMsg.Ok(), (msg) => c.json(msg)); }) ); - app.get("/ws", (c, next) => this.factory.inject(c, async ({ sthis, logger, ende, impl }) => { - impl.headers.Items().forEach(([k, v]) => c.res.headers.set(k, v[0])); - const rReqOpen = await exception2Result(() => JSON.parse(URI.from(c.req.url).getParam("reqOpen", ""))); - if (rReqOpen.isErr()) { - c.status(400); - return c.json(buildErrorMsg(sthis, logger, { tid: "internal" }, rReqOpen.Err())); - } - const reqOpen = rReqOpen.Ok(); - if (!MsgIsReqOpen(reqOpen) || !reqOpen.conn) { - c.status(400); - return c.json(buildErrorMsg(sthis, logger, reqOpen, logger.Error().Msg("expected reqOpen").AsError())); - } + app.get("/ws", (c, next) => + this.factory.inject(c, async ({ sthis, logger, ende, impl }) => { return impl.upgradeWebSocket((_c) => { let dp: MsgDispatcher; return { onOpen: (_e, _ws) => { dp = new MsgDispatcher(sthis, impl.gestalt()); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - // const rConn = dp.addConn(reqOpen.conn!); - // if (rConn.isErr()) { - // ws.send(ende.encode(buildErrorMsg(sthis, logger, reqOpen, rConn.Err()))); - // } else { - // ws.send(ende.encode(buildResOpen(sthis, reqOpen, rConn.Ok().conn.resId))); - // } }, onError: (error) => { logger.Error().Err(error).Msg("WebSocket error"); @@ -146,7 +121,18 @@ export class HonoServer { onMessage: async (event, ws) => { const rMsg = await exception2Result(async () => ende.decode(await top_uint8(event.data)) as MsgBase); if (rMsg.isErr()) { - ws.send(ende.encode(buildErrorMsg(sthis, logger, reqOpen, rMsg.Err()))); + ws.send( + ende.encode( + buildErrorMsg( + sthis, + logger, + { + message: event.data, + } as ErrorMsg, + rMsg.Err() + ) + ) + ); } else { await dp.dispatch(impl, rMsg.Ok(), (msg) => { const str = ende.encode(msg); diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index 775e8232..3af4d1d8 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -1,37 +1,30 @@ import { HttpHeader, Logger, Result, URI, exception2Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; +import { MsgBase, buildErrorMsg, MsgWithError, RequestOpts } from "./msg-types.js"; import { - MsgBase, - buildErrorMsg, - WithErrorMsg, - RequestOpts, - ReqResId, -} from "./msg-types.js"; -import { ExchangedGestalt, MsgConnection, MsgerParamsWithEnDe, OnMsgFn, selectRandom, timeout, UnReg } from "./msger.js"; + ExchangedGestalt, + MsgerParamsWithEnDe, + MsgRawConnection, + OnMsgFn, + selectRandom, + timeout, + UnReg, +} from "./msger.js"; +import { MsgRawConnectionBase } from "./msg-raw-connection-base.js"; -export class HttpConnection implements MsgConnection { - readonly sthis: SuperThis; +export class HttpConnection extends MsgRawConnectionBase implements MsgRawConnection { readonly logger: Logger; readonly msgP: MsgerParamsWithEnDe; - readonly exchangedGestalt: ExchangedGestalt; readonly baseURIs: URI[]; - reqResId?: ReqResId - readonly #onMsg = new Map(); - constructor( - sthis: SuperThis, - uris: URI[], - msgP: MsgerParamsWithEnDe, - exGestalt: ExchangedGestalt - ) { - this.sthis = sthis; + constructor(sthis: SuperThis, uris: URI[], msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt) { + super(sthis, exGestalt); this.logger = ensureLogger(sthis, "HttpConnection"); // this.msgParam = msgP; this.baseURIs = uris; - this.exchangedGestalt = exGestalt; this.msgP = msgP; } @@ -51,7 +44,7 @@ export class HttpConnection implements MsgConnection { return Result.Ok(undefined); } - toMsg(msg: WithErrorMsg): WithErrorMsg { + toMsg(msg: MsgWithError): MsgWithError { this.#onMsg.forEach((fn) => fn(msg)); return msg; } @@ -62,7 +55,7 @@ export class HttpConnection implements MsgConnection { return () => this.#onMsg.delete(key); } - async request(req: Q, _opts: RequestOpts): Promise> { + async request(req: Q, _opts: RequestOpts): Promise> { const headers = HttpHeader.from(); headers.Set("Content-Type", this.msgP.mime); headers.Set("Accept", this.msgP.mime); diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index ed69c47a..e06bf956 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -1,7 +1,6 @@ // import type { Database } from "better-sqlite3"; -import { MetaMerger } from "./meta-merger.js"; +import { Connection, MetaMerger } from "./meta-merger.js"; import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; -import { Connection } from "../msg-types.js"; import { runtimeFn } from "@adviser/cement"; import { SQLDatabase } from "./abstract-sql.js"; import type { Env } from "../backend/env.js"; @@ -10,6 +9,23 @@ function sortCRDTEntries(rows: CRDTEntry[]) { return rows.sort((a, b) => a.cid.localeCompare(b.cid)); } +interface MetaConnection { + readonly metas: CRDTEntry[]; + readonly connection: Connection; +} + +function toCRDTEntries(rows: MetaConnection[]) { + return rows.reduce((r, i) => [...r, ...i.metas], [] as CRDTEntry[]); +} + +// function filterConnection(ref: MetaConnection[], connection: Connection) { +// return toCRDTEntries(ref.filter((r) => +// (r.connection.tenant.tenant === connection.tenant.tenant && +// r.connection.tenant.ledger === connection.tenant.ledger && +// r.connection.conn.reqId === connection.conn.reqId && +// r.connection.conn.resId === connection.conn.resId))) +// } + describe("MetaMerger", () => { let db: SQLDatabase; const sthis = ensureSuperThis(); @@ -31,12 +47,14 @@ describe("MetaMerger", () => { let connection: Connection; beforeEach(() => { connection = { - key: { + tenant: { tenant: `tenant${sthis.timeOrderedNextId().str}`, ledger: "ledger", }, - reqId: "reqId", - resId: "resId", + conn: { + reqId: "reqId", + resId: "resId", + }, } satisfies Connection; }); @@ -82,7 +100,10 @@ describe("MetaMerger", () => { }) .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); await mm.addMeta({ - connection: { ...connection, reqId: sthis.timeOrderedNextId().str } satisfies Connection, + connection: { + ...connection, + conn: { ...connection.conn, reqId: sthis.timeOrderedNextId().str }, + } satisfies Connection, metas, now: new Date(), }); @@ -94,8 +115,8 @@ describe("MetaMerger", () => { it("metaToSend to sink", async () => { const connections = Array(2) .fill(connection) - .map((c) => ({ ...c, reqId: sthis.timeOrderedNextId().str })); - const ref: CRDTEntry[] = []; + .map((c) => ({ ...c, conn: { ...c.conn, reqId: sthis.timeOrderedNextId().str } })); + const ref: MetaConnection[] = []; for (const connection of connections) { const metas = Array(2) .fill({ @@ -104,7 +125,7 @@ describe("MetaMerger", () => { data: "MomRkYXRho", }) .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); - ref.push(...metas); + ref.push({ metas, connection }); await mm.addMeta({ connection, metas, @@ -114,14 +135,18 @@ describe("MetaMerger", () => { // wrote 10 connections with 3 metas each for (const connection of connections) { const rows = await mm.metaToSend(connection); - expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(ref)); + expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(toCRDTEntries(ref))); + const rowsEmpty = await mm.metaToSend(connection); + expect(sortCRDTEntries(rowsEmpty)).toEqual([]); } const newConnections = Array(2) .fill(connection) - .map((c) => ({ ...c, reqId: sthis.timeOrderedNextId().str })); + .map((c) => ({ ...c, conn: { ...c.conn, reqId: sthis.timeOrderedNextId().str } })); for (const connection of newConnections) { const rows = await mm.metaToSend(connection); - expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(ref)); + expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(toCRDTEntries(ref))); + const rowsEmpty = await mm.metaToSend(connection); + expect(sortCRDTEntries(rowsEmpty)).toEqual([]); } }); }); diff --git a/src/cloud/meta-merger/meta-merger.ts b/src/cloud/meta-merger/meta-merger.ts index f312a67f..fa79726a 100644 --- a/src/cloud/meta-merger/meta-merger.ts +++ b/src/cloud/meta-merger/meta-merger.ts @@ -9,12 +9,17 @@ class MetaMerger { */ import { CRDTEntry, SuperThis } from "@fireproof/core"; -import { Connection } from "../msg-types.js"; import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; import { MetaSendSql } from "./meta-send.js"; import { TenantLedgerSql } from "./tenant-ledger.js"; import { TenantSql } from "./tenant.js"; import { SQLDatabase } from "./abstract-sql.js"; +import { QSId, TenantLedger } from "../msg-types.js"; + +export interface Connection { + readonly tenant: TenantLedger; + readonly conn: QSId; +} export interface MetaMerge { readonly connection: Connection; @@ -31,10 +36,8 @@ export interface ByConnection { function toByConnection(connection: Connection): ByConnection { return { - tenant: connection.key.tenant, - ledger: connection.key.ledger, - reqId: connection.reqId, - resId: connection.resId, + ...connection.conn, + ...connection.tenant, }; } @@ -80,8 +83,7 @@ export class MetaMerger { await this.sql.metaSend.deleteByConnection(connCIDs); await this.sql.metaByTenantLedger.deleteByConnection(connCIDs); await this.sql.tenantLedger.ensure({ - tenant: mm.connection.key.tenant, - ledger: mm.connection.key.ledger, + ...mm.connection.tenant, createdAt: now, }); for (const meta of mm.metas) { diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts index 732da471..2e2196da 100644 --- a/src/cloud/msg-dispatch.ts +++ b/src/cloud/msg-dispatch.ts @@ -1,17 +1,17 @@ -import { Logger, Result } from "@adviser/cement"; +import { Logger } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; import { Gestalt, MsgBase, MsgIsReqGestalt, buildResGestalt, - MsgIsReqOpen, buildErrorMsg, buildResOpen, - WithErrorMsg, + MsgWithError, + MsgIsWithConn, MsgWithConn, - MsgIsWithReqResId, - ResOpen, + QSId, + MsgIsReqOpen, } from "./msg-types.js"; import { MsgIsReqGetData, @@ -55,19 +55,48 @@ export class WSConnection { type Promisable = T | Promise; +// function WithValidConn(msg: T, rri?: ResOpen): msg is MsgWithConn { +// return MsgIsWithConn(msg) && !!rri && rri.conn.resId === msg.conn.resId && rri.conn.reqId === msg.conn.reqId; +// } -function WithValidConn(msg: T, rri?: ResOpen): msg is MsgWithConn { - return MsgIsWithReqResId(msg) && - !!rri && - rri.conn.resId === msg.conn.resId && - rri.conn.reqId === msg.conn.reqId; +interface ConnItem { + conn: QSId; + touched: Date; } +class ConnectionManager { + readonly conns = new Map(); + readonly maxItems: number; + + constructor(maxItems?: number) { + this.maxItems = maxItems || 100; + } + + addConn(conn: QSId): QSId { + if (this.conns.size >= this.maxItems) { + const oldest = Array.from(this.conns.values()); + const oneHourAgo = new Date(new Date().getTime() - 60 * 60 * 1000).getTime(); + oldest + .filter((item) => item.touched.getTime() < oneHourAgo) + .forEach((item) => this.conns.delete(item.conn.resId)); + } + this.conns.set(`${conn.reqId}:${conn.resId}`, { conn, touched: new Date() }); + return conn; + } + + isConnected(msg: MsgBase): msg is MsgWithConn { + if (!MsgIsWithConn(msg)) { + return false; + } + return this.conns.has(`${msg.conn.reqId}:${msg.conn.resId}`); + } +} +const connManager = new ConnectionManager(); + export class MsgDispatcher { readonly sthis: SuperThis; readonly logger: Logger; // wsConn?: WSConnection; - myOpen?: ResOpen; readonly gestalt: Gestalt; readonly id: string; @@ -80,33 +109,25 @@ export class MsgDispatcher { this.id = sthis.nextId().str; } - addConn(msg: MsgBase): Result { - if (!MsgIsReqOpen(msg)) { - return this.logger.Error().Msg("msg missing reqId").ResultError(); - } - if (this.myOpen) { - return this.logger.Error().Msg("myConn set").ResultError(); - } - this.myOpen = buildResOpen(this.sthis, msg, this.sthis.nextId(12).str); - return Result.Ok(this.myOpen); - } + // addConn(msg: MsgBase): Result { + // if (!MsgIsReqOpenWithConn(msg)) { + // return this.logger.Error().Msg("msg missing reqId").ResultError(); + // } + // return Result.Ok(connManager.addConn(msg.conn)); + // } async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => Promisable): Promise { const validateConn = async ( msg: T, - fn: (msg: MsgWithConn) => Promisable> + fn: (msg: MsgWithConn) => Promisable> ): Promise => { - if (!MsgIsWithReqResId({ ...msg, conn: this.myOpen?.conn })) { - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("dispatch missing connection"))); - } - if (!MsgIsWithReqResId(msg)) { - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("req missing connection"))); - } - if (WithValidConn(msg, this.myOpen)) { - const r = await fn(msg); - return Promise.resolve(send(r)); + if (!connManager.isConnected(msg)) { + return send(buildErrorMsg(this.sthis, this.logger, { ...msg }, new Error("dispatch missing connection"))); + // return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("non open connection"))); } - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("non open connection"))); + // if (WithValidConn(msg, this.myOpen)) { + const r = await fn(msg); + return Promise.resolve(send(r)); }; switch (true) { case MsgIsReqGestalt(msg): @@ -115,12 +136,13 @@ export class MsgDispatcher { if (!msg.conn) { return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); } - /* DDoS protection */ - const rConn = this.addConn(msg); - if (rConn.isErr()) { - return send(buildErrorMsg(this.sthis, this.logger, msg, rConn.Err())); + if (connManager.isConnected(msg)) { + return send(buildResOpen(this.sthis, msg, msg.conn.resId)); } - return send(buildResOpen(this.sthis, msg, rConn.Ok().conn.resId)); + const resId = this.sthis.nextId(12).str; + const resOpen = buildResOpen(this.sthis, msg, resId); + connManager.addConn(resOpen.conn); + return send(resOpen); } case MsgIsReqGetData(msg): { return validateConn(msg, (msg) => buildResGetData(this.sthis, this.logger, msg, ctx)); diff --git a/src/cloud/msg-raw-connection-base.ts b/src/cloud/msg-raw-connection-base.ts new file mode 100644 index 00000000..66bf75e1 --- /dev/null +++ b/src/cloud/msg-raw-connection-base.ts @@ -0,0 +1,31 @@ +import { Logger } from "@adviser/cement"; +import { SuperThis } from "@fireproof/core"; +import { MsgBase, ErrorMsg, buildErrorMsg } from "./msg-types.js"; +import { ExchangedGestalt, OnErrorFn, UnReg } from "./msger.js"; + +export class MsgRawConnectionBase { + readonly sthis: SuperThis; + readonly exchangedGestalt: ExchangedGestalt; + + constructor(sthis: SuperThis, exGestalt: ExchangedGestalt) { + this.sthis = sthis; + this.exchangedGestalt = exGestalt; + } + + readonly onErrorFns = new Map(); + onError(fn: OnErrorFn): UnReg { + const key = this.sthis.nextId().str; + this.onErrorFns.set(key, fn); + return () => this.onErrorFns.delete(key); + } + + buildErrorMsg(logger: Logger, msg: Partial, err: Error): ErrorMsg { + // const logLine = this.sthis.logger.Error().Err(err).Any("msg", msg); + const rmsg = Array.from(this.onErrorFns.values()).reduce((msg, fn) => { + return fn(msg, err); + }, msg); + const emsg = buildErrorMsg(this.sthis, logger, rmsg, err); + logger.Error().Err(err).Any("msg", rmsg).Msg("connection error"); + return emsg; + } +} diff --git a/src/cloud/msg-type-meta.ts b/src/cloud/msg-type-meta.ts index df758111..bf6c0a0c 100644 --- a/src/cloud/msg-type-meta.ts +++ b/src/cloud/msg-type-meta.ts @@ -1,14 +1,24 @@ import { VERSION } from "@adviser/cement"; import { CRDTEntry } from "@fireproof/core"; -import { MsgBase, Connection, NextId, ReqRes, ReqSignedUrlParam, SignedUrlParam } from "./msg-types.js"; +import { + GwCtx, + MsgBase, + MsgWithConn, + MsgWithOptionalConn, + MsgWithTenantLedger, + NextId, + ReqRes, + ReqSignedUrlParam, + SignedUrlParam, +} from "./msg-types.js"; /* Subscribe Meta */ -export interface ReqSubscribeMeta extends MsgBase { - readonly type: "reqSubscribeMeta"; - readonly subscriberId: string; - readonly conn: Connection; -} +// export interface ReqSubscribeMeta extends MsgBase { +// readonly type: "reqSubscribeMeta"; +// readonly subscriberId: string; +// readonly conn: ; +// } // export type ReqSubscribeMetaWithConnId = AddConnId; @@ -16,48 +26,47 @@ export interface ReqSubscribeMeta extends MsgBase { // return req.type === "reqSubscribeMetaWithConnId"; // } -export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { - return req.type === "reqSubscribeMeta"; -} +// export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { +// return req.type === "reqSubscribeMeta"; +// } -export function buildReqSubscribeMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { - return { - tid: sthis.nextId().str, - subscriberId, - type: "reqSubscribeMeta", - version: VERSION, - conn: ck, - }; -} +// export function buildReqSubscribeMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { +// return { +// tid: sthis.nextId().str, +// subscriberId, +// type: "reqSubscribeMeta", +// version: VERSION, +// conn: ck, +// }; +// } -export interface ResSubscribeMeta extends MsgBase { - readonly type: "resSubscribeMeta"; - readonly subscriberId: string; - readonly conn: Connection; -} +// export interface ResSubscribeMeta extends MsgBase { +// readonly type: "resSubscribeMeta"; +// readonly subscriberId: string; +// readonly conn: Connection; +// } -export function buildResSubscribeMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { - return { - tid: req.tid, - type: "resSubscribeMeta", - subscriberId: req.subscriberId, - conn: req.conn, - version: VERSION, - }; -} +// export function buildResSubscribeMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { +// return { +// tid: req.tid, +// type: "resSubscribeMeta", +// subscriberId: req.subscriberId, +// conn: req.conn, +// version: VERSION, +// }; +// } -export function MsgIsResSubscribeMeta>( - qs: T -): qs is T & ReqRes { - return qs.res.type === "resSubscribeMeta"; -} +// export function MsgIsResSubscribeMeta>( +// qs: T +// ): qs is T & ReqRes { +// return qs.res.type === "resSubscribeMeta"; +// } /* Put Meta */ -export interface ReqPutMeta extends MsgBase { +export interface ReqPutMeta extends MsgWithTenantLedger { readonly type: "reqPutMeta"; readonly params: ReqSignedUrlParam; readonly metas: CRDTEntry[]; - readonly conn: Connection; } // export type ReqPutMetaWithConnId = AddConnId; @@ -67,27 +76,24 @@ export interface ReqPutMeta extends MsgBase { // } export interface PutMetaParam { - readonly metaId: string; readonly metas: CRDTEntry[]; readonly signedPutUrl: string; } -export interface ResPutMeta extends MsgBase, PutMetaParam { +export interface ResPutMeta extends MsgWithTenantLedger, PutMetaParam { readonly type: "resPutMeta"; - readonly metas: CRDTEntry[]; - readonly conn: Connection; } export function buildReqPutMeta( sthis: NextId, - conn: Connection, signedUrlParams: ReqSignedUrlParam, - metas: CRDTEntry[] + metas: CRDTEntry[], + gwCtx: GwCtx ): ReqPutMeta { return { tid: sthis.nextId().str, type: "reqPutMeta", - conn, + ...gwCtx, version: VERSION, params: signedUrlParams, metas, @@ -98,12 +104,16 @@ export function MsgIsReqPutMeta(msg: MsgBase): msg is ReqPutMeta { return msg.type === "reqPutMeta"; } -export function buildResPutMeta(req: ReqPutMeta, metaParam: PutMetaParam): ResPutMeta { +export function buildResPutMeta( + req: MsgWithTenantLedger>, + metaParam: PutMetaParam +): ResPutMeta { return { ...metaParam, tid: req.tid, type: "resPutMeta", conn: req.conn, + tenant: req.tenant, version: VERSION, }; } @@ -123,25 +133,25 @@ export interface ConnSubId { * and might implement long polling. * It will answer with a UpdateMetaEvent. */ -export interface ReqUpdateMeta extends MsgBase, ConnSubId { - readonly type: "reqUpdateMeta"; - readonly conn: Connection; -} +// export interface ReqUpdateMeta extends MsgBase, ConnSubId { +// readonly type: "reqUpdateMeta"; +// } -export interface UpdateMetaEvent extends MsgBase, ConnSubId { +export interface UpdateMetaEvent extends MsgWithTenantLedger, ConnSubId { readonly type: "updateMeta"; - readonly conn: Connection; - readonly metaId: string; readonly metas: CRDTEntry[]; } -export function buildUpdateMetaEvent(rq: ReqRes, consub: ConnSubId): UpdateMetaEvent { +export function buildUpdateMetaEvent( + rq: ReqRes>, ResPutMeta>, + consub: ConnSubId +): UpdateMetaEvent { return { ...consub, tid: rq.res.tid, type: "updateMeta", conn: rq.res.conn, - metaId: rq.res.metaId, + tenant: rq.res.tenant, metas: rq.req.metas, version: rq.res.version, }; @@ -152,10 +162,9 @@ export function MsgIsUpdateMetaEvent(msg: MsgBase): msg is UpdateMetaEvent { } /* Get Meta */ -export interface ReqGetMeta extends MsgBase { +export interface ReqGetMeta extends MsgWithTenantLedger { readonly type: "reqGetMeta"; readonly params: ReqSignedUrlParam; - readonly conn: Connection; } // export type ReqGetMetaWithConnId = AddConnId; @@ -183,10 +192,10 @@ export interface ResGetMeta extends MsgBase, GetMetaParam { readonly params: SignedUrlParam; } -export function buildReqGetMeta(sthis: NextId, conn: Connection, signedUrlParams: ReqSignedUrlParam): ReqGetMeta { +export function buildReqGetMeta(sthis: NextId, signedUrlParams: ReqSignedUrlParam, gwCtx: GwCtx): ReqGetMeta { return { tid: sthis.nextId().str, - conn, + ...gwCtx, type: "reqGetMeta", version: VERSION, params: signedUrlParams, @@ -208,10 +217,9 @@ export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes { readonly type: "reqDelMeta"; readonly params: ReqSignedUrlParam; - readonly conn: Connection; } // export type ReqDelMetaWithConnId = AddConnId; @@ -233,10 +241,10 @@ export interface ResDelMeta extends MsgBase, DelMetaParam { readonly type: "resDelMeta"; } -export function buildReqDelMeta(sthis: NextId, conn: Connection, signedUrlParams: SignedUrlParam): ReqDelMeta { +export function buildReqDelMeta(sthis: NextId, signedUrlParams: SignedUrlParam, gwCtx: GwCtx): ReqDelMeta { return { tid: sthis.nextId().str, - conn, + ...gwCtx, type: "reqDelMeta", version: VERSION, params: signedUrlParams, diff --git a/src/cloud/msg-types-data.ts b/src/cloud/msg-types-data.ts index bdf5389a..12ceeb77 100644 --- a/src/cloud/msg-types-data.ts +++ b/src/cloud/msg-types-data.ts @@ -3,13 +3,15 @@ import { SuperThis } from "@fireproof/core"; import { ReqSignedUrl, NextId, - Connection, MsgBase, ResSignedUrl, - WithErrorMsg, + MsgWithError, buildRes, ReqSignedUrlParam, buildReqSignedUrl, + GwCtx, + MsgIsTenantLedger, + MsgWithConn, } from "./msg-types.js"; import { PreSignedMsg } from "./pre-signed-url.js"; @@ -17,8 +19,8 @@ export interface ReqGetData extends ReqSignedUrl { readonly type: "reqGetData"; } -export function buildReqGetData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetData { - return buildReqSignedUrl(sthis, "reqGetData", sup, conn); +export function buildReqGetData(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqGetData { + return buildReqSignedUrl(sthis, "reqGetData", sup, ctx); } export function MsgIsReqGetData(msg: MsgBase): msg is ReqGetData { @@ -31,7 +33,7 @@ export interface ResGetData extends ResSignedUrl { } export function MsgIsResGetData(msg: MsgBase): msg is ResGetData { - return msg.type === "resGetData"; + return msg.type === "resGetData" && MsgIsTenantLedger(msg); } export interface CalculatePreSignedUrl { @@ -41,10 +43,10 @@ export interface CalculatePreSignedUrl { export function buildResGetData( sthis: SuperThis, logger: Logger, - req: ReqGetData, + req: MsgWithConn, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("GET", "data", "resGetData", sthis, logger, req, ctx); +): Promise> { + return buildRes, ResGetData>("GET", "data", "resGetData", sthis, logger, req, ctx); } export interface ReqPutData extends ReqSignedUrl { @@ -56,8 +58,8 @@ export function MsgIsReqPutData(msg: MsgBase): msg is ReqPutData { return msg.type === "reqPutData"; } -export function buildReqPutData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutData { - return buildReqSignedUrl(sthis, "reqPutData", sup, conn); +export function buildReqPutData(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqPutData { + return buildReqSignedUrl(sthis, "reqPutData", sup, ctx); } export interface ResPutData extends ResSignedUrl { @@ -71,10 +73,10 @@ export function MsgIsResPutData(msg: MsgBase): msg is ResPutData { export function buildResPutData( sthis: SuperThis, logger: Logger, - req: ReqPutData, + req: MsgWithConn, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("PUT", "data", "resPutData", sthis, logger, req, ctx); +): Promise> { + return buildRes, ResPutData>("PUT", "data", "resPutData", sthis, logger, req, ctx); } export interface ReqDelData extends ReqSignedUrl { @@ -85,8 +87,8 @@ export function MsgIsReqDelData(msg: MsgBase): msg is ReqDelData { return msg.type === "reqDelData"; } -export function buildReqDelData(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelData { - return buildReqSignedUrl(sthis, "reqDelData", sup, conn); +export function buildReqDelData(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqDelData { + return buildReqSignedUrl(sthis, "reqDelData", sup, ctx); } export interface ResDelData extends ResSignedUrl { @@ -100,8 +102,8 @@ export function MsgIsResDelData(msg: MsgBase): msg is ResDelData { export function buildResDelData( sthis: SuperThis, logger: Logger, - req: ReqDelData, + req: MsgWithConn, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("DELETE", "data", "resDelData", sthis, logger, req, ctx); +): Promise> { + return buildRes, ResDelData>("DELETE", "data", "resDelData", sthis, logger, req, ctx); } diff --git a/src/cloud/msg-types-wal.ts b/src/cloud/msg-types-wal.ts index a5f3123c..3363cd43 100644 --- a/src/cloud/msg-types-wal.ts +++ b/src/cloud/msg-types-wal.ts @@ -2,14 +2,17 @@ import { Logger } from "@adviser/cement"; import { SuperThis } from "@fireproof/core"; import { MsgBase, - Connection, - WithErrorMsg, + MsgWithError, buildRes, NextId, ReqSignedUrl, ResSignedUrl, ReqSignedUrlParam, buildReqSignedUrl, + GwCtx, + MsgIsTenantLedger, + MsgWithTenantLedger, + MsgWithConn, } from "./msg-types.js"; import { CalculatePreSignedUrl } from "./msg-types-data.js"; @@ -21,8 +24,8 @@ export function MsgIsReqGetWAL(msg: MsgBase): msg is ReqGetWAL { return msg.type === "reqGetWAL"; } -export function buildReqGetWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqGetWAL { - return buildReqSignedUrl(sthis, "reqGetWAL", sup, conn); +export function buildReqGetWAL(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqGetWAL { + return buildReqSignedUrl(sthis, "reqGetWAL", sup, ctx); } export interface ResGetWAL extends ResSignedUrl { @@ -37,10 +40,18 @@ export function MsgIsResGetWAL(msg: MsgBase): msg is ResGetWAL { export function buildResGetWAL( sthis: SuperThis, logger: Logger, - req: ReqGetWAL, + req: MsgWithTenantLedger>, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("GET", "wal", "resGetWAL", sthis, logger, req, ctx); +): Promise> { + return buildRes>, ResGetWAL>( + "GET", + "wal", + "resGetWAL", + sthis, + logger, + req, + ctx + ); } export interface ReqPutWAL extends Omit { @@ -52,8 +63,8 @@ export function MsgIsReqPutWAL(msg: MsgBase): msg is ReqPutWAL { return msg.type === "reqPutWAL"; } -export function buildReqPutWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqPutWAL { - return buildReqSignedUrl(sthis, "reqPutWAL", sup, conn); +export function buildReqPutWAL(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqPutWAL { + return buildReqSignedUrl(sthis, "reqPutWAL", sup, ctx); } export interface ResPutWAL extends Omit { @@ -67,10 +78,18 @@ export function MsgIsResPutWAL(msg: MsgBase): msg is ResPutWAL { export function buildResPutWAL( sthis: SuperThis, logger: Logger, - req: ReqPutWAL, + req: MsgWithTenantLedger>, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("PUT", "wal", "resPutWAL", sthis, logger, req, ctx); +): Promise> { + return buildRes>, ResPutWAL>( + "PUT", + "wal", + "resPutWAL", + sthis, + logger, + req, + ctx + ); } export interface ReqDelWAL extends Omit { @@ -81,8 +100,8 @@ export function MsgIsReqDelWAL(msg: MsgBase): msg is ReqDelWAL { return msg.type === "reqDelWAL"; } -export function buildReqDelWAL(sthis: NextId, sup: ReqSignedUrlParam, conn: Connection): ReqDelWAL { - return buildReqSignedUrl(sthis, "reqDelWAL", sup, conn); +export function buildReqDelWAL(sthis: NextId, sup: ReqSignedUrlParam, ctx: GwCtx): ReqDelWAL { + return buildReqSignedUrl(sthis, "reqDelWAL", sup, ctx); } export interface ResDelWAL extends Omit { @@ -90,14 +109,22 @@ export interface ResDelWAL extends Omit { } export function MsgIsResDelWAL(msg: MsgBase): msg is ResDelWAL { - return msg.type === "resDelWAL"; + return msg.type === "resDelWAL" && MsgIsTenantLedger(msg); } export function buildResDelWAL( sthis: SuperThis, logger: Logger, - req: ReqDelWAL, + req: MsgWithTenantLedger>, ctx: CalculatePreSignedUrl -): Promise> { - return buildRes("DELETE", "wal", "resDelWAL", sthis, logger, req, ctx); +): Promise> { + return buildRes>, ResDelWAL>( + "DELETE", + "wal", + "resDelWAL", + sthis, + logger, + req, + ctx + ); } diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index e4d29ae9..b1bfc5b8 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -5,7 +5,7 @@ import { PreSignedMsg } from "./pre-signed-url.js"; export const VERSION = "FP-MSG-1.0"; -export type WithErrorMsg = T | ErrorMsg; +export type MsgWithError = T | ErrorMsg; export interface RequestOpts { readonly waitFor: (msg: MsgBase) => boolean; @@ -53,31 +53,35 @@ export function keyTenantLedger(t: TenantLedger): string { return `${t.tenant}:${t.ledger}`; } -export interface ReqResId { +export interface QSId { readonly reqId: string; readonly resId: string; } -export interface Connection extends ReqResId{ - readonly key: TenantLedger; -} +// export interface Connection extends ReqResId{ +// readonly key: TenantLedger; +// } -export interface Connected { - readonly conn: Connection; -} +// export interface Connected { +// readonly conn: Connection; +// } export interface MsgBase { readonly tid: string; readonly type: string; readonly version: string; readonly auth?: AuthType; - readonly conn?: Connection; } -export type MsgWithConn = T & { readonly conn: Connection }; +export type MsgWithConn = T & { readonly conn: QSId }; + +export type MsgWithOptionalConn = T & { readonly conn?: QSId }; + +export type MsgWithTenantLedger = T & { readonly tenant: TenantLedger }; export interface ErrorMsg extends MsgBase { readonly type: "error"; + readonly src: unknown; readonly message: string; readonly body?: string; readonly stack?: string[]; @@ -292,14 +296,19 @@ export function MsgIsResGestalt(msg: MsgBase): msg is ResGestalt { } export interface ReqOpenConnection { - readonly key: TenantLedger; + // readonly key: TenantLedger; readonly reqId?: string; + readonly resId?: string; // for double open +} + +export interface ReqOpenConn { + readonly reqId: string; readonly resId?: string; } -export interface ReqOpen extends Omit { +export interface ReqOpen extends MsgBase { readonly type: "reqOpen"; - readonly conn: Connection; + readonly conn: ReqOpenConn; } export function buildReqOpen(sthis: NextId, conn: ReqOpenConnection): ReqOpen { @@ -308,25 +317,34 @@ export function buildReqOpen(sthis: NextId, conn: ReqOpenConnection): ReqOpen { type: "reqOpen", version: VERSION, conn: { - ...(conn as Connection), + ...conn, reqId: conn.reqId || sthis.nextId().str, }, }; } -export function MsgIsReqOpen(msg: MsgBase): msg is ReqOpen { +export function MsgIsReqOpenWithConn(imsg: MsgBase): imsg is MsgWithConn { + const msg = imsg as MsgWithConn; return msg.type === "reqOpen" && !!msg.conn && !!msg.conn.reqId; } +export function MsgIsReqOpen(imsg: MsgBase): imsg is MsgWithConn { + const msg = imsg as MsgWithConn; + return msg.type === "reqOpen" && !!msg.conn && !!msg.conn.reqId; +} export interface ResOpen extends MsgBase { readonly type: "resOpen"; - readonly conn: Connection; + readonly conn: QSId; } -export function MsgIsWithReqResId(msg: T): msg is MsgWithConn { +export function MsgIsWithConn(msg: T): msg is MsgWithConn { const mwc = (msg as MsgWithConn).conn; - return !!(mwc as ReqResId).reqId && !!(mwc as ReqResId).resId + return mwc && !!(mwc as QSId).reqId && !!(mwc as QSId).resId; +} + +export function MsgIsConnected(msg: T, qsid: QSId): msg is MsgWithConn { + return MsgIsWithConn(msg) && msg.conn.reqId === qsid.reqId && msg.conn.resId === qsid.resId; } export function buildResOpen(sthis: NextId, req: ReqOpen, resStreamId?: string): ResOpen { @@ -337,8 +355,8 @@ export function buildResOpen(sthis: NextId, req: ReqOpen, resStreamId?: string): ...req, type: "resOpen", conn: { - ...(req.conn as Connection), - resId: resStreamId || sthis.nextId().str, + ...req.conn, + resId: req.conn.resId || resStreamId || sthis.nextId().str, }, }; } @@ -352,7 +370,7 @@ export interface ReqClose extends Omit { } export function MsgIsReqClose(msg: MsgBase): msg is ReqClose { - return msg.type === "reqClose"; + return msg.type === "reqClose" && MsgIsWithConn(msg); } export interface ResClose extends Omit { @@ -360,7 +378,7 @@ export interface ResClose extends Omit { } export function MsgIsResClose(msg: MsgBase): msg is ResClose { - return msg.type === "resClose"; + return msg.type === "resClose" && MsgIsWithConn(msg); } export interface SignedUrlParam { @@ -383,10 +401,10 @@ export interface UpdateReqRes { export type ReqRes = Readonly>; -export interface ReqOptRes { - readonly req: Q; - readonly res?: S; -} +// export interface ReqOptRes { +// readonly req: Q; +// readonly res?: S; +// } // /* Signed URL */ // export function buildReqSignedUrl(req: ReqSignedUrlParam): ReqSignedUrlParam { @@ -438,7 +456,7 @@ export function getStoreFromType(req: MsgBase): StoreAndType { export function buildErrorMsg( sthis: SuperThis, logger: Logger, - base: Partial, + base: Partial, error: Error, body?: string, stack?: string[] @@ -447,6 +465,7 @@ export function buildErrorMsg( stack = error.stack?.split("\n"); } const msg = { + src: base, type: "error", tid: base.tid || "internal", message: error.message, @@ -454,39 +473,49 @@ export function buildErrorMsg( body, stack, } satisfies ErrorMsg; - logger.Error().Any("ErrorMsg", msg).Msg("error"); + logger.Any("ErrorMsg", msg); return msg; } -export interface ReqSignedUrl extends MsgBase { +// export type MsgWithTenantLedger = T & { readonly tenant: TenantLedger }; + +export function MsgIsTenantLedger(msg: T): msg is MsgWithTenantLedger { + const t = (msg as MsgWithTenantLedger).tenant; + return !!t && !!t.tenant && !!t.ledger; +} + +export interface ReqSignedUrl extends MsgWithTenantLedger { // readonly type: "reqSignedUrl"; - readonly conn: Connection; readonly params: ReqSignedUrlParam; } +export interface GwCtx { + readonly conn?: QSId; + readonly tenant: TenantLedger; +} + export function buildReqSignedUrl( sthis: NextId, type: string, params: ReqSignedUrlParam, - conn: Connection + gwCtx: GwCtx ): T { return { tid: sthis.nextId().str, type, version: VERSION, - conn, + ...gwCtx, params, } as T; } -export interface ResSignedUrl extends MsgBase { +export interface ResSignedUrl extends MsgWithTenantLedger { // readonly type: "resSignedUrl"; - readonly conn: Connection; readonly params: SignedUrlParam; readonly signedUrl: string; } -export async function buildRes( +export async function buildRes>, S extends ResSignedUrl>( method: SignedUrlParam["method"], store: FPStoreTypes, type: string, @@ -494,14 +523,17 @@ export async function buildRes( logger: Logger, req: Q, ctx: CalculatePreSignedUrl -): Promise> { +): Promise> { const psm = { + type: "reqSignedUrl", + version: req.version, params: { ...req.params, method, store, }, conn: req.conn, + tenant: req.tenant, tid: req.tid, } satisfies PreSignedMsg; const rSignedUrl = await ctx.calculatePreSignedUrl(psm); @@ -513,5 +545,5 @@ export async function buildRes( params: psm.params, type, signedUrl: rSignedUrl.Ok().toString(), - } as unknown as WithErrorMsg; + } as unknown as MsgWithError; } diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 1b3c17e0..5e08876a 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -8,11 +8,16 @@ import { MsgerParams, MsgIsResGestalt, ReqGestalt, - ReqOpen, - ReqResId, RequestOpts, ResGestalt, - WithErrorMsg, + MsgWithError, + MsgWithConn, + buildReqOpen, + MsgIsConnected, + MsgIsError, + MsgIsResOpen, + MsgWithOptionalConn, + QSId, } from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; import { HttpConnection } from "./http-connection.js"; @@ -39,7 +44,7 @@ export function timeout(ms: number, promise: Promise): Promise { }); } -export type OnMsgFn = (msg: WithErrorMsg) => void; +export type OnMsgFn = (msg: MsgWithError) => void; export type UnReg = () => void; export interface ExchangedGestalt { @@ -47,23 +52,25 @@ export interface ExchangedGestalt { readonly remote: Gestalt; } -export interface MsgConnection { +export type OnErrorFn = (msg: Partial, err: Error) => Partial; + +export interface MsgRawConnection { // readonly ws: WebSocket; // readonly params: ConnectionKey; // qsOpen: ReqRes; - reqResId?: ReqResId; + readonly sthis: SuperThis; readonly exchangedGestalt: ExchangedGestalt; - request(req: Q, opts: RequestOpts): Promise>; + request(req: Q, opts: RequestOpts): Promise>; start(): Promise>; close(): Promise>; - onMsg(msg: OnMsgFn): UnReg; + onMsg(msg: OnMsgFn): UnReg; } export function jsonEnDe(sthis: SuperThis): EnDeCoder { return { encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)), decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)), - } + }; } export type MsgerParamsWithEnDe = MsgerParams & { readonly ende: EnDeCoder }; @@ -82,7 +89,7 @@ export interface OpenParams { readonly timeout: number; } -export async function applyStart(prC: Promise>): Promise> { +export async function applyStart(prC: Promise>): Promise> { const rC = await prC; if (rC.isErr()) { return rC; @@ -95,6 +102,53 @@ export async function applyStart(prC: Promise>): Promise { + static async connect( + mrc: Result | MsgRawConnection, + conn: Partial = {} + ): Promise> { + if (Result.Is(mrc)) { + if (mrc.isErr()) { + return Result.Err(mrc.Err()); + } + mrc = mrc.Ok(); + } + const res = await mrc.request(buildReqOpen(mrc.sthis, conn), { waitFor: MsgIsResOpen }); + if (MsgIsError(res) || !MsgIsResOpen(res)) { + return mrc.sthis.logger.Error().Err(res).Msg("unexpected response").ResultError(); + } + return Result.Ok(new MsgConnected(mrc, res.conn)); + } + + readonly sthis: SuperThis; + readonly conn: QSId; + readonly raw: MsgRawConnection; + readonly exchangedGestalt: ExchangedGestalt; + private constructor(raw: MsgRawConnection, conn: QSId) { + this.sthis = raw.sthis; + this.raw = raw; + this.exchangedGestalt = raw.exchangedGestalt; + this.conn = conn; + } + + request(req: Q, opts: RequestOpts): Promise> { + return this.raw.request({ ...req, conn: req.conn || this.conn }, opts); + } + start(): Promise> { + return this.raw.start(); + } + close(): Promise> { + return this.raw.close(); + } + onMsg(msgFn: OnMsgFn): UnReg { + return this.raw.onMsg((msg) => { + if (MsgIsConnected(msg, this.conn)) { + msgFn(msg); + } + }); + } +} + // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Msger { static async openHttp( @@ -103,7 +157,7 @@ export class Msger { urls: URI[], msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt - ): Promise> { + ): Promise> { return Result.Ok(new HttpConnection(sthis, urls, msgP, exGestalt)); } static async openWS( @@ -112,42 +166,32 @@ export class Msger { url: URI, msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt - ): Promise> { + ): Promise> { let ws: WebSocket; // const { encode } = jsonEnDe(sthis); - url = url - .build() - // .setParam("reqOpen", sthis.txt.decode(encode(qOpen))) - .URI(); + url = url.build().URI(); + // .setParam("reqOpen", sthis.txt.decode(encode(qOpen))) if (runtimeFn().isNodeIsh) { const { WebSocket } = await import("ws"); ws = new WebSocket(url.toString()) as unknown as WebSocket; } else { ws = new WebSocket(url.toString()); } - return Result.Ok( - new WSConnection( - sthis, - ws, - msgP, - exGestalt - ) - ); + return Result.Ok(new WSConnection(sthis, ws, msgP, exGestalt)); } static async open( sthis: SuperThis, curl: CoerceURI, - qOpen: ReqOpen, imsgP: Partial = {} - ): Promise> { + ): Promise> { // initial exchange with JSON encoding - const jsGI = defaultMsgParams(sthis, { ...imsgP, mime: "application/json", ende: jsonEnDe(sthis) }); + const jsMsgP = defaultMsgParams(sthis, { ...imsgP, mime: "application/json", ende: jsonEnDe(sthis) }); const url = URI.from(curl); const gs = defaultGestalt(defaultMsgParams(sthis, imsgP), { id: "FP-Universal-Client" }); /* * request Gestalt with Http */ - const rHC = await Msger.openHttp(sthis, undefined, [url], jsGI, { my: gs, remote: gs }); + const rHC = await Msger.openHttp(sthis, [url], jsMsgP, { my: gs, remote: gs }); if (rHC.isErr()) { return rHC; } @@ -165,7 +209,6 @@ export class Msger { return applyStart( Msger.openHttp( sthis, - qOpen, exGt.remote.httpEndpoints.map((i) => BuildURI.from(url).resolve(i).URI()), msgP, exGt @@ -173,20 +216,20 @@ export class Msger { ); } return applyStart( - Msger.openWS(sthis, qOpen, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt) + Msger.openWS(sthis, BuildURI.from(url).resolve(selectRandom(exGt.remote.wsEndpoints)).URI(), msgP, exGt) ); } + static connect( + sthis: SuperThis, + curl: CoerceURI, + imsgP: Partial = {}, + conn: Partial = {} + ): Promise> { + return Msger.open(sthis, curl, imsgP).then((srv) => MsgConnected.connect(srv, conn)); + } + private constructor() { /* */ } - - // readonly logger: Logger; - // readonly url: URI; - // readonly qs: ReqRes; - // constructor(logger: Logger, url: URI, qs: ReqRes) { - // this.logger = logger; - // this.url = url; - // this.qs = qs; - // } } diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 53c8742a..2c4dedfc 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -40,32 +40,42 @@ export class NodeHonoFactory implements HonoServerFactory { const ende = jsonEnDe(sthis); const fpProtocol = sthis.env.get("FP_PROTOCOL"); - const msgP = this.params.msgP || defaultMsgParams(sthis, { - hasPersistent: true, - protocolCapabilities: fpProtocol ? (fpProtocol === "ws" ? ["stream"] : ["reqRes"]) : ["reqRes", "stream"], - }); - const gs = this.params.gs || defaultGestalt(msgP, { - id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", - }); + const msgP = + this.params.msgP || + defaultMsgParams(sthis, { + hasPersistent: true, + protocolCapabilities: fpProtocol ? (fpProtocol === "ws" ? ["stream"] : ["reqRes"]) : ["reqRes", "stream"], + }); + const gs = + this.params.gs || + defaultGestalt(msgP, { + id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", + }); // this.sthis.env. return fn({ sthis, logger, ende, impl: new NodeHonoServer(sthis, this, gs) }); } async start(app: Hono): Promise { - const { createNodeWebSocket } = await import("@hono/node-ws"); - const { serve } = await import("@hono/node-server"); - this._serve = serve as serveFn; - const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }); - this._upgradeWebSocket = upgradeWebSocket; - this._injectWebSocket = injectWebSocket as (t: unknown) => void; + try { + const { createNodeWebSocket } = await import("@hono/node-ws"); + const { serve } = await import("@hono/node-server"); + this._serve = serve as serveFn; + const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }); + this._upgradeWebSocket = upgradeWebSocket; + this._injectWebSocket = injectWebSocket as (t: unknown) => void; + } catch (e) { + throw this.sthis.logger.Error().Err(e).Msg("Failed to start NodeHonoFactory").AsError(); + } } async serve(app: Hono, port: number): Promise { await new Promise((resolve) => { - this._server = this._serve({ fetch: app.fetch, port }, () => resolve()); + this._server = this._serve({ fetch: app.fetch, port }, () => { + this._injectWebSocket(this._server); + resolve(); + }); }); - this._injectWebSocket(this._server); } async close(): Promise { this._server.close(() => { diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts index b4bf0edc..b8deca6d 100644 --- a/src/cloud/pre-signed-url.ts +++ b/src/cloud/pre-signed-url.ts @@ -1,18 +1,17 @@ import { Result, URI } from "@adviser/cement"; import { AwsClient } from "aws4fetch"; -import { Connection, SignedUrlParam } from "./msg-types.js"; +import { MsgWithConn, MsgWithTenantLedger, SignedUrlParam } from "./msg-types.js"; -export interface PreSignedMsg { +export interface PreSignedMsg extends MsgWithTenantLedger { readonly params: SignedUrlParam; readonly tid: string; - readonly conn?: Connection; } -export interface PreSignedConnMsg { - readonly params: SignedUrlParam; - readonly tid: string; - readonly conn: Connection; -} +// export interface PreSignedConnMsg { +// readonly params: SignedUrlParam; +// readonly tid: string; +// readonly conn: QSId; +// } export interface PreSignedEnv { readonly storageUrl: URI; @@ -26,11 +25,11 @@ export interface PreSignedEnv { }; } -export async function calculatePreSignedUrl(ipsm: PreSignedMsg, env: PreSignedEnv): Promise> { - if (!ipsm.conn) { - return Result.Err(new Error("Connection is not supported")); - } - const psm = ipsm as PreSignedConnMsg; +export async function calculatePreSignedUrl(psm: PreSignedMsg, env: PreSignedEnv): Promise> { + // if (!ipsm.conn) { + // return Result.Err(new Error("Connection is not supported")); + // } + // const psm = ipsm as PreSignedConnMsg; // verify if you are not overriding let store: string = psm.params.store; @@ -54,8 +53,8 @@ export async function calculatePreSignedUrl(ipsm: PreSignedMsg, env: PreSignedEn // .protocol(vals.protocuol === "ws" ? "http:" : "https:") .setParam("X-Amz-Expires", expiresInSeconds.toString()) .setParam("tid", psm.tid) - .appendRelative(psm.conn.key.tenant) - .appendRelative(psm.conn.key.ledger) + .appendRelative(psm.tenant.tenant) + .appendRelative(psm.tenant.ledger) .appendRelative(store) .appendRelative(`${psm.params.key}${suffix}`) .URI(); diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts index fdc3c7de..b05094a5 100644 --- a/src/cloud/test-helper.ts +++ b/src/cloud/test-helper.ts @@ -1,18 +1,25 @@ -import { Future, URI } from "@adviser/cement"; +import { Future, Result, URI } from "@adviser/cement"; import { SuperThis } from "@fireproof/core"; import { $, fs } from "zx"; import { HttpConnection } from "./http-connection.js"; -import { MsgerParams, ReqOpen, Gestalt, defaultGestalt } from "./msg-types.js"; -import { defaultMsgParams, applyStart, Msger, MsgerParamsWithEnDe } from "./msger.js"; +import { + MsgerParams, + Gestalt, + defaultGestalt, + buildReqGestalt, + MsgIsResGestalt, + MsgIsError, + MsgBase, +} from "./msg-types.js"; +import { defaultMsgParams, applyStart, Msger, MsgerParamsWithEnDe, MsgRawConnection } from "./msger.js"; import { WSConnection } from "./ws-connection.js"; import * as toml from "smol-toml"; import { Env } from "./backend/env.js"; import { HonoServer } from "./hono-server.js"; import { NodeHonoFactory } from "./node-hono-server.js"; import { CFHonoFactory } from "./backend/cf-hono-server.js"; -import { R } from "vitest/dist/chunks/environment.LoooBwUu.js"; -export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, qOpen: ReqOpen, my: Gestalt) { +export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["reqRes"] }), { id: "HTTP-server", }); @@ -27,7 +34,6 @@ export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithE applyStart( Msger.openHttp( sthis, - qOpen, [URI.from(`http://localhost:${port}/fp`)], { ...msgP, @@ -40,10 +46,9 @@ export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithE }, connRefused: { url: () => URI.from(`http://127.0.0.1:${port - 1}/fp`), - open: () => - Msger.openHttp( + open: async (): Promise>> => { + const ret = await Msger.openHttp( sthis, - qOpen, [URI.from(`http://localhost:${port - 1}/fp`)], { ...msgP, @@ -51,14 +56,23 @@ export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithE timeout: 1000, }, exGt - ), + ); + if (ret.isErr()) { + return ret; + } + // should fail + const res = await ret.Ok().request(buildReqGestalt(sthis, my), { waitFor: MsgIsResGestalt }); + if (MsgIsError(res)) { + return Result.Err(res.message); + } + return ret; + }, }, timeout: { url: () => URI.from(`http://4.7.1.1:${port}/fp`), - open: () => - Msger.openHttp( + open: async (): Promise>> => { + const ret = await Msger.openHttp( sthis, - qOpen, [URI.from(`http://4.7.1.1:${port}/fp`)], { ...msgP, @@ -66,12 +80,19 @@ export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithE timeout: 500, }, exGt - ), + ); + // should fail + const res = await ret.Ok().request(buildReqGestalt(sthis, my), { waitFor: MsgIsResGestalt }); + if (MsgIsError(res)) { + return Result.Err(res.message); + } + return ret; + }, }, }; } -export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, qOpen: ReqOpen, my: Gestalt) { +export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["stream"] }), { id: "WS-server", }); @@ -86,7 +107,6 @@ export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnD applyStart( Msger.openWS( sthis, - qOpen, URI.from(`http://localhost:${port}/ws`), { ...msgP, @@ -102,7 +122,6 @@ export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnD open: () => Msger.openWS( sthis, - qOpen, URI.from(`http://localhost:${port - 1}/ws`), { ...msgP, @@ -117,7 +136,6 @@ export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnD open: () => Msger.openWS( sthis, - qOpen, URI.from(`http://4.7.1.1:${port - 1}/ws`), { ...msgP, @@ -148,7 +166,7 @@ export function NodeHonoServerFactory() { factory: async (sthis: SuperThis, msgP: MsgerParams, remoteGestalt: Gestalt, _port: number) => { const { env } = await resolveToml(); sthis.env.sets(env as unknown as Record); - return new HonoServer(new NodeHonoFactory(sthis, { msgP, gs: remoteGestalt })) + return new HonoServer(new NodeHonoFactory(sthis, { msgP, gs: remoteGestalt })); }, }; } @@ -183,9 +201,11 @@ export function CFHonoServerFactory() { console.error("!!", chunk.toString()); }); await waitReady.asPromise(); - return new HonoServer(new CFHonoFactory(() => { + return new HonoServer( + new CFHonoFactory(() => { if (pid) process.kill(pid); - })) + }) + ); }, }; } diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index bb1340b8..90d8aa72 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -1,30 +1,17 @@ import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { - MsgBase, - MsgIsError, - buildErrorMsg, - ReqOpen, - ResOpen, - MsgIsResOpen, - WaitForTid, - Connection, - WithErrorMsg, - RequestOpts, - ReqResId, -} from "./msg-types.js"; -import { ExchangedGestalt, MsgConnection, MsgerParamsWithEnDe, OnMsgFn, UnReg } from "./msger.js"; +import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, WaitForTid, MsgWithError, RequestOpts } from "./msg-types.js"; +import { ExchangedGestalt, MsgerParamsWithEnDe, MsgRawConnection, OnMsgFn, UnReg } from "./msger.js"; +import { MsgRawConnectionBase } from "./msg-raw-connection-base.js"; export interface WSReqOpen { readonly reqOpen: ReqOpen; readonly ws: WebSocket; // this WS is opened with a specific URL-Param } -export class WSConnection implements MsgConnection { - readonly sthis: SuperThis; +export class WSConnection extends MsgRawConnectionBase implements MsgRawConnection { readonly logger: Logger; readonly msgP: MsgerParamsWithEnDe; - readonly exchangedGestalt: ExchangedGestalt; readonly ws: WebSocket; // readonly baseURI: URI; @@ -35,11 +22,13 @@ export class WSConnection implements MsgConnection { opened = false; + readonly id: string; + constructor(sthis: SuperThis, ws: WebSocket, msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt) { - this.sthis = sthis; + super(sthis, exGestalt); + this.id = sthis.nextId().str; this.logger = ensureLogger(sthis, "WSConnection"); this.msgP = msgP; - this.exchangedGestalt = exGestalt; this.ws = ws; // this.wqs = { ...wsq }; } @@ -51,26 +40,17 @@ export class WSConnection implements MsgConnection { this.toMsg(buildErrorMsg(this.sthis, this.logger, {} as MsgBase, err)); onOpenFuture.resolve(Result.Err(err)); }, this.msgP.timeout); - this.wqs.ws.onopen = () => { + this.ws.onopen = () => { onOpenFuture.resolve(Result.Ok(undefined)); this.opened = true; }; - this.wqs.ws.onerror = (ierr) => { + this.ws.onerror = (ierr) => { const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError(); onOpenFuture.resolve(Result.Err(err)); - let conn: Connection; - try { - conn = this.conn; - } catch (_err) { - conn = { - key: { tenant: "not-connect", ledger: "not-connect" }, - reqId: "not-connect", - resId: "not-connect", - }; - } - this.toMsg(buildErrorMsg(this.sthis, this.logger, { conn } as MsgBase, err)); + const res = this.buildErrorMsg(this.logger.Error(), {}, err); + this.toMsg(res); }; - this.wqs.ws.onmessage = (evt) => { + this.ws.onmessage = (evt) => { if (!this.opened) { this.toMsg( buildErrorMsg( @@ -83,7 +63,7 @@ export class WSConnection implements MsgConnection { } this.#wsOnMessage(evt); }; - this.wqs.ws.onclose = () => { + this.ws.onclose = () => { this.opened = false; this.close().catch((ierr) => { const err = this.logger.Error().Err(ierr).Msg("close error").AsError(); @@ -98,11 +78,11 @@ export class WSConnection implements MsgConnection { if (rOpen.isErr()) { return rOpen; } - const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(resOpen)) { - return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); - } - this.wqs.resOpen = resOpen; + // const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen }); + // if (!MsgIsResOpen(resOpen)) { + // return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError()); + // } + // this.wqs.resOpen = resOpen; return Result.Ok(undefined); } @@ -135,17 +115,17 @@ export class WSConnection implements MsgConnection { this.#onClose.forEach((fn) => fn()); this.#onClose.clear(); this.#onMsg.clear(); - this.wqs.ws.close(); + this.ws.close(); return Result.Ok(undefined); } - toMsg(msg: WithErrorMsg): WithErrorMsg { + toMsg(msg: MsgWithError): MsgWithError { this.#onMsg.forEach((fn) => fn(msg)); return msg; } async sendMsg(msg: MsgBase): Promise { - this.wqs.ws.send(this.msgP.ende.encode(msg)); + this.ws.send(this.msgP.ende.encode(msg)); } onMsg(fn: OnMsgFn): UnReg { @@ -160,7 +140,7 @@ export class WSConnection implements MsgConnection { return () => this.#onClose.delete(key); } - async request(req: Q, opts: RequestOpts): Promise> { + async request(req: Q, opts: RequestOpts): Promise> { if (!this.opened) { return buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Msg("Connection not open").AsError()); } From 89de574e2343354477e904bc09134eae5826525f Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Tue, 7 Jan 2025 11:01:29 +0100 Subject: [PATCH 78/83] WIP --- src/cloud/connection.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index c90bd8a8..20043e59 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -60,7 +60,7 @@ describe("Connection", () => { sthis.env.sets((await resolveToml()).env as unknown as Record); }); - describe.each([[NodeHonoServerFactory(), CFHonoServerFactory()]])("$name - Connection", (honoServer) => { + describe.each([NodeHonoServerFactory(), CFHonoServerFactory()])("$name - Connection", (honoServer) => { const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { reqId: "req-open-test" }); const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); From ccd9d1d141c3aa1c20adbeae56a3a455d9e9eca1 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Wed, 8 Jan 2025 19:36:51 +0100 Subject: [PATCH 79/83] chore: with Meta-Merge --- src/cloud/backend/cf-hono-server.ts | 31 +- src/cloud/client/gateway.ts | 2 +- src/cloud/connection.test.ts | 462 +++++++++++------- src/cloud/hono-server.ts | 105 +++- src/cloud/http-connection.ts | 49 +- .../meta-merger/cf-worker-abstract-sql.ts | 4 +- src/cloud/meta-merger/meta-merger.test.ts | 73 ++- src/cloud/meta-merger/meta-merger.ts | 40 +- src/cloud/meta-merger/tenant-ledger.ts | 6 +- src/cloud/msg-dispatch.ts | 104 ++-- src/cloud/msg-dispatcher-impl.ts | 127 +++++ src/cloud/msg-type-meta.ts | 212 ++------ src/cloud/msg-types.ts | 60 ++- src/cloud/msger.ts | 47 +- src/cloud/node-hono-server.ts | 21 +- src/cloud/pre-signed-url.ts | 1 - src/cloud/test-helper.ts | 8 +- src/cloud/ws-connection.ts | 64 ++- 18 files changed, 912 insertions(+), 504 deletions(-) create mode 100644 src/cloud/msg-dispatcher-impl.ts diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index 03831ddc..e7e89cee 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -1,11 +1,13 @@ -import { HttpHeader, Logger, LoggerImpl, URI } from "@adviser/cement"; +import { HttpHeader, Logger, LoggerImpl, ResolveOnce, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; -import { CORS, ConnMiddleware, HonoServerFactory, RunTimeParams, HonoServerBase } from "../hono-server.js"; +import { ConnMiddleware, HonoServerFactory, RunTimeParams, HonoServerBase } from "../hono-server.js"; import { WSContext, WSContextInit, WSEvents } from "hono/ws"; import { buildErrorMsg, defaultGestalt, EnDeCoder, Gestalt } from "../msg-types.js"; // import { RequestInfo as CFRequestInfo } from "@cloudflare/workers-types"; import { defaultMsgParams, jsonEnDe } from "../msger.js"; import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; +import { SQLDatabase } from "../meta-merger/abstract-sql.js"; +import { CFWorkerSQLDatabase } from "../meta-merger/cf-worker-abstract-sql.js"; // function ensureLogger(env: Env, module = "Fireproof"): Logger { // const logger = new LoggerImpl() @@ -28,6 +30,8 @@ import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; // return logger.Logger(); // } +const startedChs = new ResolveOnce(); + export class CFHonoFactory implements HonoServerFactory { readonly _onClose: () => void; constructor( @@ -55,8 +59,14 @@ export class CFHonoFactory implements HonoServerFactory { const gs = defaultGestalt(msgP, { id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - - const ret = fn({ sthis, logger, ende, impl: new CFHonoServer(sthis, logger, ende, gs) }); + const ret = startedChs + .once(async () => { + const db = new CFWorkerSQLDatabase(c.env.DB); + const chs = new CFHonoServer(sthis, logger, ende, gs, db); + await chs.start(); + return chs; + }) + .then((chs) => fn({ sthis, logger, ende, impl: chs })); return ret; // .then((v) => sthis.logger.Flush().then(() => v)) } @@ -77,13 +87,18 @@ export class CFHonoFactory implements HonoServerFactory { export class CFHonoServer extends HonoServerBase { // _upgradeWebSocket?: UpgradeWebSocket - readonly headers: HttpHeader; readonly ende: EnDeCoder; // readonly env: Env; // readonly wsConnections = new Map() - constructor(sthis: SuperThis, logger: Logger, ende: EnDeCoder, gs: Gestalt, headers?: HttpHeader) { - super(sthis, logger, gs); - this.headers = HttpHeader.from(headers).Merge(CORS); + constructor( + sthis: SuperThis, + logger: Logger, + ende: EnDeCoder, + gs: Gestalt, + sqlDb: SQLDatabase, + headers?: HttpHeader + ) { + super(sthis, logger, gs, sqlDb, headers); this.ende = ende; // this.env = env; } diff --git a/src/cloud/client/gateway.ts b/src/cloud/client/gateway.ts index f56c70c3..a221fcef 100644 --- a/src/cloud/client/gateway.ts +++ b/src/cloud/client/gateway.ts @@ -117,7 +117,7 @@ abstract class BaseGateway { }, version: VERSION, } as ReqSignedUrl; - return conn.request(rsu, { waitFor: waitForFn }); + return conn.request(rsu, { waitFor: waitForFn }); } async putObject(uri: URI, uploadUrl: string, body: Uint8Array): Promise> { diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 20043e59..0c1f4535 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -9,7 +9,8 @@ import { defaultGestalt, ReqSignedUrlParam, GwCtx, - ResSignedUrl, + MsgWithError, + ResOptionalSignedUrl, } from "./msg-types.js"; import { MsgIsResGetData, @@ -32,8 +33,20 @@ import { HonoServer } from "./hono-server.js"; import { Hono } from "hono"; import { calculatePreSignedUrl } from "./pre-signed-url.js"; import { CFHonoServerFactory, httpStyle, NodeHonoServerFactory, resolveToml, wsStyle } from "./test-helper.js"; +import { + buildReqDelMeta, + buildBindGetMeta, + buildReqPutMeta, + MsgIsResDelMeta, + ResDelMeta, + ReqDelMeta, + BindGetMeta, + EventGetMeta, + MsgIsEventGetMeta, + MsgIsResPutMeta, +} from "./msg-type-meta.js"; -async function refURL(sp: ResSignedUrl) { +async function refURL(sp: ResOptionalSignedUrl) { const { env } = await resolveToml(); return ( await calculatePreSignedUrl(sp, { @@ -64,214 +77,283 @@ describe("Connection", () => { const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); const qOpen = buildReqOpen(sthis, { reqId: "req-open-test" }); const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); - describe.each([httpStyle(sthis, port, msgP, my), wsStyle(sthis, port, msgP, my)])("$name", (style) => { - let server: HonoServer; - beforeAll(async () => { - const app = new Hono(); - server = await honoServer - .factory(sthis, msgP, style.remoteGestalt, port) - .then((srv) => srv.register(app, port)); - }); - afterAll(async () => { - // console.log("closing server"); - await server.close(); - }); - it(`conn refused`, async () => { - const rC = await applyStart(style.connRefused.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/ECONNREFUSED/); - }); + describe.each([httpStyle(sthis, port, msgP, my), wsStyle(sthis, port, msgP, my)])( + `${honoServer.name} - $name`, + (style) => { + let server: HonoServer; + beforeAll(async () => { + const app = new Hono(); + server = await honoServer + .factory(sthis, msgP, style.remoteGestalt, port) + .then((srv) => srv.register(app, port)); + }); + afterAll(async () => { + // console.log("closing server"); + await server.close(); + }); + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/ECONNREFUSED/); + }); - it(`timeout`, async () => { - const rC = await applyStart(style.timeout.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/Timeout/i); - }); + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/Timeout/i); + }); - describe(`connection`, () => { - let c: MsgConnected; - beforeEach(async () => { - const rC = await style.ok.open().then((r) => MsgConnected.connect(r, { reqId: "req-open-testx" })); - expect(rC.isOk()).toBeTruthy(); - c = rC.Ok(); - expect(c.conn).toEqual({ - reqId: "req-open-testx", - resId: c.conn.resId, + describe(`connection`, () => { + let c: MsgConnected; + beforeEach(async () => { + const rC = await style.ok.open().then((r) => MsgConnected.connect(r, { reqId: "req-open-testx" })); + expect(rC.isOk()).toBeTruthy(); + c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testx", + resId: c.conn.resId, + }); + }); + afterEach(async () => { + await c.close(); }); - }); - afterEach(async () => { - await c.close(); - }); - it("kaputt url http", async () => { - const r = await c.raw.request( - { - tid: "test", - type: "kaputt", - version: "FP-MSG-1.0", - }, - { waitFor: () => true } - ); - if (!MsgIsError(r)) { - assert.fail("expected MsgError"); - return; - } - expect(r).toEqual({ - message: "unexpected message", - tid: "test", - type: "error", - version: "FP-MSG-1.0", - src: { + it("kaputt url http", async () => { + const r = await c.raw.request( + { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + { waitFor: () => true } + ); + if (!MsgIsError(r)) { + assert.fail("expected MsgError"); + return; + } + expect(r).toEqual({ + message: "unexpected message", tid: "test", - type: "kaputt", + type: "error", version: "FP-MSG-1.0", - }, + src: { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + }); + }); + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}); + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); + const r = await c.raw.request(req, { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)); + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); }); - }); - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, {}); - const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); - const r = await c.raw.request(req, { waitFor: MsgIsResGestalt }); - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)); - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); - }); - it("openConnection", async () => { - const req = buildReqOpen(sthis, { ...c.conn }); - const r = await c.raw.request(req, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)); - } - expect(r).toEqual({ - conn: { ...c.conn, resId: r.conn?.resId }, - tid: req.tid, - type: "resOpen", - version: "FP-MSG-1.0", + it("openConnection", async () => { + const req = buildReqOpen(sthis, { ...c.conn }); + const r = await c.raw.request(req, { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)); + } + expect(r).toEqual({ + conn: { ...c.conn, resId: r.conn?.resId }, + tid: req.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); }); }); - }); - it("open", async () => { - const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, { - reqId: "req-open-testy", - }); - expect(rC.isOk()).toBeTruthy(); - const c = rC.Ok(); - expect(c.conn).toEqual({ - reqId: "req-open-testy", - resId: c.conn.resId, - }); - expect(c.raw).toBeInstanceOf(style.cInstance); - expect(c.exchangedGestalt).toEqual({ - my, - remote: style.remoteGestalt, - }); - await c.close(); - }); - describe(`${honoServer.name} - Msgs`, () => { - let gwCtx: GwCtx; - let conn: MsgConnected; - beforeAll(async () => { - const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, qOpen.conn); + it("open", async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, { + reqId: "req-open-testy", + }); expect(rC.isOk()).toBeTruthy(); - conn = rC.Ok(); - gwCtx = { - conn: conn.conn, - tenant: { - tenant: "Tenant", - ledger: "Ledger", - }, - }; - }); - afterAll(async () => { - await conn.close(); - }); - it("Open", async () => { - const res = await conn.raw.request(buildReqOpen(sthis, conn.conn), { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(res)) { - assert.fail("expected MsgResOpen", JSON.stringify(res)); - } - expect(MsgIsResOpen(res)).toBeTruthy(); - expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn.resId }); + const c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testy", + resId: c.conn.resId, + }); + expect(c.raw).toBeInstanceOf(style.cInstance); + expect(c.exchangedGestalt).toEqual({ + my, + remote: style.remoteGestalt, + }); + await c.close(); }); - - function sup() { - return { - path: "test/me", - key: "key-test", - } satisfies ReqSignedUrlParam; - } - describe("Data", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetData(sthis, sp, gwCtx), { waitFor: MsgIsResGetData }); - if (MsgIsResGetData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetData", JSON.stringify(res)); - } + describe(`${honoServer.name} - Msgs`, () => { + let gwCtx: GwCtx; + let conn: MsgConnected; + beforeAll(async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, qOpen.conn); + expect(rC.isOk()).toBeTruthy(); + conn = rC.Ok(); + gwCtx = { + conn: conn.conn, + tenant: { + tenant: "Tenant", + ledger: "Ledger", + }, + }; }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutData(sthis, sp, gwCtx), { waitFor: MsgIsResPutData }); - if (MsgIsResPutData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutData", JSON.stringify(res)); - } + afterAll(async () => { + await conn.close(); }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelData(sthis, sp, gwCtx), { waitFor: MsgIsResDelData }); - if (MsgIsResDelData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelData", JSON.stringify(res)); + it("Open", async () => { + const res = await conn.raw.request(buildReqOpen(sthis, conn.conn), { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(res)) { + assert.fail("expected MsgResOpen", JSON.stringify(res)); } + expect(MsgIsResOpen(res)).toBeTruthy(); + expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn.resId }); }); - }); - // describe("Meta", async () => { - // // const res = await conn.request(buildReqGetMeta(), { waitFor: MsgIsResGetMeta }); - // // expect(MsgIsError(res)).toBeTruthy(); - // }); - describe("WAL", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetWAL(sthis, sp, gwCtx), { waitFor: MsgIsResGetWAL }); - if (MsgIsResGetWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetWAL", JSON.stringify(res)); - } + + function sup() { + return { + path: "test/me", + key: "key-test", + } satisfies ReqSignedUrlParam; + } + describe("Data", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetData(sthis, sp, gwCtx), { waitFor: MsgIsResGetData }); + if (MsgIsResGetData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetData", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutData(sthis, sp, gwCtx), { waitFor: MsgIsResPutData }); + if (MsgIsResPutData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutData", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelData(sthis, sp, gwCtx), { waitFor: MsgIsResDelData }); + if (MsgIsResDelData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelData", JSON.stringify(res)); + } + }); }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutWAL(sthis, sp, gwCtx), { waitFor: MsgIsResPutWAL }); - if (MsgIsResPutWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutWAL", JSON.stringify(res)); - } + + describe("Meta", async () => { + it("bind stop", async () => { + const sp = sup(); + expect(conn.raw.activeBinds.size).toBe(0); + const streams: ReadableStream>[] = Array(5) + .fill(0) + .map(() => { + return conn.bind(buildBindGetMeta(sthis, sp, gwCtx), { + waitFor: MsgIsEventGetMeta, + }); + }); + for await (const stream of streams) { + const reader = stream.getReader(); + while (true) { + const { done, value: msg } = await reader.read(); + if (done) { + break; + } + if (MsgIsEventGetMeta(msg)) { + // expect(msg.params).toEqual(sp); + expect(URI.from(msg.signedUrl).asObj()).toEqual(await refURL(msg)); + } else { + assert.fail("expected MsgEventGetMeta", JSON.stringify(msg)); + } + await reader.cancel(); + } + } + expect(conn.raw.activeBinds.size).toBe(0); + // await Promise.all(streams.map((s) => s.cancel())); + }); + + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildBindGetMeta(sthis, sp, gwCtx), { waitFor: MsgIsEventGetMeta }); + if (MsgIsEventGetMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgIsEventGetMeta", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const metas = Array(5) + .fill({ cid: "x", parents: [], data: "MomRkYXRho" }) + .map((data) => { + return { ...data, cid: sthis.timeOrderedNextId().str }; + }); + const res = await conn.request(buildReqPutMeta(sthis, sp, metas, gwCtx), { waitFor: MsgIsResPutMeta }); + if (MsgIsResPutMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgIsResPutMeta", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelMeta(sthis, sp, gwCtx), { + waitFor: MsgIsResDelMeta, + }); + if (MsgIsResDelMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelWAL(sthis, sp, gwCtx), { waitFor: MsgIsResDelWAL }); - if (MsgIsResDelWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelWAL", JSON.stringify(res)); - } + describe("WAL", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetWAL(sthis, sp, gwCtx), { waitFor: MsgIsResGetWAL }); + if (MsgIsResGetWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetWAL", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutWAL(sthis, sp, gwCtx), { waitFor: MsgIsResPutWAL }); + if (MsgIsResPutWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutWAL", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelWAL(sthis, sp, gwCtx), { waitFor: MsgIsResDelWAL }); + if (MsgIsResDelWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); }); }); - }); - }); + } + ); }); }); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index 8f34521c..cfa0a27e 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -2,10 +2,35 @@ import { exception2Result, HttpHeader, param, ResolveOnce, Result, URI } from "@ import { Logger, SuperThis } from "@fireproof/core"; import { Context, Hono, Next } from "hono"; import { top_uint8 } from "../coerce-binary.js"; -import { Gestalt, buildErrorMsg, MsgBase, EnDeCoder, ErrorMsg } from "./msg-types.js"; +import { + Gestalt, + buildErrorMsg, + MsgBase, + EnDeCoder, + ErrorMsg, + MsgWithError, + buildRes, + MsgWithConn, + GwCtx, + MsgIsError, +} from "./msg-types.js"; import { MsgDispatcher, WSConnection } from "./msg-dispatch.js"; import { WSEvents } from "hono/ws"; import { calculatePreSignedUrl, PreSignedMsg } from "./pre-signed-url.js"; +import { buildMsgDispatcher } from "./msg-dispatcher-impl.js"; +import { + BindGetMeta, + buildEventGetMeta, + buildResDelMeta, + buildResPutMeta, + EventGetMeta, + ReqDelMeta, + ReqPutMeta, + ResDelMeta, + ResPutMeta, +} from "./msg-type-meta.js"; +import { MetaMerger } from "./meta-merger/meta-merger.js"; +import { SQLDatabase } from "./meta-merger/abstract-sql.js"; export interface RunTimeParams { readonly sthis: SuperThis; @@ -16,27 +41,95 @@ export interface RunTimeParams { // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export type ConnMiddleware = (conn: WSConnection, c: Context, next: Next) => Promise; export interface HonoServerImpl { + start(): Promise; gestalt(): Gestalt; - // msgP(): MsgerParams; calculatePreSignedUrl(p: PreSignedMsg): Promise>; upgradeWebSocket: (createEvents: (c: Context) => WSEvents | Promise) => ConnMiddleware; + handleBindGetMeta(sthis: SuperThis, logger: Logger, msg: BindGetMeta): Promise>; + handleReqPutMeta(sthis: SuperThis, logger: Logger, msg: ReqPutMeta): Promise>; + handleReqDelMeta(sthis: SuperThis, logger: Logger, msg: ReqDelMeta): Promise>; readonly headers: HttpHeader; } -export abstract class HonoServerBase { +export abstract class HonoServerBase implements HonoServerImpl { readonly _gs: Gestalt; readonly sthis: SuperThis; readonly logger: Logger; - constructor(sthis: SuperThis, logger: Logger, gs: Gestalt) { + readonly metaMerger: MetaMerger; + readonly headers: HttpHeader; + constructor(sthis: SuperThis, logger: Logger, gs: Gestalt, sqlDb: SQLDatabase, headers?: HttpHeader) { this.logger = logger; this._gs = gs; this.sthis = sthis; + this.metaMerger = new MetaMerger(sqlDb); + this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + } + + abstract upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware; + + start(drop = false): Promise { + return this.metaMerger.createSchema(drop).then(() => this); } gestalt(): Gestalt { return this._gs; } + async handleReqPutMeta( + sthis: SuperThis, + logger: Logger, + msg: MsgWithConn + ): Promise> { + const rUrl = await buildRes("PUT", "meta", "resPutMeta", sthis, logger, msg, this); + if (MsgIsError(rUrl)) { + return rUrl; + } + await this.metaMerger.addMeta({ + logger, + connection: msg, + metas: msg.metas, + }); + return buildResPutMeta(sthis, logger, msg, { ...rUrl, metas: await this.metaMerger.metaToSend(msg) }); + } + + async handleReqDelMeta( + sthis: SuperThis, + logger: Logger, + msg: MsgWithConn + ): Promise> { + const rUrl = await buildRes("DELETE", "meta", "resDelMeta", sthis, logger, msg, this); + if (MsgIsError(rUrl)) { + return rUrl; + } + await this.metaMerger.delMeta({ + logger, + connection: msg, + }); + return buildResDelMeta(sthis, logger, msg, rUrl.signedUrl); + } + + async handleBindGetMeta( + sthis: SuperThis, + logger: Logger, + msg: MsgWithConn, + gwCtx: GwCtx = msg + ): Promise> { + const rUrl = await buildRes("GET", "meta", "eventGetMeta", sthis, logger, msg, this); + if (MsgIsError(rUrl)) { + return rUrl; + } + return buildEventGetMeta( + sthis, + logger, + msg, + { + ...rUrl, + metas: await this.metaMerger.metaToSend(msg), + }, + gwCtx + ); + } + calculatePreSignedUrl(p: PreSignedMsg): Promise> { const rRes = this.sthis.env.gets({ STORAGE_URL: param.REQUIRED, @@ -103,7 +196,7 @@ export class HonoServer { c.status(400); return c.json(buildErrorMsg(sthis, logger, { tid: "internal" }, rMsg.Err())); } - const dispatcher = new MsgDispatcher(sthis, impl.gestalt()); + const dispatcher = buildMsgDispatcher(sthis, impl.gestalt()); return dispatcher.dispatch(impl, rMsg.Ok(), (msg) => c.json(msg)); }) ); @@ -113,7 +206,7 @@ export class HonoServer { let dp: MsgDispatcher; return { onOpen: (_e, _ws) => { - dp = new MsgDispatcher(sthis, impl.gestalt()); + dp = buildMsgDispatcher(sthis, impl.gestalt()); }, onError: (error) => { logger.Error().Err(error).Msg("WebSocket error"); diff --git a/src/cloud/http-connection.ts b/src/cloud/http-connection.ts index 3af4d1d8..17a07b34 100644 --- a/src/cloud/http-connection.ts +++ b/src/cloud/http-connection.ts @@ -1,7 +1,8 @@ import { HttpHeader, Logger, Result, URI, exception2Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { MsgBase, buildErrorMsg, MsgWithError, RequestOpts } from "./msg-types.js"; +import { MsgBase, buildErrorMsg, MsgWithError, RequestOpts, MsgIsError } from "./msg-types.js"; import { + ActiveStream, ExchangedGestalt, MsgerParamsWithEnDe, MsgRawConnection, @@ -40,6 +41,7 @@ export class HttpConnection extends MsgRawConnectionBase implements MsgRawConnec } async close(): Promise> { + await Promise.all(Array.from(this.activeBinds.values()).map((state) => state.controller?.close())); this.#onMsg.clear(); return Result.Ok(undefined); } @@ -55,6 +57,51 @@ export class HttpConnection extends MsgRawConnectionBase implements MsgRawConnec return () => this.#onMsg.delete(key); } + #poll(state: ActiveStream): void { + this.request(state.bind.msg, state.bind.opts) + .then((msg) => { + try { + state.controller?.enqueue(msg); + if (MsgIsError(msg)) { + state.controller?.close(); + } else { + state.timeout = setTimeout(() => this.#poll(state), state.bind.opts.pollInterval ?? 1000); + } + } catch (err) { + console.log("poll error", err); + state.controller?.error(err); + state.controller?.close(); + } + }) + .catch((err) => { + console.log("poll catch error", err); + state.controller?.error(err); + // state.controller?.close(); + }); + } + + readonly activeBinds = new Map>(); + bind(req: Q, opts: RequestOpts): ReadableStream> { + const state: ActiveStream = { + id: this.sthis.nextId().str, + bind: { + msg: req, + opts, + }, + } satisfies ActiveStream; + this.activeBinds.set(state.id, state); + return new ReadableStream>({ + cancel: () => { + clearTimeout(state.timeout as number); + this.activeBinds.delete(state.id); + }, + start: (controller) => { + state.controller = controller; + this.#poll(state); + }, + }); + } + async request(req: Q, _opts: RequestOpts): Promise> { const headers = HttpHeader.from(); headers.Set("Content-Type", this.msgP.mime); diff --git a/src/cloud/meta-merger/cf-worker-abstract-sql.ts b/src/cloud/meta-merger/cf-worker-abstract-sql.ts index a3ff80ae..3f024357 100644 --- a/src/cloud/meta-merger/cf-worker-abstract-sql.ts +++ b/src/cloud/meta-merger/cf-worker-abstract-sql.ts @@ -9,7 +9,9 @@ export class CFWorkerSQLStatement implements SQLStatement { } async run(...iparams: SQLParams): Promise { - return this.stmt.bind(...sqliteCoerceParams(iparams)).run() as T; + const bound = this.stmt.bind(...sqliteCoerceParams(iparams)); + console.log("cf-run", sqliteCoerceParams(iparams), bound); + return bound.run() as T; } async all(...params: SQLParams): Promise { const rows = await this.stmt.bind(...sqliteCoerceParams(params)).run(); diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index e06bf956..9d9dffa9 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -29,6 +29,7 @@ function toCRDTEntries(rows: MetaConnection[]) { describe("MetaMerger", () => { let db: SQLDatabase; const sthis = ensureSuperThis(); + const logger = sthis.logger; let mm: MetaMerger; beforeAll(async () => { // db = new Database(':memory:'); @@ -40,7 +41,7 @@ describe("MetaMerger", () => { const { BetterSQLDatabase } = await import("./bettersql-abstract-sql.js"); db = new BetterSQLDatabase("./dist/test.db"); } - mm = new MetaMerger(sthis, db); + mm = new MetaMerger(db); await mm.createSchema(); }); @@ -53,13 +54,22 @@ describe("MetaMerger", () => { }, conn: { reqId: "reqId", - resId: "resId", + resId: `resId-${sthis.timeOrderedNextId().str}`, }, } satisfies Connection; }); + afterEach(async () => { + mm.delMeta({ + logger, + connection, + metas: [], + }); + }); + it("insert nothing", async () => { await mm.addMeta({ + logger, connection, metas: [], now: new Date(), @@ -77,6 +87,7 @@ describe("MetaMerger", () => { data: "MomRkYXRho", }); await mm.addMeta({ + logger, connection, metas, now: new Date(), @@ -91,6 +102,7 @@ describe("MetaMerger", () => { }); it("insert multiple", async () => { + const conns = []; for (let i = 0; i < 10; i++) { const metas = Array(i) .fill({ @@ -99,10 +111,16 @@ describe("MetaMerger", () => { data: "MomRkYXRho", }) .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); + const conn = { + ...connection.conn, + reqId: sthis.timeOrderedNextId().str, + }; + conns.push(conn); await mm.addMeta({ + logger, connection: { ...connection, - conn: { ...connection.conn, reqId: sthis.timeOrderedNextId().str }, + conn, } satisfies Connection, metas, now: new Date(), @@ -110,6 +128,15 @@ describe("MetaMerger", () => { const rows = await mm.metaToSend(connection); expect(sortCRDTEntries(rows)).toEqual(sortCRDTEntries(metas)); } + await Promise.all( + conns.map(async (conn) => + mm.delMeta({ + logger, + connection: { ...connection, conn }, + metas: [], + }) + ) + ); }); it("metaToSend to sink", async () => { @@ -127,6 +154,7 @@ describe("MetaMerger", () => { .map((m) => ({ ...m, cid: sthis.timeOrderedNextId().str })); ref.push({ metas, connection }); await mm.addMeta({ + logger, connection, metas, now: new Date(), @@ -148,5 +176,44 @@ describe("MetaMerger", () => { const rowsEmpty = await mm.metaToSend(connection); expect(sortCRDTEntries(rowsEmpty)).toEqual([]); } + await Promise.all( + connections.map(async (connection) => + mm.delMeta({ + logger, + connection, + metas: [], + }) + ) + ); + }); + + it("delMeta", async () => { + await mm.addMeta({ + logger, + connection, + metas: [ + { + cid: `del-${sthis.timeOrderedNextId().str}`, + parents: [], + data: "MomRkYXRho", + }, + { + cid: `del-${sthis.timeOrderedNextId().str}`, + parents: [], + data: "MomRkYXRho", + }, + ], + now: new Date(), + }); + const rows = await mm.metaToSend(connection); + expect(rows.length).toBe(2); + await mm.delMeta({ + logger, + connection, + metas: rows, + now: new Date(), + }); + const rowsDel = await mm.metaToSend(connection); + expect(rowsDel.length).toBe(0); }); }); diff --git a/src/cloud/meta-merger/meta-merger.ts b/src/cloud/meta-merger/meta-merger.ts index fa79726a..5b7a62d5 100644 --- a/src/cloud/meta-merger/meta-merger.ts +++ b/src/cloud/meta-merger/meta-merger.ts @@ -1,14 +1,4 @@ -/* -class MetaMerger { - mergeMeta(meta) { - } - - getMeta() { - } -} -*/ - -import { CRDTEntry, SuperThis } from "@fireproof/core"; +import { CRDTEntry, Logger } from "@fireproof/core"; import { MetaByTenantLedgerSql } from "./meta-by-tenant-ledger.js"; import { MetaSendSql } from "./meta-send.js"; import { TenantLedgerSql } from "./tenant-ledger.js"; @@ -22,6 +12,7 @@ export interface Connection { } export interface MetaMerge { + readonly logger: Logger; readonly connection: Connection; readonly metas: CRDTEntry[]; readonly now?: Date; @@ -43,7 +34,7 @@ function toByConnection(connection: Connection): ByConnection { export class MetaMerger { readonly db: SQLDatabase; - readonly sthis: SuperThis; + // readonly sthis: SuperThis; readonly sql: { readonly tenant: TenantSql; readonly tenantLedger: TenantLedgerSql; @@ -51,9 +42,9 @@ export class MetaMerger { readonly metaSend: MetaSendSql; }; - constructor(sthis: SuperThis, db: SQLDatabase) { + constructor(db: SQLDatabase) { this.db = db; - this.sthis = sthis; + // this.sthis = sthis; const tenant = new TenantSql(db); const tenantLedger = new TenantLedgerSql(db, tenant); this.sql = { @@ -70,18 +61,27 @@ export class MetaMerger { } } - async addMeta(mm: MetaMerge) { - if (!mm.metas.length) { - return; - } + async delMeta( + mm: Omit & { readonly metas?: CRDTEntry[] } + ): Promise<{ now: Date; byConnection: ByConnection }> { const now = mm.now || new Date(); const byConnection = toByConnection(mm.connection); + const metaCIDs = (mm.metas ?? []).map((meta) => meta.cid); const connCIDs = { ...byConnection, - metaCIDs: mm.metas.map((meta) => meta.cid), + // needs something with is not empty to delete + metaCIDs: metaCIDs.length ? metaCIDs : [new Date().toISOString()], }; await this.sql.metaSend.deleteByConnection(connCIDs); await this.sql.metaByTenantLedger.deleteByConnection(connCIDs); + return { now, byConnection }; + } + + async addMeta(mm: MetaMerge) { + if (!mm.metas.length) { + return; + } + const { now, byConnection } = await this.delMeta(mm); await this.sql.tenantLedger.ensure({ ...mm.connection.tenant, createdAt: now, @@ -95,7 +95,7 @@ export class MetaMerger { updateAt: now, }); } catch (e) { - this.sthis.logger.Warn().Err(e).Str("metaCID", meta.cid).Msg("addMeta"); + mm.logger.Warn().Err(e).Str("metaCID", meta.cid).Msg("addMeta"); } } } diff --git a/src/cloud/meta-merger/tenant-ledger.ts b/src/cloud/meta-merger/tenant-ledger.ts index 7e6bd226..e3a8dc77 100644 --- a/src/cloud/meta-merger/tenant-ledger.ts +++ b/src/cloud/meta-merger/tenant-ledger.ts @@ -54,8 +54,10 @@ export class TenantLedgerSql { } async ensure(t: TenantLedgerRow) { - this.tenantSql.ensure({ tenant: t.tenant, createdAt: t.createdAt }); + await this.tenantSql.ensure({ tenant: t.tenant, createdAt: t.createdAt }); const stmt = this.sqlEnsureTenantLedger(); - return stmt.run(t.tenant, t.ledger, t.createdAt, t.tenant, t.ledger); + console.log("ensure(->TenantLedgerRow)", t.tenant, t.ledger, t.createdAt); + const ret = stmt.run(t.tenant, t.ledger, t.createdAt, t.tenant, t.ledger); + return ret; } } diff --git a/src/cloud/msg-dispatch.ts b/src/cloud/msg-dispatch.ts index 2e2196da..dc39b54a 100644 --- a/src/cloud/msg-dispatch.ts +++ b/src/cloud/msg-dispatch.ts @@ -1,36 +1,10 @@ import { Logger } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { - Gestalt, - MsgBase, - MsgIsReqGestalt, - buildResGestalt, - buildErrorMsg, - buildResOpen, - MsgWithError, - MsgIsWithConn, - MsgWithConn, - QSId, - MsgIsReqOpen, -} from "./msg-types.js"; -import { - MsgIsReqGetData, - buildResGetData, - MsgIsReqPutData, - MsgIsReqDelData, - buildResDelData, - buildResPutData, -} from "./msg-types-data.js"; -import { - MsgIsReqDelWAL, - MsgIsReqGetWAL, - MsgIsReqPutWAL, - buildResDelWAL, - buildResGetWAL, - buildResPutWAL, -} from "./msg-types-wal.js"; +import { Gestalt, MsgBase, buildErrorMsg, MsgWithError, MsgIsWithConn, MsgWithConn, QSId } from "./msg-types.js"; + import { PreSignedMsg } from "./pre-signed-url.js"; import { HonoServerImpl } from "./hono-server.js"; +import { UnReg } from "./msger.js"; export interface MsgContext { calculatePreSignedUrl(p: PreSignedMsg): Promise; @@ -93,6 +67,15 @@ class ConnectionManager { } const connManager = new ConnectionManager(); +export interface MsgDispatcherCtx { + readonly impl: HonoServerImpl; +} +export interface MsgDispatchItem { + readonly match: (msg: MsgBase) => boolean; + readonly isNotConn?: boolean; + fn(sthis: SuperThis, logger: Logger, ctx: MsgDispatcherCtx, msg: Q): Promisable>; +} + export class MsgDispatcher { readonly sthis: SuperThis; readonly logger: Logger; @@ -100,9 +83,13 @@ export class MsgDispatcher { readonly gestalt: Gestalt; readonly id: string; - readonly conns = new Map(); + readonly connManager = connManager; - constructor(sthis: SuperThis, gestalt: Gestalt) { + static new(sthis: SuperThis, gestalt: Gestalt): MsgDispatcher { + return new MsgDispatcher(sthis, gestalt); + } + + private constructor(sthis: SuperThis, gestalt: Gestalt) { this.sthis = sthis; this.logger = ensureLogger(sthis, "Dispatcher"); this.gestalt = gestalt; @@ -116,6 +103,17 @@ export class MsgDispatcher { // return Result.Ok(connManager.addConn(msg.conn)); // } + readonly items = new Map>(); + registerMsg(...iItems: MsgDispatchItem[]): UnReg { + const items = iItems.flat(); + const ids: string[] = items.map((item) => { + const id = this.sthis.nextId(12).str; + this.items.set(id, item); + return id; + }); + return () => ids.forEach((id) => this.items.delete(id)); + } + async dispatch(ctx: HonoServerImpl, msg: MsgBase, send: (msg: MsgBase) => Promisable): Promise { const validateConn = async ( msg: T, @@ -129,43 +127,13 @@ export class MsgDispatcher { const r = await fn(msg); return Promise.resolve(send(r)); }; - switch (true) { - case MsgIsReqGestalt(msg): - return send(buildResGestalt(msg, this.gestalt)); - case MsgIsReqOpen(msg): { - if (!msg.conn) { - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("missing connection"))); - } - if (connManager.isConnected(msg)) { - return send(buildResOpen(this.sthis, msg, msg.conn.resId)); - } - const resId = this.sthis.nextId(12).str; - const resOpen = buildResOpen(this.sthis, msg, resId); - connManager.addConn(resOpen.conn); - return send(resOpen); - } - case MsgIsReqGetData(msg): { - return validateConn(msg, (msg) => buildResGetData(this.sthis, this.logger, msg, ctx)); - } - case MsgIsReqPutData(msg): { - return validateConn(msg, (msg) => buildResPutData(this.sthis, this.logger, msg, ctx)); - } - case MsgIsReqDelData(msg): { - return validateConn(msg, (msg) => buildResDelData(this.sthis, this.logger, msg, ctx)); - } - - case MsgIsReqGetWAL(msg): { - return validateConn(msg, (msg) => buildResGetWAL(this.sthis, this.logger, msg, ctx)); - } - case MsgIsReqPutWAL(msg): { - return validateConn(msg, (msg) => buildResPutWAL(this.sthis, this.logger, msg, ctx)); - } - case MsgIsReqDelWAL(msg): { - return validateConn(msg, (msg) => buildResDelWAL(this.sthis, this.logger, msg, ctx)); - } - - default: - return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); + const found = Array.from(this.items.values()).find((item) => item.match(msg)); + if (!found) { + return send(buildErrorMsg(this.sthis, this.logger, msg, new Error("unexpected message"))); + } + if (!found.isNotConn) { + return validateConn(msg, (msg) => found.fn(this.sthis, this.logger, { impl: ctx }, msg)); } + return send(await found.fn(this.sthis, this.logger, { impl: ctx }, msg)); } } diff --git a/src/cloud/msg-dispatcher-impl.ts b/src/cloud/msg-dispatcher-impl.ts new file mode 100644 index 00000000..1645fc23 --- /dev/null +++ b/src/cloud/msg-dispatcher-impl.ts @@ -0,0 +1,127 @@ +import { SuperThis } from "@fireproof/core"; +import { MsgDispatcher } from "./msg-dispatch.js"; +import { + MsgIsReqGetData, + buildResGetData, + MsgIsReqPutData, + MsgIsReqDelData, + buildResDelData, + buildResPutData, + ReqGetData, + ReqPutData, + ReqDelData, +} from "./msg-types-data.js"; +import { + MsgIsReqDelWAL, + MsgIsReqGetWAL, + MsgIsReqPutWAL, + ReqDelWAL, + ReqGetWAL, + ReqPutWAL, + buildResDelWAL, + buildResGetWAL, + buildResPutWAL, +} from "./msg-types-wal.js"; +import { + MsgIsReqGestalt, + buildResGestalt, + MsgIsReqOpen, + buildErrorMsg, + buildResOpen, + MsgIsReqOpenWithConn, + MsgWithConn, + ReqGestalt, + Gestalt, +} from "./msg-types.js"; +import { + BindGetMeta, + MsgIsBindGetMeta, + MsgIsReqDelMeta, + MsgIsReqPutMeta, + ReqDelMeta, + ReqPutMeta, +} from "./msg-type-meta.js"; + +export function buildMsgDispatcher(sthis: SuperThis, gestalt: Gestalt): MsgDispatcher { + const dp = MsgDispatcher.new(sthis, gestalt); + dp.registerMsg( + { + match: MsgIsReqGestalt, + isNotConn: true, + fn: (_sthis, _logger, _ctx, msg: ReqGestalt) => { + return buildResGestalt(msg, dp.gestalt); + }, + }, + { + match: MsgIsReqOpen, + isNotConn: true, + fn: (sthis, logger, _ctx, msg) => { + if (!MsgIsReqOpenWithConn(msg)) { + return buildErrorMsg(sthis, logger, msg, new Error("missing connection")); + } + if (dp.connManager.isConnected(msg)) { + return buildResOpen(sthis, msg, msg.conn.resId); + } + const resId = sthis.nextId(12).str; + const resOpen = buildResOpen(sthis, msg, resId); + dp.connManager.addConn(resOpen.conn); + return resOpen; + }, + }, + { + match: MsgIsReqGetData, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResGetData(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsReqPutData, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResPutData(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsReqDelData, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResDelData(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsReqGetWAL, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResGetWAL(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsReqPutWAL, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResPutWAL(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsReqDelWAL, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return buildResDelWAL(sthis, logger, msg, ctx.impl); + }, + }, + { + match: MsgIsBindGetMeta, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return ctx.impl.handleBindGetMeta(sthis, logger, msg); + }, + }, + { + match: MsgIsReqPutMeta, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return ctx.impl.handleReqPutMeta(sthis, logger, msg); + }, + }, + { + match: MsgIsReqDelMeta, + fn: (sthis, logger, ctx, msg: MsgWithConn) => { + return ctx.impl.handleReqDelMeta(sthis, logger, msg); + }, + } + ); + return dp; +} diff --git a/src/cloud/msg-type-meta.ts b/src/cloud/msg-type-meta.ts index bf6c0a0c..80c2201d 100644 --- a/src/cloud/msg-type-meta.ts +++ b/src/cloud/msg-type-meta.ts @@ -1,4 +1,4 @@ -import { VERSION } from "@adviser/cement"; +import { Logger, VERSION } from "@adviser/cement"; import { CRDTEntry } from "@fireproof/core"; import { GwCtx, @@ -7,61 +7,10 @@ import { MsgWithOptionalConn, MsgWithTenantLedger, NextId, - ReqRes, ReqSignedUrlParam, - SignedUrlParam, + ResOptionalSignedUrl, } from "./msg-types.js"; -/* Subscribe Meta */ - -// export interface ReqSubscribeMeta extends MsgBase { -// readonly type: "reqSubscribeMeta"; -// readonly subscriberId: string; -// readonly conn: ; -// } - -// export type ReqSubscribeMetaWithConnId = AddConnId; - -// export function MsgIsReqSubscribeMetaWithConnId(req: MsgBase): req is ReqSubscribeMetaWithConnId { -// return req.type === "reqSubscribeMetaWithConnId"; -// } - -// export function MsgIsReqSubscribeMeta(req: MsgBase): req is ReqSubscribeMeta { -// return req.type === "reqSubscribeMeta"; -// } - -// export function buildReqSubscribeMeta(sthis: NextId, ck: Connection, subscriberId: string): ReqSubscribeMeta { -// return { -// tid: sthis.nextId().str, -// subscriberId, -// type: "reqSubscribeMeta", -// version: VERSION, -// conn: ck, -// }; -// } - -// export interface ResSubscribeMeta extends MsgBase { -// readonly type: "resSubscribeMeta"; -// readonly subscriberId: string; -// readonly conn: Connection; -// } - -// export function buildResSubscribeMeta(req: ReqSubscribeMeta /*, _conn: Connection*/): ResSubscribeMeta { -// return { -// tid: req.tid, -// type: "resSubscribeMeta", -// subscriberId: req.subscriberId, -// conn: req.conn, -// version: VERSION, -// }; -// } - -// export function MsgIsResSubscribeMeta>( -// qs: T -// ): qs is T & ReqRes { -// return qs.res.type === "resSubscribeMeta"; -// } - /* Put Meta */ export interface ReqPutMeta extends MsgWithTenantLedger { readonly type: "reqPutMeta"; @@ -69,18 +18,7 @@ export interface ReqPutMeta extends MsgWithTenantLedger { readonly metas: CRDTEntry[]; } -// export type ReqPutMetaWithConnId = AddConnId; - -// export function MsgIsReqPutMetaWithConnId(msg: MsgBase): msg is ReqPutMetaWithConnId { -// return msg.type === "reqPutMetaWithConnId"; -// } - -export interface PutMetaParam { - readonly metas: CRDTEntry[]; - readonly signedPutUrl: string; -} - -export interface ResPutMeta extends MsgWithTenantLedger, PutMetaParam { +export interface ResPutMeta extends MsgWithTenantLedger, QSMeta { readonly type: "resPutMeta"; } @@ -105,115 +43,74 @@ export function MsgIsReqPutMeta(msg: MsgBase): msg is ReqPutMeta { } export function buildResPutMeta( + _sthis: NextId, + _logger: Logger, req: MsgWithTenantLedger>, - metaParam: PutMetaParam + meta: QSMeta ): ResPutMeta { return { - ...metaParam, + ...meta, tid: req.tid, - type: "resPutMeta", conn: req.conn, tenant: req.tenant, + type: "resPutMeta", + // key: req.key, version: VERSION, }; } -export function MsgIsResPutMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resPutMeta" && qs.req.type === "reqPutMeta"; -} - -export interface ConnSubId { - readonly connId: string; - readonly subscriberId: string; -} - -/** - * This is used for non WebSocket server implementations - * to retrieve the meta data. It should be done by polling - * and might implement long polling. - * It will answer with a UpdateMetaEvent. - */ -// export interface ReqUpdateMeta extends MsgBase, ConnSubId { -// readonly type: "reqUpdateMeta"; -// } - -export interface UpdateMetaEvent extends MsgWithTenantLedger, ConnSubId { - readonly type: "updateMeta"; - readonly metas: CRDTEntry[]; -} - -export function buildUpdateMetaEvent( - rq: ReqRes>, ResPutMeta>, - consub: ConnSubId -): UpdateMetaEvent { - return { - ...consub, - tid: rq.res.tid, - type: "updateMeta", - conn: rq.res.conn, - tenant: rq.res.tenant, - metas: rq.req.metas, - version: rq.res.version, - }; -} - -export function MsgIsUpdateMetaEvent(msg: MsgBase): msg is UpdateMetaEvent { - return msg.type === "updateMeta"; +export function MsgIsResPutMeta(qs: MsgBase): qs is ResPutMeta { + return qs.type === "resPutMeta"; } -/* Get Meta */ -export interface ReqGetMeta extends MsgWithTenantLedger { - readonly type: "reqGetMeta"; +/* Bind Meta */ +export interface BindGetMeta extends MsgWithTenantLedger { + readonly type: "bindGetMeta"; readonly params: ReqSignedUrlParam; } -// export type ReqGetMetaWithConnId = AddConnId; - -export function MsgIsReqGetMeta(msg: MsgBase): msg is ReqGetMeta { - return msg.type === "reqGetMeta"; +export function MsgIsBindGetMeta(msg: MsgBase): msg is BindGetMeta { + return msg.type === "bindGetMeta"; } -// export function MsgIsReqGetMetaWithConnId(msg: MsgBase): msg is ReqGetMetaWithConnId { -// return msg.type === "reqGetMetaWithConnId"; -// } - -export interface GetMetaParam { - // readonly params: SignedUrlParam; - // readonly key: ConnectionKey; - readonly status: "found" | "not-found" | "redirect"; +export interface QSMeta extends ResOptionalSignedUrl { readonly metas: CRDTEntry[]; - readonly connId: string; - // if set client should query this url to retrieve the meta - readonly signedGetUrl?: string; + readonly keys?: string[]; } -export interface ResGetMeta extends MsgBase, GetMetaParam { - readonly type: "resGetMeta"; - readonly params: SignedUrlParam; +export interface EventGetMeta extends MsgWithTenantLedger, ResOptionalSignedUrl { + readonly type: "eventGetMeta"; } -export function buildReqGetMeta(sthis: NextId, signedUrlParams: ReqSignedUrlParam, gwCtx: GwCtx): ReqGetMeta { +export function buildBindGetMeta(sthis: NextId, params: ReqSignedUrlParam, gwCtx: GwCtx): BindGetMeta { return { tid: sthis.nextId().str, ...gwCtx, - type: "reqGetMeta", + type: "bindGetMeta", version: VERSION, - params: signedUrlParams, + params, }; } -export function buildResGetMeta(req: ReqGetMeta, metaParam: GetMetaParam): ResGetMeta { +export function buildEventGetMeta( + _sthis: NextId, + _logger: Logger, + req: MsgWithTenantLedger>, + metaParam: QSMeta, + gwCtx: GwCtx +): EventGetMeta { return { ...metaParam, + ...gwCtx, tid: req.tid, - type: "resGetMeta", + type: "eventGetMeta", params: { ...req.params, method: "GET", store: "meta" }, version: VERSION, }; } -export function MsgIsResGetMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resGetMeta" && qs.req.type === "reqGetMeta"; +export function MsgIsEventGetMeta(qs: MsgBase): qs is EventGetMeta { + return qs.type === "eventGetMeta"; } /* Del Meta */ @@ -222,26 +119,7 @@ export interface ReqDelMeta extends MsgWithTenantLedger { readonly params: ReqSignedUrlParam; } -// export type ReqDelMetaWithConnId = AddConnId; - -// export function MsgIsReqDelMetaWithConnId(msg: MsgBase): msg is ReqDelMetaWithConnId { -// return msg.type === "reqDelMetaWithConnId"; -// } - -export interface DelMetaParam { - readonly params: SignedUrlParam; - // readonly key: ConnectionKey; - readonly status: "found" | "not-found" | "redirect" | "unsupported"; - // readonly connId: string; - // if set client should query this url to retrieve the meta - readonly signedDelUrl?: string; -} - -export interface ResDelMeta extends MsgBase, DelMetaParam { - readonly type: "resDelMeta"; -} - -export function buildReqDelMeta(sthis: NextId, signedUrlParams: SignedUrlParam, gwCtx: GwCtx): ReqDelMeta { +export function buildReqDelMeta(sthis: NextId, signedUrlParams: ReqSignedUrlParam, gwCtx: GwCtx): ReqDelMeta { return { tid: sthis.nextId().str, ...gwCtx, @@ -255,16 +133,28 @@ export function MsgIsReqDelMeta(msg: MsgBase): msg is ReqDelMeta { return msg.type === "reqDelMeta"; } -export function buildResDelMeta(req: ReqDelMeta, metaParam: DelMetaParam): ResDelMeta { +export interface ResDelMeta extends MsgWithTenantLedger, ResOptionalSignedUrl { + readonly type: "resDelMeta"; +} + +export function buildResDelMeta( + _sthis: NextId, + _logger: Logger, + req: MsgWithTenantLedger>, + signedUrl?: string +): ResDelMeta { return { - ...metaParam, + params: { ...req.params, method: "DELETE", store: "meta" }, + signedUrl, tid: req.tid, + conn: req.conn, + tenant: req.tenant, type: "resDelMeta", // key: req.key, version: VERSION, }; } -export function MsgIsResDelMeta(qs: ReqRes): qs is ReqRes { - return qs.res.type === "resDelMeta" && qs.req.type === "reqDelMeta"; +export function MsgIsResDelMeta(qs: MsgBase): qs is ResDelMeta { + return qs.type === "resDelMeta"; } diff --git a/src/cloud/msg-types.ts b/src/cloud/msg-types.ts index b1bfc5b8..43664e83 100644 --- a/src/cloud/msg-types.ts +++ b/src/cloud/msg-types.ts @@ -9,6 +9,7 @@ export type MsgWithError = T | ErrorMsg; export interface RequestOpts { readonly waitFor: (msg: MsgBase) => boolean; + readonly pollInterval?: number; // 1000ms readonly timeout?: number; // ms } @@ -73,6 +74,10 @@ export interface MsgBase { readonly auth?: AuthType; } +export function MsgIsTid(msg: MsgBase, tid: string): boolean { + return msg.tid === tid; +} + export type MsgWithConn = T & { readonly conn: QSId }; export type MsgWithOptionalConn = T & { readonly conn?: QSId }; @@ -421,27 +426,27 @@ export type ReqRes = Readonly = { - reqGetData: { store: "data", resType: "resGetData" }, - reqPutData: { store: "data", resType: "resPutData" }, - reqDelData: { store: "data", resType: "resDelData" }, - reqGetWAL: { store: "wal", resType: "resGetWAL" }, - reqPutWAL: { store: "wal", resType: "resPutWAL" }, - reqDelWAL: { store: "wal", resType: "resDelWAL" }, -}; - -export function getStoreFromType(req: MsgBase): StoreAndType { - return ( - reqToRes[req.type] || - (() => { - throw new Error(`unknown req.type=${req.type}`); - })() - ); -} +// interface StoreAndType { +// readonly store: FPStoreTypes; +// readonly resType: string; +// } +// const reqToRes: Record = { +// reqGetData: { store: "data", resType: "resGetData" }, +// reqPutData: { store: "data", resType: "resPutData" }, +// reqDelData: { store: "data", resType: "resDelData" }, +// reqGetWAL: { store: "wal", resType: "resGetWAL" }, +// reqPutWAL: { store: "wal", resType: "resPutWAL" }, +// reqDelWAL: { store: "wal", resType: "resDelWAL" }, +// }; + +// export function getStoreFromType(req: MsgBase): StoreAndType { +// return ( +// reqToRes[req.type] || +// (() => { +// throw new Error(`unknown req.type=${req.type}`); +// })() +// ); +// } // export function buildResSignedUrl(req: ReqSignedUrl, signedUrl: string): ResSignedUrl { // return { @@ -490,10 +495,17 @@ export interface ReqSignedUrl extends MsgWithTenantLedger { } export interface GwCtx { + readonly tid?: string; readonly conn?: QSId; readonly tenant: TenantLedger; } +export interface GwCtxConn { + readonly tid?: string; + readonly conn: QSId; + readonly tenant: TenantLedger; +} + export function buildReqSignedUrl( sthis: NextId, type: string, @@ -515,6 +527,12 @@ export interface ResSignedUrl extends MsgWithTenantLedger { readonly signedUrl: string; } +export interface ResOptionalSignedUrl extends MsgWithTenantLedger { + // readonly type: "resSignedUrl"; + readonly params: SignedUrlParam; + readonly signedUrl?: string; +} + export async function buildRes>, S extends ResSignedUrl>( method: SignedUrlParam["method"], store: FPStoreTypes, diff --git a/src/cloud/msger.ts b/src/cloud/msger.ts index 5e08876a..d6ea4da2 100644 --- a/src/cloud/msger.ts +++ b/src/cloud/msger.ts @@ -7,7 +7,6 @@ import { MsgBase, MsgerParams, MsgIsResGestalt, - ReqGestalt, RequestOpts, ResGestalt, MsgWithError, @@ -18,6 +17,8 @@ import { MsgIsResOpen, MsgWithOptionalConn, QSId, + MsgIsTid, + ReqGestalt, } from "./msg-types.js"; import { SuperThis } from "@fireproof/core"; import { HttpConnection } from "./http-connection.js"; @@ -54,13 +55,25 @@ export interface ExchangedGestalt { export type OnErrorFn = (msg: Partial, err: Error) => Partial; +export interface ActiveStream { + readonly id: string; + readonly bind: { + readonly msg: Q; + readonly opts: RequestOpts; + }; + timeout?: unknown; + controller?: ReadableStreamDefaultController>; +} + export interface MsgRawConnection { // readonly ws: WebSocket; // readonly params: ConnectionKey; // qsOpen: ReqRes; readonly sthis: SuperThis; readonly exchangedGestalt: ExchangedGestalt; - request(req: Q, opts: RequestOpts): Promise>; + readonly activeBinds: Map>; + bind(req: Q, opts: RequestOpts): ReadableStream>; + request(req: Q, opts: RequestOpts): Promise>; start(): Promise>; close(): Promise>; onMsg(msg: OnMsgFn): UnReg; @@ -124,14 +137,40 @@ export class MsgConnected implements MsgRawConnection { readonly conn: QSId; readonly raw: MsgRawConnection; readonly exchangedGestalt: ExchangedGestalt; + readonly activeBinds: Map>; private constructor(raw: MsgRawConnection, conn: QSId) { this.sthis = raw.sthis; this.raw = raw; this.exchangedGestalt = raw.exchangedGestalt; this.conn = conn; + this.activeBinds = raw.activeBinds; + } + + bind( + req: Q, + opts: RequestOpts + ): ReadableStream> { + const stream = this.raw.bind({ ...req, conn: req.conn || this.conn }, opts); + const ts = new TransformStream, MsgWithError>({ + transform: (chunk, controller) => { + if (!MsgIsTid(chunk, req.tid)) { + return; + } + if (MsgIsConnected(chunk, this.conn)) { + if ((opts.waitFor && opts.waitFor(chunk)) || MsgIsError(chunk)) { + controller.enqueue(chunk); + } + } + }, + }); + // eslint-disable-next-line no-console + // why the hell pipeTo sends an error that is undefined? + stream.pipeThrough(ts); + // stream.pipeTo(ts.writable).catch((err) => err && err.message && console.error("bind error", err)); + return ts.readable; } - request(req: Q, opts: RequestOpts): Promise> { + request(req: Q, opts: RequestOpts): Promise> { return this.raw.request({ ...req, conn: req.conn || this.conn }, opts); } start(): Promise> { @@ -196,7 +235,7 @@ export class Msger { return rHC; } const hc = rHC.Ok(); - const resGestalt = await hc.request(buildReqGestalt(sthis, gs), { + const resGestalt = await hc.request(buildReqGestalt(sthis, gs), { waitFor: MsgIsResGestalt, }); if (!MsgIsResGestalt(resGestalt)) { diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 2c4dedfc..66a8472f 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -1,10 +1,11 @@ import { UpgradeWebSocket, WSEvents } from "hono/ws"; -import { ConnMiddleware, CORS, HonoServerBase, HonoServerFactory, RunTimeParams } from "./hono-server.js"; +import { ConnMiddleware, HonoServerBase, HonoServerFactory, HonoServerImpl, RunTimeParams } from "./hono-server.js"; import { HttpHeader, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; import { ensureLogger, SuperThis } from "@fireproof/core"; import { defaultMsgParams, jsonEnDe } from "./msger.js"; import { defaultGestalt, Gestalt, MsgerParams } from "./msg-types.js"; +import { SQLDatabase } from "./meta-merger/abstract-sql.js"; interface ServerType { close(fn: () => void): void; @@ -15,6 +16,7 @@ type serveFn = (options: unknown, listeningListener?: ((info: unknown) => void) export interface NodeHonoFactoryParams { readonly msgP?: MsgerParams; readonly gs?: Gestalt; + readonly sql: SQLDatabase; } export class NodeHonoFactory implements HonoServerFactory { @@ -26,7 +28,7 @@ export class NodeHonoFactory implements HonoServerFactory { readonly sthis: SuperThis; readonly params: NodeHonoFactoryParams; - constructor(sthis: SuperThis, params: NodeHonoFactoryParams = {}) { + constructor(sthis: SuperThis, params: NodeHonoFactoryParams) { this.sthis = sthis; this.params = params; } @@ -51,9 +53,8 @@ export class NodeHonoFactory implements HonoServerFactory { defaultGestalt(msgP, { id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - - // this.sthis.env. - return fn({ sthis, logger, ende, impl: new NodeHonoServer(sthis, this, gs) }); + const nhs = new NodeHonoServer(sthis, this, gs, this.params.sql); + return nhs.start().then((nhs) => fn({ sthis, logger, ende, impl: nhs })); } async start(app: Hono): Promise { @@ -85,16 +86,14 @@ export class NodeHonoFactory implements HonoServerFactory { } } -export class NodeHonoServer extends HonoServerBase { - readonly headers: HttpHeader; +export class NodeHonoServer extends HonoServerBase implements HonoServerImpl { readonly _upgradeWebSocket: UpgradeWebSocket; - constructor(sthis: SuperThis, factory: NodeHonoFactory, gs: Gestalt, headers?: HttpHeader) { - super(sthis, sthis.logger, gs); - this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); + constructor(sthis: SuperThis, factory: NodeHonoFactory, gs: Gestalt, sqldb: SQLDatabase, headers?: HttpHeader) { + super(sthis, sthis.logger, gs, sqldb, headers); this._upgradeWebSocket = factory._upgradeWebSocket; } - upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { + override upgradeWebSocket(createEvents: (c: Context) => WSEvents | Promise): ConnMiddleware { return async (_conn, c, next) => { // conn.attachWSPair({ client: c.req, server: c.res }); return this._upgradeWebSocket(createEvents)(c, next); diff --git a/src/cloud/pre-signed-url.ts b/src/cloud/pre-signed-url.ts index b8deca6d..a5f25de7 100644 --- a/src/cloud/pre-signed-url.ts +++ b/src/cloud/pre-signed-url.ts @@ -4,7 +4,6 @@ import { MsgWithConn, MsgWithTenantLedger, SignedUrlParam } from "./msg-types.js export interface PreSignedMsg extends MsgWithTenantLedger { readonly params: SignedUrlParam; - readonly tid: string; } // export interface PreSignedConnMsg { diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts index b05094a5..682944cd 100644 --- a/src/cloud/test-helper.ts +++ b/src/cloud/test-helper.ts @@ -18,6 +18,7 @@ import { Env } from "./backend/env.js"; import { HonoServer } from "./hono-server.js"; import { NodeHonoFactory } from "./node-hono-server.js"; import { CFHonoFactory } from "./backend/cf-hono-server.js"; +import { BetterSQLDatabase } from "./meta-merger/bettersql-abstract-sql.js"; export function httpStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnDe, my: Gestalt) { const remote = defaultGestalt(defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: ["reqRes"] }), { @@ -166,7 +167,12 @@ export function NodeHonoServerFactory() { factory: async (sthis: SuperThis, msgP: MsgerParams, remoteGestalt: Gestalt, _port: number) => { const { env } = await resolveToml(); sthis.env.sets(env as unknown as Record); - return new HonoServer(new NodeHonoFactory(sthis, { msgP, gs: remoteGestalt })); + const nhf = new NodeHonoFactory(sthis, { + msgP, + gs: remoteGestalt, + sql: new BetterSQLDatabase("./dist/node-meta.sqlite"), + }); + return new HonoServer(nhf); }, }; } diff --git a/src/cloud/ws-connection.ts b/src/cloud/ws-connection.ts index 90d8aa72..5c29cfd7 100644 --- a/src/cloud/ws-connection.ts +++ b/src/cloud/ws-connection.ts @@ -1,7 +1,16 @@ import { exception2Result, Future, Logger, Result } from "@adviser/cement"; import { SuperThis, ensureLogger } from "@fireproof/core"; -import { MsgBase, MsgIsError, buildErrorMsg, ReqOpen, WaitForTid, MsgWithError, RequestOpts } from "./msg-types.js"; -import { ExchangedGestalt, MsgerParamsWithEnDe, MsgRawConnection, OnMsgFn, UnReg } from "./msger.js"; +import { + MsgBase, + MsgIsError, + buildErrorMsg, + ReqOpen, + WaitForTid, + MsgWithError, + RequestOpts, + MsgIsTid, +} from "./msg-types.js"; +import { ActiveStream, ExchangedGestalt, MsgerParamsWithEnDe, MsgRawConnection, OnMsgFn, UnReg } from "./msger.js"; import { MsgRawConnectionBase } from "./msg-raw-connection-base.js"; export interface WSReqOpen { @@ -124,13 +133,14 @@ export class WSConnection extends MsgRawConnectionBase implements MsgRawConnecti return msg; } - async sendMsg(msg: MsgBase): Promise { + sendMsg(msg: MsgBase): Promise { this.ws.send(this.msgP.ende.encode(msg)); + return Promise.resolve(); } - onMsg(fn: OnMsgFn): UnReg { + onMsg(fn: OnMsgFn): UnReg { const key = this.sthis.nextId().str; - this.#onMsg.set(key, fn); + this.#onMsg.set(key, fn as OnMsgFn); return () => this.#onMsg.delete(key); } @@ -140,6 +150,50 @@ export class WSConnection extends MsgRawConnectionBase implements MsgRawConnecti return () => this.#onClose.delete(key); } + readonly activeBinds = new Map>(); + bind(req: Q, opts: RequestOpts): ReadableStream> { + const state: ActiveStream = { + id: this.sthis.nextId().str, + bind: { + msg: req, + opts, + }, + // timeout: undefined, + // controller: undefined, + } satisfies ActiveStream; + this.activeBinds.set(state.id, state); + return new ReadableStream>({ + cancel: () => { + // clearTimeout(state.timeout as number); + this.activeBinds.delete(state.id); + }, + start: (controller) => { + this.onMsg((msg) => { + if (MsgIsError(msg)) { + controller.enqueue(msg); + return; + } + if (!MsgIsTid(msg, req.tid)) { + return; + } + if (opts.waitFor && opts.waitFor(msg)) { + controller.enqueue(msg); + } + }); + this.sendMsg(req); + const future = new Future(); + this.waitForTid.set(req.tid, { tid: req.tid, future, waitFor: opts.waitFor, timeout: opts.timeout }); + future.asPromise().then((msg) => { + if (MsgIsError(msg)) { + // double err emitting + controller.enqueue(msg); + controller.close(); + } + }); + }, + }); + } + async request(req: Q, opts: RequestOpts): Promise> { if (!this.opened) { return buildErrorMsg(this.sthis, this.logger, req, this.logger.Error().Msg("Connection not open").AsError()); From 47fa88e6221895c5bbb06603e2a66c8eb9c3ef60 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Wed, 8 Jan 2025 22:56:05 +0100 Subject: [PATCH 80/83] chore: implement sql driver for durable object --- src/cloud/backend/cf-dobj-abstract-sql.ts | 251 +++++++++ src/cloud/backend/cf-hono-server.ts | 28 +- src/cloud/backend/env.d.ts | 17 +- src/cloud/backend/server.ts | 462 ++++++++-------- src/cloud/backend/wrangler.toml | 102 +++- src/cloud/client/cloud-gateway.test.ts | 2 +- src/cloud/connection.test.ts | 519 +++++++++--------- .../meta-merger/bettersql-abstract-sql.ts | 8 +- .../meta-merger/cf-worker-abstract-sql.ts | 2 +- .../meta-merger/meta-by-tenant-ledger.ts | 15 +- src/cloud/meta-merger/meta-merger.test.ts | 50 +- src/cloud/meta-merger/tenant-ledger.ts | 1 - src/cloud/test-helper.ts | 16 +- vitest.cf-worker.config.ts | 4 +- 14 files changed, 937 insertions(+), 540 deletions(-) create mode 100644 src/cloud/backend/cf-dobj-abstract-sql.ts diff --git a/src/cloud/backend/cf-dobj-abstract-sql.ts b/src/cloud/backend/cf-dobj-abstract-sql.ts new file mode 100644 index 00000000..5f0493d3 --- /dev/null +++ b/src/cloud/backend/cf-dobj-abstract-sql.ts @@ -0,0 +1,251 @@ +// import { DurableObject } from "cloudflare:workers"; +import { SQLDatabase, SQLParams, SQLStatement } from "../meta-merger/abstract-sql.js"; +// import { Env } from "./env.js"; +import { ExecSQLResult, FPDurableObject } from "./server.js"; + +export class CFDObjSQLStatement implements SQLStatement { + readonly sql: string; + readonly db: CFDObjSQLDatabase; + constructor(db: CFDObjSQLDatabase, sql: string) { + this.db = db; + this.sql = sql; + } + async run(...params: SQLParams): Promise { + const res = (await this.db.dobj.execSql(this.sql, params)) as ExecSQLResult; + return res.rawResults[0] as T; + } + async all(...params: SQLParams): Promise { + const res = (await this.db.dobj.execSql(this.sql, params)) as ExecSQLResult; + return res.rawResults as T[]; + } +} + +export class CFDObjSQLDatabase implements SQLDatabase { + readonly dobj: DurableObjectStub; + constructor(dobj: DurableObjectStub) { + this.dobj = dobj; + } + prepare(sql: string): SQLStatement { + return new CFDObjSQLStatement(this, sql); + } +} + +// export class FPDurableObject extends DurableObject { +// // readonly sessions: Map = new Map(); +// // readonly lastMetaByTendant = new Map[]>(); +// // readonly wsEvents: WSEvents = {}; + +// // injectWSEvents(wsEvents: WSEvents): void { +// // Object.assign(this.wsEvents, wsEvents); +// // } +// // getSQLDatabase(): SQLDatabase { +// // return this._cfDObjSQLDatabase; +// // } + +// async execSql(sql: string, params: unknown[]): Promise { +// console.log("execSql", sql, params); +// const stmt = await this.ctx.storage.sql.exec(sql, params); +// return stmt; +// } + +// // webSocketError(_ws: WebSocket, error: unknown): void | Promise { +// // this.logger.Error().Any("error", error).Msg("webSocketError"); +// // this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); +// // } + +// // async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { +// // this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); +// // if (typeof msg !== "string") { +// // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); +// // return; +// // } + +// // return CFMsgProcessor.dispatch( +// // () => JSON.parse(msg.toString()), +// // { env: this.env }, +// // async (req: MsgBase, ictx: CFCtxBase) => { +// // if (req.auth) { +// // // do ucan magic +// // } +// // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; +// // group = { +// // ...group, +// // qs: { +// // ...group.qs, +// // q: { +// // ...group.qs.q, +// // [req.type]: { +// // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, +// // }, +// // }, +// // }, +// // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), +// // lastUsed: new Date(), +// // } satisfies FPMetaGroup; +// // ws.serializeAttachment(group); +// // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; +// // return { req, ctx }; +// // } +// // ).then((qs) => { +// // let group = { +// // ...qs.ctx.group, +// // qs: { +// // ...qs.ctx.group.qs, +// // s: { +// // ...qs.ctx.group.qs.s, +// // [qs.req.type]: { +// // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, +// // }, +// // }, +// // }, +// // } satisfies FPMetaGroup; +// // switch (true) { +// // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): +// // { +// // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; +// // ws.serializeAttachment(group); +// // // console.log("putMeta group", group); +// // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( +// // buildUpdateMetaEvent(qs, { +// // connId: qs.res.connId, +// // subscriberId: "later-overriden", +// // }) +// // ); +// // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); +// // } +// // break; +// // case MsgIsResSubscribeMeta(qs): +// // { +// // group = { ...group, group: qs.res } satisfies FPMetaGroup; +// // // console.log("subscribeMeta group", group); +// // ws.serializeAttachment(group); +// // this.updateMeta({ +// // connId: qs.res.connId, +// // subscriberId: "later-overriden", +// // tid: qs.res.tid, +// // type: "updateMeta", +// // key: qs.res.key, +// // metaId: "later-overriden", +// // metas: [], +// // version: qs.res.version, +// // }); +// // } +// // break; +// // } +// // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); +// // ws.send(JSON.stringify(qs.res)); +// // }); +// // } + +// // async fetch(_req: Request): Promise { +// // const { 0: fromClient, 1: toClient } = new WebSocketPair(); +// // this.ctx.acceptWebSocket(toClient); +// // // this.logger.Debug().Msg("fetch"); +// // this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); +// // return new Response(null, { +// // status: 101, +// // webSocket: fromClient, +// // }); + +// // // const path = URI.from(req.url).pathname; +// // // switch (path) { +// // // case "/fp": { +// // // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); +// // // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); +// // // } +// // // case "/ws": { +// // // const upgradeHeader = req.headers.get("Upgrade"); +// // // if (!upgradeHeader || upgradeHeader !== "websocket") { +// // // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); +// // // } +// // // const { 0: fromClient, 1: toClient } = new WebSocketPair(); +// // // this.ctx.acceptWebSocket(toClient); +// // // // this.logger.Debug().Msg("fetch"); +// // // return new Response(null, { +// // // status: 101, +// // // webSocket: fromClient, +// // // }); +// // // } +// // // default: { +// // // const logger = ensureLogger(this.env); +// // // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); +// // // } +// // // } +// // // return new Response("Not implemented", { status: 501 }); +// // } + +// // webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { +// // try { +// // // if (typeof this.env.WS_EVENTS.onClose === "function") { +// // this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); +// // // } +// // ws.close(code, reason); +// // // eslint-disable-next-line @typescript-eslint/no-unused-vars +// // } catch (e) { +// // // ignore +// // } finally { +// // this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); +// // } +// // } + +// // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { +// // const wsSocks = ctx.dobj.getWebSockets(); +// // const groupWs = wsSocks.map((ws) => ({ +// // ws, +// // group: ws.deserializeAttachment() as FPMetaGroup, +// // })); +// // const joinedMeta = groupWs.reduce((acc, { group }) => { +// // if (group && group.lastMeta) { +// // acc.push(...group.lastMeta.metas); +// // } +// // return acc +// // }, [] as CRDTEntry[]) +// // const now = new Date() +// // const joinedQS = { +// // req: { ...qs.req, metas: joinedMeta }, +// // res: qs.res, +// // } +// // return acc; +// // }, [] as CRDTEntry[]); +// // if (joinedMeta.length === 0) { +// // return []; +// // } +// // const now = new Date(); +// // const joinedUp = { +// // ...up, +// // metas: joinedMeta, +// // }; +// // groupWs.forEach(({ ws, group }) => { +// // // console.log("group->", group); +// // // group = { +// // // ...group, +// // // msgSeq: (group ? group.msgSeq : 0) + 1, +// // // } +// // group = { +// // ...group, +// // qs: { +// // ...group.qs, +// // s: { +// // ...group.qs.s, +// // [up.type]: { +// // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, +// // }, +// // }, +// // }, +// // lastUsed: now, +// // } satisfies FPMetaGroup; +// // ws.serializeAttachment(group); +// // const toSend = { +// // ...joinedUp, +// // subscriberId: group.group.subscriberId, +// // connId: group.group.connId, +// // }; +// // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); +// // ws.send( +// // // this is not the best way to do this +// // JSON.stringify(toSend) +// // ); +// // }); +// // return joinedMeta; +// // } +// } diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index e7e89cee..0646d159 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -8,6 +8,9 @@ import { defaultMsgParams, jsonEnDe } from "../msger.js"; import { ensureLogger, ensureSuperThis, SuperThis } from "@fireproof/core"; import { SQLDatabase } from "../meta-merger/abstract-sql.js"; import { CFWorkerSQLDatabase } from "../meta-merger/cf-worker-abstract-sql.js"; +import { CFDObjSQLDatabase } from "./cf-dobj-abstract-sql.js"; +import { Env } from "./env.js"; +import { FPDurableObject } from "./server.js"; // function ensureLogger(env: Env, module = "Fireproof"): Logger { // const logger = new LoggerImpl() @@ -32,6 +35,15 @@ import { CFWorkerSQLDatabase } from "../meta-merger/cf-worker-abstract-sql.js"; const startedChs = new ResolveOnce(); +export function getDurableObject(env: Env) { + // console.log("getDurableObject", env); + const cfBackendKey = env.CF_BACKEND_KEY ?? "FP_DO"; + const rany = env as unknown as Record>; + const dObjNs = rany[cfBackendKey]; + const id = dObjNs.idFromName(env.FP_DO_ID ?? cfBackendKey); + return dObjNs.get(id); +} + export class CFHonoFactory implements HonoServerFactory { readonly _onClose: () => void; constructor( @@ -61,7 +73,21 @@ export class CFHonoFactory implements HonoServerFactory { }); const ret = startedChs .once(async () => { - const db = new CFWorkerSQLDatabase(c.env.DB); + const cfBackendMode = + c.env.CF_BACKEND_MODE && c.env.CF_BACKEND_MODE === "DURABLE_OBJECT" ? "DURABLE_OBJECT" : "D1"; + let db: SQLDatabase; + switch (cfBackendMode) { + case "DURABLE_OBJECT": + db = new CFDObjSQLDatabase(getDurableObject(c.env)); + break; + case "D1": + default: + { + const cfBackendKey = c.env.CF_BACKEND_KEY ?? "FP_D1"; + db = new CFWorkerSQLDatabase(c.env[cfBackendKey] as D1Database); + } + break; + } const chs = new CFHonoServer(sthis, logger, ende, gs, db); await chs.start(); return chs; diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index 4c5bca7b..b6333a38 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -2,8 +2,8 @@ // by running `wrangler types` import type { DurableObjectNamespace } from "@cloudflare/workers-types"; -import { FPMetaGroups } from "./fp-meta-groups.js"; -import { WSEvents } from "hono/ws"; +// import { WSEvents } from "hono/ws"; +import { FPDurableObject } from "./server.ts"; export interface Env { // bucket: R2Bucket; @@ -31,11 +31,18 @@ export interface Env { /** Maximum idle time in seconds before connection timeout. Optional. */ MAX_IDLE_TIME?: string; - FP_META_GROUPS: DurableObjectNamespace; + // default D1 + CF_BACKEND_MODE: "D1" | "DURABLE_OBJECT"; + // default D1 "FP_D1" + // default DURABLE_OBJECT "FP_DO" + CF_BACKEND_KEY?: string; - DB: D1Database; + FP_DO: DurableObjectNamespace; + // default CF_BACKEND_KEY + FP_DO_ID: string; + FP_D1: D1Database; - WS_EVENTS: WSEvents; + // WS_EVENTS: WSEvents; } // declare module "cloudflare:test" { diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index a8fb40b1..20a402ff 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -1,12 +1,13 @@ // / -import { Logger } from "@adviser/cement"; +// import { Logger } from "@adviser/cement"; // import { Hono } from "hono"; import { DurableObject } from "cloudflare:workers"; import { HonoServer } from "../hono-server.js"; import { Hono } from "hono"; import { Env } from "./env.js"; import { CFHonoFactory } from "./cf-hono-server.js"; -import { WSContext, WSEvents } from "hono/ws"; +// import { SQLDatabase, SQLStatement } from "../meta-merger/abstract-sql.js"; +// import { WSContext, WSEvents } from "hono/ws"; // function json(data: T, status = 200) { // return Response.json(data, { status, headers: CORS }); @@ -43,231 +44,6 @@ import { WSContext, WSEvents } from "hono/ws"; // // const sthis = new NextIdImpl(); -export class FPMetaGroups extends DurableObject { - // readonly sessions: Map = new Map(); - // readonly lastMetaByTendant = new Map[]>(); - - logger!: Logger; - - readonly wsEvents: WSEvents = {}; - - // constructor(ctx: DurableObjectState, env: Env) { - // super(ctx, env); - // // this.logger = ensureLogger(env, "FPMetaGroups"); - // // this.ctx.getWebSockets().forEach((webSocket) => { - // // const fpMetaGroup = webSocket.deserializeAttachment() as FPMetaGroup; - // // if (MsgIsResSubscribeMeta(fpMetaGroup.group)) { - // // this.sessions.set(webSocket, fpMetaGroup); - // // } - // // }); - // } - - // injectWSEvents(wsEvents: WSEvents): void { - // Object.assign(this.wsEvents, wsEvents); - // } - - webSocketError(_ws: WebSocket, error: unknown): void | Promise { - this.logger.Error().Any("error", error).Msg("webSocketError"); - this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); - } - - async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { - this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); - // if (typeof msg !== "string") { - // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); - // return; - // } - - // return CFMsgProcessor.dispatch( - // () => JSON.parse(msg.toString()), - // { env: this.env }, - // async (req: MsgBase, ictx: CFCtxBase) => { - // if (req.auth) { - // // do ucan magic - // } - // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; - // group = { - // ...group, - // qs: { - // ...group.qs, - // q: { - // ...group.qs.q, - // [req.type]: { - // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, - // }, - // }, - // }, - // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), - // lastUsed: new Date(), - // } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; - // return { req, ctx }; - // } - // ).then((qs) => { - // let group = { - // ...qs.ctx.group, - // qs: { - // ...qs.ctx.group.qs, - // s: { - // ...qs.ctx.group.qs.s, - // [qs.req.type]: { - // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, - // }, - // }, - // }, - // } satisfies FPMetaGroup; - // switch (true) { - // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): - // { - // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // // console.log("putMeta group", group); - // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( - // buildUpdateMetaEvent(qs, { - // connId: qs.res.connId, - // subscriberId: "later-overriden", - // }) - // ); - // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); - // } - // break; - // case MsgIsResSubscribeMeta(qs): - // { - // group = { ...group, group: qs.res } satisfies FPMetaGroup; - // // console.log("subscribeMeta group", group); - // ws.serializeAttachment(group); - // this.updateMeta({ - // connId: qs.res.connId, - // subscriberId: "later-overriden", - // tid: qs.res.tid, - // type: "updateMeta", - // key: qs.res.key, - // metaId: "later-overriden", - // metas: [], - // version: qs.res.version, - // }); - // } - // break; - // } - // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); - // ws.send(JSON.stringify(qs.res)); - // }); - } - - async fetch(_req: Request): Promise { - const { 0: fromClient, 1: toClient } = new WebSocketPair(); - this.ctx.acceptWebSocket(toClient); - // this.logger.Debug().Msg("fetch"); - this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); - return new Response(null, { - status: 101, - webSocket: fromClient, - }); - - // const path = URI.from(req.url).pathname; - // switch (path) { - // case "/fp": { - // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); - // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); - // } - // case "/ws": { - // const upgradeHeader = req.headers.get("Upgrade"); - // if (!upgradeHeader || upgradeHeader !== "websocket") { - // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); - // } - // const { 0: fromClient, 1: toClient } = new WebSocketPair(); - // this.ctx.acceptWebSocket(toClient); - // // this.logger.Debug().Msg("fetch"); - // return new Response(null, { - // status: 101, - // webSocket: fromClient, - // }); - // } - // default: { - // const logger = ensureLogger(this.env); - // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); - // } - // } - // return new Response("Not implemented", { status: 501 }); - } - - webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { - try { - // if (typeof this.env.WS_EVENTS.onClose === "function") { - this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); - // } - ws.close(code, reason); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - } catch (e) { - // ignore - } finally { - this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); - } - } - - // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { - // const wsSocks = ctx.dobj.getWebSockets(); - // const groupWs = wsSocks.map((ws) => ({ - // ws, - // group: ws.deserializeAttachment() as FPMetaGroup, - // })); - // const joinedMeta = groupWs.reduce((acc, { group }) => { - // if (group && group.lastMeta) { - // acc.push(...group.lastMeta.metas); - // } - // return acc - // }, [] as CRDTEntry[]) - // const now = new Date() - // const joinedQS = { - // req: { ...qs.req, metas: joinedMeta }, - // res: qs.res, - // } - // return acc; - // }, [] as CRDTEntry[]); - // if (joinedMeta.length === 0) { - // return []; - // } - // const now = new Date(); - // const joinedUp = { - // ...up, - // metas: joinedMeta, - // }; - // groupWs.forEach(({ ws, group }) => { - // // console.log("group->", group); - // // group = { - // // ...group, - // // msgSeq: (group ? group.msgSeq : 0) + 1, - // // } - // group = { - // ...group, - // qs: { - // ...group.qs, - // s: { - // ...group.qs.s, - // [up.type]: { - // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, - // }, - // }, - // }, - // lastUsed: now, - // } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // const toSend = { - // ...joinedUp, - // subscriberId: group.group.subscriberId, - // connId: group.group.connId, - // }; - // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); - // ws.send( - // // this is not the best way to do this - // JSON.stringify(toSend) - // ); - // }); - // return joinedMeta; - // } -} - // // const app = new Hono<{ Bindings: Env }>(); // interface CFCtxBaseParam { @@ -397,3 +173,235 @@ export default { }, } satisfies ExportedHandler; */ + +export interface ExecSQLResult { + readonly rowsRead: number; + readonly rowsWritten: number; + readonly rawResults: unknown[]; +} + +export class FPDurableObject extends DurableObject { + // readonly sessions: Map = new Map(); + // readonly lastMetaByTendant = new Map[]>(); + // readonly wsEvents: WSEvents = {}; + + // injectWSEvents(wsEvents: WSEvents): void { + // Object.assign(this.wsEvents, wsEvents); + // } + // getSQLDatabase(): SQLDatabase { + // return this._cfDObjSQLDatabase; + // } + + async execSql(sql: string, params: unknown[]): Promise { + const cursor = await this.ctx.storage.sql.exec(sql, ...params); + const rawResults = cursor.toArray(); + const res = { + rowsRead: cursor.rowsRead, + rowsWritten: cursor.rowsWritten, + rawResults, + }; + // console.log("execSql", sql, params, res); + return res; + } + + // webSocketError(_ws: WebSocket, error: unknown): void | Promise { + // this.logger.Error().Any("error", error).Msg("webSocketError"); + // this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); + // } + + // async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { + // this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); + // if (typeof msg !== "string") { + // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); + // return; + // } + + // return CFMsgProcessor.dispatch( + // () => JSON.parse(msg.toString()), + // { env: this.env }, + // async (req: MsgBase, ictx: CFCtxBase) => { + // if (req.auth) { + // // do ucan magic + // } + // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; + // group = { + // ...group, + // qs: { + // ...group.qs, + // q: { + // ...group.qs.q, + // [req.type]: { + // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, + // }, + // }, + // }, + // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), + // lastUsed: new Date(), + // } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; + // return { req, ctx }; + // } + // ).then((qs) => { + // let group = { + // ...qs.ctx.group, + // qs: { + // ...qs.ctx.group.qs, + // s: { + // ...qs.ctx.group.qs.s, + // [qs.req.type]: { + // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, + // }, + // }, + // }, + // } satisfies FPMetaGroup; + // switch (true) { + // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): + // { + // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // // console.log("putMeta group", group); + // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( + // buildUpdateMetaEvent(qs, { + // connId: qs.res.connId, + // subscriberId: "later-overriden", + // }) + // ); + // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); + // } + // break; + // case MsgIsResSubscribeMeta(qs): + // { + // group = { ...group, group: qs.res } satisfies FPMetaGroup; + // // console.log("subscribeMeta group", group); + // ws.serializeAttachment(group); + // this.updateMeta({ + // connId: qs.res.connId, + // subscriberId: "later-overriden", + // tid: qs.res.tid, + // type: "updateMeta", + // key: qs.res.key, + // metaId: "later-overriden", + // metas: [], + // version: qs.res.version, + // }); + // } + // break; + // } + // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); + // ws.send(JSON.stringify(qs.res)); + // }); + // } + + // async fetch(_req: Request): Promise { + // const { 0: fromClient, 1: toClient } = new WebSocketPair(); + // this.ctx.acceptWebSocket(toClient); + // // this.logger.Debug().Msg("fetch"); + // this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); + // return new Response(null, { + // status: 101, + // webSocket: fromClient, + // }); + + // // const path = URI.from(req.url).pathname; + // // switch (path) { + // // case "/fp": { + // // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); + // // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); + // // } + // // case "/ws": { + // // const upgradeHeader = req.headers.get("Upgrade"); + // // if (!upgradeHeader || upgradeHeader !== "websocket") { + // // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); + // // } + // // const { 0: fromClient, 1: toClient } = new WebSocketPair(); + // // this.ctx.acceptWebSocket(toClient); + // // // this.logger.Debug().Msg("fetch"); + // // return new Response(null, { + // // status: 101, + // // webSocket: fromClient, + // // }); + // // } + // // default: { + // // const logger = ensureLogger(this.env); + // // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); + // // } + // // } + // // return new Response("Not implemented", { status: 501 }); + // } + + // webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { + // try { + // // if (typeof this.env.WS_EVENTS.onClose === "function") { + // this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); + // // } + // ws.close(code, reason); + // // eslint-disable-next-line @typescript-eslint/no-unused-vars + // } catch (e) { + // // ignore + // } finally { + // this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); + // } + // } + + // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { + // const wsSocks = ctx.dobj.getWebSockets(); + // const groupWs = wsSocks.map((ws) => ({ + // ws, + // group: ws.deserializeAttachment() as FPMetaGroup, + // })); + // const joinedMeta = groupWs.reduce((acc, { group }) => { + // if (group && group.lastMeta) { + // acc.push(...group.lastMeta.metas); + // } + // return acc + // }, [] as CRDTEntry[]) + // const now = new Date() + // const joinedQS = { + // req: { ...qs.req, metas: joinedMeta }, + // res: qs.res, + // } + // return acc; + // }, [] as CRDTEntry[]); + // if (joinedMeta.length === 0) { + // return []; + // } + // const now = new Date(); + // const joinedUp = { + // ...up, + // metas: joinedMeta, + // }; + // groupWs.forEach(({ ws, group }) => { + // // console.log("group->", group); + // // group = { + // // ...group, + // // msgSeq: (group ? group.msgSeq : 0) + 1, + // // } + // group = { + // ...group, + // qs: { + // ...group.qs, + // s: { + // ...group.qs.s, + // [up.type]: { + // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, + // }, + // }, + // }, + // lastUsed: now, + // } satisfies FPMetaGroup; + // ws.serializeAttachment(group); + // const toSend = { + // ...joinedUp, + // subscriberId: group.group.subscriberId, + // connId: group.group.connId, + // }; + // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); + // ws.send( + // // this is not the best way to do this + // JSON.stringify(toSend) + // ); + // }); + // return joinedMeta; + // } +} diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index a4ad5341..3d230712 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -4,26 +4,78 @@ compatibility_date = "2024-04-19" compatibility_flags = ["nodejs_compat"] # upload_source_maps = true +# [durable_objects] +# bindings = [ +# { name = "FP_DO", class_name = "FPDurableObject"}, +# ] + +# [[d1_databases]] +# binding = "DB" +# database_name = "test-meta-merge" +# database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" + [durable_objects] bindings = [ - { name = "FP_META_GROUPS", class_name = "FPMetaGroups"}, + # { name = "FP_DO", class_name = "FPDurableObject", script_name = "cf-dobj-abstract-sql" } + { name = "FP_DO", class_name = "FPDurableObject" } ] -[[d1_databases]] -binding = "DB" -database_name = "test-meta-merge" -database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" - - [[migrations]] tag = "v1" # Should be unique for each entry -new_classes = ["FPMetaGroups"] +new_sqlite_classes = ["FPDurableObject"] [observability] enabled = true head_sampling_rate = 1 -[env.test-reqRes.vars] + +[env.test.vars] +VERSION = "FP-MSG-1.0" +STORAGE_URL = "http://localhost:9000/testbucket" +ACCESS_KEY_ID = "minioadmin" +SECRET_ACCESS_KEY = "minioadmin" +FP_DEBUG = "FPMetaGroups" +#FP_FORMAT = "yaml" +# TEST_DATE = "20241121T225359Z" +FP_PROTOCOL = "http" +CF_BACKEND_MODE = "DURABLE_OBJECT" + +# [env.test.services] +# bindings = [ +# { binding = "FP_DO", service = "FP_DO" } +# ] + +[[env.test.d1_databases]] +binding = "FP_D1" +database_name = "test-meta-merge" +database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" + +[[env.test.migrations]] +tag = "v1" # Should be unique for each entry +new_sqlite_classes = ["FPDurableObject"] + +[env.test.durable_objects] +bindings = [ + { name = "FP_DO", class_name = "FPDurableObject" }, +] + + +[env.test-reqRes-D1.vars] +VERSION = "FP-MSG-1.0" +STORAGE_URL = "http://localhost:9000/testbucket" +ACCESS_KEY_ID = "minioadmin" +SECRET_ACCESS_KEY = "minioadmin" +FP_DEBUG = "FPMetaGroups" +#FP_FORMAT = "yaml" +# TEST_DATE = "20241121T225359Z" +FP_PROTOCOL = "http" + +[[env.test-reqRes-D1.d1_databases]] +binding = "FP_D1" +database_name = "test-meta-merge" +database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" + +[env.test-reqRes-DO.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" @@ -32,19 +84,31 @@ FP_DEBUG = "FPMetaGroups" #FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" FP_PROTOCOL = "http" +CF_BACKEND_MODE = "DURABLE_OBJECT" -[env.test-reqRes.durable_objects] +[env.test-reqRes-DO.durable_objects] bindings = [ - { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, + { name = "FP_DO", class_name = "FPDurableObject" }, ] -[[env.test-reqRes.d1_databases]] -binding = "DB" +[env.test-stream-D1.vars] +VERSION = "FP-MSG-1.0" +STORAGE_URL = "http://localhost:9000/testbucket" +ACCESS_KEY_ID = "minioadmin" +SECRET_ACCESS_KEY = "minioadmin" +FP_DEBUG = "FPMetaGroups" +#FP_FORMAT = "yaml" +# TEST_DATE = "20241121T225359Z" +FP_PROTOCOL = "ws" + + +[[env.test-stream-D1.d1_databases]] +binding = "FP_D1" database_name = "test-meta-merge" database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" -[env.test-stream.vars] +[env.test-stream-DO.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" ACCESS_KEY_ID = "minioadmin" @@ -53,13 +117,11 @@ FP_DEBUG = "FPMetaGroups" #FP_FORMAT = "yaml" # TEST_DATE = "20241121T225359Z" FP_PROTOCOL = "ws" +CF_BACKEND_MODE = "DURABLE_OBJECT" -[env.test-stream.durable_objects] +[env.test-stream-D0.durable_objects] bindings = [ - { name = "FP_META_GROUPS", class_name = "FPMetaGroups" }, + { name = "FP_DO", class_name = "FPDurableObject" }, ] -[[env.test-stream.d1_databases]] -binding = "DB" -database_name = "test-meta-merge" -database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" \ No newline at end of file + diff --git a/src/cloud/client/cloud-gateway.test.ts b/src/cloud/client/cloud-gateway.test.ts index 589f6a2f..b30f07fe 100644 --- a/src/cloud/client/cloud-gateway.test.ts +++ b/src/cloud/client/cloud-gateway.test.ts @@ -11,7 +11,7 @@ const sthis = ensureSuperThis(); const msgP = defaultMsgParams(sthis, { hasPersistent: true }); const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); -describe.each([NodeHonoServerFactory(), CFHonoServerFactory()])("$name - Gateway", ({ factory }) => { +describe.each([NodeHonoServerFactory(), CFHonoServerFactory("D1")])("$name - Gateway", ({ factory }) => { const port = 1024 + Math.floor(Math.random() * (65536 - 1024)); const style = wsStyle(sthis, port, msgP, my); diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index 0c1f4535..f00ded4b 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -47,7 +47,7 @@ import { } from "./msg-type-meta.js"; async function refURL(sp: ResOptionalSignedUrl) { - const { env } = await resolveToml(); + const { env } = await resolveToml("D1"); return ( await calculatePreSignedUrl(sp, { storageUrl: URI.from(env.STORAGE_URL), @@ -70,290 +70,293 @@ describe("Connection", () => { const msgP = defaultMsgParams(sthis, { hasPersistent: true }); beforeAll(async () => { - sthis.env.sets((await resolveToml()).env as unknown as Record); + sthis.env.sets((await resolveToml("D1")).env as unknown as Record); }); - describe.each([NodeHonoServerFactory(), CFHonoServerFactory()])("$name - Connection", (honoServer) => { - const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); - const qOpen = buildReqOpen(sthis, { reqId: "req-open-test" }); - const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); - describe.each([httpStyle(sthis, port, msgP, my), wsStyle(sthis, port, msgP, my)])( - `${honoServer.name} - $name`, - (style) => { - let server: HonoServer; - beforeAll(async () => { - const app = new Hono(); - server = await honoServer - .factory(sthis, msgP, style.remoteGestalt, port) - .then((srv) => srv.register(app, port)); - }); - afterAll(async () => { - // console.log("closing server"); - await server.close(); - }); - it(`conn refused`, async () => { - const rC = await applyStart(style.connRefused.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/ECONNREFUSED/); - }); + describe.each([NodeHonoServerFactory(), CFHonoServerFactory("DO") /*, CFHonoServerFactory("DO")*/])( + "$name - Connection", + (honoServer) => { + const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); + const qOpen = buildReqOpen(sthis, { reqId: "req-open-test" }); + const my = defaultGestalt(msgP, { id: "FP-Universal-Client" }); + describe.each([httpStyle(sthis, port, msgP, my), wsStyle(sthis, port, msgP, my)])( + `${honoServer.name} - $name`, + (style) => { + let server: HonoServer; + beforeAll(async () => { + const app = new Hono(); + server = await honoServer + .factory(sthis, msgP, style.remoteGestalt, port) + .then((srv) => srv.register(app, port)); + }); + afterAll(async () => { + // console.log("closing server"); + await server.close(); + }); + it(`conn refused`, async () => { + const rC = await applyStart(style.connRefused.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/ECONNREFUSED/); + }); - it(`timeout`, async () => { - const rC = await applyStart(style.timeout.open()); - expect(rC.isErr()).toBeTruthy(); - expect(rC.Err().message).toMatch(/Timeout/i); - }); + it(`timeout`, async () => { + const rC = await applyStart(style.timeout.open()); + expect(rC.isErr()).toBeTruthy(); + expect(rC.Err().message).toMatch(/Timeout/i); + }); - describe(`connection`, () => { - let c: MsgConnected; - beforeEach(async () => { - const rC = await style.ok.open().then((r) => MsgConnected.connect(r, { reqId: "req-open-testx" })); - expect(rC.isOk()).toBeTruthy(); - c = rC.Ok(); - expect(c.conn).toEqual({ - reqId: "req-open-testx", - resId: c.conn.resId, + describe(`connection`, () => { + let c: MsgConnected; + beforeEach(async () => { + const rC = await style.ok.open().then((r) => MsgConnected.connect(r, { reqId: "req-open-testx" })); + expect(rC.isOk()).toBeTruthy(); + c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testx", + resId: c.conn.resId, + }); + }); + afterEach(async () => { + await c.close(); }); - }); - afterEach(async () => { - await c.close(); - }); - it("kaputt url http", async () => { - const r = await c.raw.request( - { - tid: "test", - type: "kaputt", - version: "FP-MSG-1.0", - }, - { waitFor: () => true } - ); - if (!MsgIsError(r)) { - assert.fail("expected MsgError"); - return; - } - expect(r).toEqual({ - message: "unexpected message", - tid: "test", - type: "error", - version: "FP-MSG-1.0", - src: { + it("kaputt url http", async () => { + const r = await c.raw.request( + { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + { waitFor: () => true } + ); + if (!MsgIsError(r)) { + assert.fail("expected MsgError"); + return; + } + expect(r).toEqual({ + message: "unexpected message", tid: "test", - type: "kaputt", + type: "error", version: "FP-MSG-1.0", - }, + src: { + tid: "test", + type: "kaputt", + version: "FP-MSG-1.0", + }, + }); + }); + it("gestalt url http", async () => { + const msgP = defaultMsgParams(sthis, {}); + const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); + const r = await c.raw.request(req, { waitFor: MsgIsResGestalt }); + if (!MsgIsResGestalt(r)) { + assert.fail("expected MsgError", JSON.stringify(r)); + } + expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); }); - }); - it("gestalt url http", async () => { - const msgP = defaultMsgParams(sthis, {}); - const req = buildReqGestalt(sthis, defaultGestalt(msgP, { id: "test" })); - const r = await c.raw.request(req, { waitFor: MsgIsResGestalt }); - if (!MsgIsResGestalt(r)) { - assert.fail("expected MsgError", JSON.stringify(r)); - } - expect(r.gestalt).toEqual(c.exchangedGestalt?.remote); - }); - it("openConnection", async () => { - const req = buildReqOpen(sthis, { ...c.conn }); - const r = await c.raw.request(req, { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(r)) { - assert.fail(JSON.stringify(r)); - } - expect(r).toEqual({ - conn: { ...c.conn, resId: r.conn?.resId }, - tid: req.tid, - type: "resOpen", - version: "FP-MSG-1.0", + it("openConnection", async () => { + const req = buildReqOpen(sthis, { ...c.conn }); + const r = await c.raw.request(req, { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(r)) { + assert.fail(JSON.stringify(r)); + } + expect(r).toEqual({ + conn: { ...c.conn, resId: r.conn?.resId }, + tid: req.tid, + type: "resOpen", + version: "FP-MSG-1.0", + }); }); }); - }); - it("open", async () => { - const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, { - reqId: "req-open-testy", - }); - expect(rC.isOk()).toBeTruthy(); - const c = rC.Ok(); - expect(c.conn).toEqual({ - reqId: "req-open-testy", - resId: c.conn.resId, - }); - expect(c.raw).toBeInstanceOf(style.cInstance); - expect(c.exchangedGestalt).toEqual({ - my, - remote: style.remoteGestalt, - }); - await c.close(); - }); - describe(`${honoServer.name} - Msgs`, () => { - let gwCtx: GwCtx; - let conn: MsgConnected; - beforeAll(async () => { - const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, qOpen.conn); + it("open", async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, { + reqId: "req-open-testy", + }); expect(rC.isOk()).toBeTruthy(); - conn = rC.Ok(); - gwCtx = { - conn: conn.conn, - tenant: { - tenant: "Tenant", - ledger: "Ledger", - }, - }; - }); - afterAll(async () => { - await conn.close(); - }); - it("Open", async () => { - const res = await conn.raw.request(buildReqOpen(sthis, conn.conn), { waitFor: MsgIsResOpen }); - if (!MsgIsResOpen(res)) { - assert.fail("expected MsgResOpen", JSON.stringify(res)); - } - expect(MsgIsResOpen(res)).toBeTruthy(); - expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn.resId }); + const c = rC.Ok(); + expect(c.conn).toEqual({ + reqId: "req-open-testy", + resId: c.conn.resId, + }); + expect(c.raw).toBeInstanceOf(style.cInstance); + expect(c.exchangedGestalt).toEqual({ + my, + remote: style.remoteGestalt, + }); + await c.close(); }); - - function sup() { - return { - path: "test/me", - key: "key-test", - } satisfies ReqSignedUrlParam; - } - describe("Data", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetData(sthis, sp, gwCtx), { waitFor: MsgIsResGetData }); - if (MsgIsResGetData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetData", JSON.stringify(res)); - } + describe(`${honoServer.name} - Msgs`, () => { + let gwCtx: GwCtx; + let conn: MsgConnected; + beforeAll(async () => { + const rC = await Msger.connect(sthis, URI.from(`http://localhost:${port}/fp`), msgP, qOpen.conn); + expect(rC.isOk()).toBeTruthy(); + conn = rC.Ok(); + gwCtx = { + conn: conn.conn, + tenant: { + tenant: "Tenant", + ledger: "Ledger", + }, + }; }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutData(sthis, sp, gwCtx), { waitFor: MsgIsResPutData }); - if (MsgIsResPutData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutData", JSON.stringify(res)); - } + afterAll(async () => { + await conn.close(); }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelData(sthis, sp, gwCtx), { waitFor: MsgIsResDelData }); - if (MsgIsResDelData(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelData", JSON.stringify(res)); + it("Open", async () => { + const res = await conn.raw.request(buildReqOpen(sthis, conn.conn), { waitFor: MsgIsResOpen }); + if (!MsgIsResOpen(res)) { + assert.fail("expected MsgResOpen", JSON.stringify(res)); } + expect(MsgIsResOpen(res)).toBeTruthy(); + expect(res.conn).toEqual({ ...qOpen.conn, resId: res.conn.resId }); }); - }); - describe("Meta", async () => { - it("bind stop", async () => { - const sp = sup(); - expect(conn.raw.activeBinds.size).toBe(0); - const streams: ReadableStream>[] = Array(5) - .fill(0) - .map(() => { - return conn.bind(buildBindGetMeta(sthis, sp, gwCtx), { - waitFor: MsgIsEventGetMeta, + function sup() { + return { + path: "test/me", + key: "key-test", + } satisfies ReqSignedUrlParam; + } + describe("Data", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetData(sthis, sp, gwCtx), { waitFor: MsgIsResGetData }); + if (MsgIsResGetData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetData", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutData(sthis, sp, gwCtx), { waitFor: MsgIsResPutData }); + if (MsgIsResPutData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutData", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelData(sthis, sp, gwCtx), { waitFor: MsgIsResDelData }); + if (MsgIsResDelData(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelData", JSON.stringify(res)); + } + }); + }); + + describe("Meta", async () => { + it("bind stop", async () => { + const sp = sup(); + expect(conn.raw.activeBinds.size).toBe(0); + const streams: ReadableStream>[] = Array(5) + .fill(0) + .map(() => { + return conn.bind(buildBindGetMeta(sthis, sp, gwCtx), { + waitFor: MsgIsEventGetMeta, + }); }); - }); - for await (const stream of streams) { - const reader = stream.getReader(); - while (true) { - const { done, value: msg } = await reader.read(); - if (done) { - break; + for await (const stream of streams) { + const reader = stream.getReader(); + while (true) { + const { done, value: msg } = await reader.read(); + if (done) { + break; + } + if (MsgIsEventGetMeta(msg)) { + // expect(msg.params).toEqual(sp); + expect(URI.from(msg.signedUrl).asObj()).toEqual(await refURL(msg)); + } else { + assert.fail("expected MsgEventGetMeta", JSON.stringify(msg)); + } + await reader.cancel(); } - if (MsgIsEventGetMeta(msg)) { - // expect(msg.params).toEqual(sp); - expect(URI.from(msg.signedUrl).asObj()).toEqual(await refURL(msg)); - } else { - assert.fail("expected MsgEventGetMeta", JSON.stringify(msg)); - } - await reader.cancel(); } - } - expect(conn.raw.activeBinds.size).toBe(0); - // await Promise.all(streams.map((s) => s.cancel())); - }); + expect(conn.raw.activeBinds.size).toBe(0); + // await Promise.all(streams.map((s) => s.cancel())); + }); - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildBindGetMeta(sthis, sp, gwCtx), { waitFor: MsgIsEventGetMeta }); - if (MsgIsEventGetMeta(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgIsEventGetMeta", JSON.stringify(res)); - } - }); - it("Put", async () => { - const sp = sup(); - const metas = Array(5) - .fill({ cid: "x", parents: [], data: "MomRkYXRho" }) - .map((data) => { - return { ...data, cid: sthis.timeOrderedNextId().str }; + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildBindGetMeta(sthis, sp, gwCtx), { waitFor: MsgIsEventGetMeta }); + if (MsgIsEventGetMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgIsEventGetMeta", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const metas = Array(5) + .fill({ cid: "x", parents: [], data: "MomRkYXRho" }) + .map((data) => { + return { ...data, cid: sthis.timeOrderedNextId().str }; + }); + const res = await conn.request(buildReqPutMeta(sthis, sp, metas, gwCtx), { waitFor: MsgIsResPutMeta }); + if (MsgIsResPutMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgIsResPutMeta", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelMeta(sthis, sp, gwCtx), { + waitFor: MsgIsResDelMeta, }); - const res = await conn.request(buildReqPutMeta(sthis, sp, metas, gwCtx), { waitFor: MsgIsResPutMeta }); - if (MsgIsResPutMeta(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgIsResPutMeta", JSON.stringify(res)); - } - }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelMeta(sthis, sp, gwCtx), { - waitFor: MsgIsResDelMeta, + if (MsgIsResDelMeta(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } }); - if (MsgIsResDelMeta(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelWAL", JSON.stringify(res)); - } - }); - }); - describe("WAL", async () => { - it("Get", async () => { - const sp = sup(); - const res = await conn.request(buildReqGetWAL(sthis, sp, gwCtx), { waitFor: MsgIsResGetWAL }); - if (MsgIsResGetWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResGetWAL", JSON.stringify(res)); - } }); - it("Put", async () => { - const sp = sup(); - const res = await conn.request(buildReqPutWAL(sthis, sp, gwCtx), { waitFor: MsgIsResPutWAL }); - if (MsgIsResPutWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResPutWAL", JSON.stringify(res)); - } - }); - it("Del", async () => { - const sp = sup(); - const res = await conn.request(buildReqDelWAL(sthis, sp, gwCtx), { waitFor: MsgIsResDelWAL }); - if (MsgIsResDelWAL(res)) { - // expect(res.params).toEqual(sp); - expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); - } else { - assert.fail("expected MsgResDelWAL", JSON.stringify(res)); - } + describe("WAL", async () => { + it("Get", async () => { + const sp = sup(); + const res = await conn.request(buildReqGetWAL(sthis, sp, gwCtx), { waitFor: MsgIsResGetWAL }); + if (MsgIsResGetWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResGetWAL", JSON.stringify(res)); + } + }); + it("Put", async () => { + const sp = sup(); + const res = await conn.request(buildReqPutWAL(sthis, sp, gwCtx), { waitFor: MsgIsResPutWAL }); + if (MsgIsResPutWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResPutWAL", JSON.stringify(res)); + } + }); + it("Del", async () => { + const sp = sup(); + const res = await conn.request(buildReqDelWAL(sthis, sp, gwCtx), { waitFor: MsgIsResDelWAL }); + if (MsgIsResDelWAL(res)) { + // expect(res.params).toEqual(sp); + expect(URI.from(res.signedUrl).asObj()).toEqual(await refURL(res)); + } else { + assert.fail("expected MsgResDelWAL", JSON.stringify(res)); + } + }); }); }); - }); - } - ); - }); + } + ); + } + ); }); diff --git a/src/cloud/meta-merger/bettersql-abstract-sql.ts b/src/cloud/meta-merger/bettersql-abstract-sql.ts index 68dc0a19..d583cb98 100644 --- a/src/cloud/meta-merger/bettersql-abstract-sql.ts +++ b/src/cloud/meta-merger/bettersql-abstract-sql.ts @@ -9,10 +9,14 @@ export class BetterSQLStatement implements SQLStatement { } async run(...iparams: SQLParams): Promise { - return this.stmt.run(...sqliteCoerceParams(iparams)) as T; + const res = (await this.stmt.run(...sqliteCoerceParams(iparams))) as T; + console.log("run", res); + return res; } async all(...params: SQLParams): Promise { - return this.stmt.all(...sqliteCoerceParams(params)) as T[]; + const res = (await this.stmt.all(...sqliteCoerceParams(params))) as T[]; + console.log("all", res); + return res; } } diff --git a/src/cloud/meta-merger/cf-worker-abstract-sql.ts b/src/cloud/meta-merger/cf-worker-abstract-sql.ts index 3f024357..f1cabf1e 100644 --- a/src/cloud/meta-merger/cf-worker-abstract-sql.ts +++ b/src/cloud/meta-merger/cf-worker-abstract-sql.ts @@ -10,7 +10,7 @@ export class CFWorkerSQLStatement implements SQLStatement { async run(...iparams: SQLParams): Promise { const bound = this.stmt.bind(...sqliteCoerceParams(iparams)); - console.log("cf-run", sqliteCoerceParams(iparams), bound); + // console.log("cf-run", sqliteCoerceParams(iparams), bound); return bound.run() as T; } async all(...params: SQLParams): Promise { diff --git a/src/cloud/meta-merger/meta-by-tenant-ledger.ts b/src/cloud/meta-merger/meta-by-tenant-ledger.ts index 0fd213f7..b8f0e94b 100644 --- a/src/cloud/meta-merger/meta-by-tenant-ledger.ts +++ b/src/cloud/meta-merger/meta-by-tenant-ledger.ts @@ -77,7 +77,9 @@ export class MetaByTenantLedgerSql { return this.#sqlInsertMetaByTenantLedger.once(() => { return this.db.prepare(` INSERT INTO MetaByTenantLedger(tenant, ledger, reqId, resId, metaCID, meta, updatedAt) - VALUES(?, ?, ?, ?, ?, ?, ?) + SELECT ?, ?, ?, ?, ?, ?, ? WHERE NOT EXISTS ( + SELECT 1 FROM MetaByTenantLedger WHERE metaCID = ? + ) `); }); } @@ -132,7 +134,16 @@ export class MetaByTenantLedgerSql { async ensure(t: MetaByTenantLedgerRow) { const stmt = this.sqlEnsureMetaByTenantLedger(); - return stmt.run(t.tenant, t.ledger, t.reqId, t.resId, t.metaCID, JSON.stringify(t.meta), t.updateAt.toISOString()); + return stmt.run( + t.tenant, + t.ledger, + t.reqId, + t.resId, + t.metaCID, + JSON.stringify(t.meta), + t.updateAt.toISOString(), + t.metaCID + ); } readonly #sqlSelectByConnection = new ResolveOnce(); diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index 9d9dffa9..4e0932eb 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -4,6 +4,7 @@ import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; import { runtimeFn } from "@adviser/cement"; import { SQLDatabase } from "./abstract-sql.js"; import type { Env } from "../backend/env.js"; +import { getDurableObject } from "../backend/cf-hono-server.js"; function sortCRDTEntries(rows: CRDTEntry[]) { return rows.sort((a, b) => a.cid.localeCompare(b.cid)); @@ -26,21 +27,47 @@ function toCRDTEntries(rows: MetaConnection[]) { // r.connection.conn.resId === connection.conn.resId))) // } -describe("MetaMerger", () => { - let db: SQLDatabase; +function getSQLFlavours(): { name: string; factory: () => Promise }[] { + if (runtimeFn().isCFWorker) { + return [ + { + name: "cf-worker-d1", + factory: async () => { + const { CFWorkerSQLDatabase } = await import("./cf-worker-abstract-sql.js"); + const { env } = await import("cloudflare:test"); + return new CFWorkerSQLDatabase((env as Env).FP_D1); + }, + }, + { + name: "cf-worker-do", + factory: async () => { + const { CFDObjSQLDatabase } = await import("../backend/cf-dobj-abstract-sql.js"); + const { env } = await import("cloudflare:test"); + return new CFDObjSQLDatabase(getDurableObject(env as Env)); + }, + }, + ]; + } else { + return [ + { + name: "bettersql", + factory: async () => { + const { BetterSQLDatabase } = await import("./bettersql-abstract-sql.js"); + return new BetterSQLDatabase("./dist/test.db"); + }, + }, + ]; + } +} + +describe.each(getSQLFlavours())("$name - MetaMerger", (flavour) => { + // let db: SQLDatabase; const sthis = ensureSuperThis(); const logger = sthis.logger; let mm: MetaMerger; beforeAll(async () => { // db = new Database(':memory:'); - if (runtimeFn().isCFWorker) { - const { CFWorkerSQLDatabase } = await import("./cf-worker-abstract-sql.js"); - const { env } = await import("cloudflare:test"); - db = new CFWorkerSQLDatabase((env as Env).DB); - } else { - const { BetterSQLDatabase } = await import("./bettersql-abstract-sql.js"); - db = new BetterSQLDatabase("./dist/test.db"); - } + const db = await flavour.factory(); mm = new MetaMerger(db); await mm.createSchema(); }); @@ -60,10 +87,9 @@ describe("MetaMerger", () => { }); afterEach(async () => { - mm.delMeta({ + await mm.delMeta({ logger, connection, - metas: [], }); }); diff --git a/src/cloud/meta-merger/tenant-ledger.ts b/src/cloud/meta-merger/tenant-ledger.ts index e3a8dc77..b5dc5fa7 100644 --- a/src/cloud/meta-merger/tenant-ledger.ts +++ b/src/cloud/meta-merger/tenant-ledger.ts @@ -56,7 +56,6 @@ export class TenantLedgerSql { async ensure(t: TenantLedgerRow) { await this.tenantSql.ensure({ tenant: t.tenant, createdAt: t.createdAt }); const stmt = this.sqlEnsureTenantLedger(); - console.log("ensure(->TenantLedgerRow)", t.tenant, t.ledger, t.createdAt); const ret = stmt.run(t.tenant, t.ledger, t.createdAt, t.tenant, t.ledger); return ret; } diff --git a/src/cloud/test-helper.ts b/src/cloud/test-helper.ts index 682944cd..144ff493 100644 --- a/src/cloud/test-helper.ts +++ b/src/cloud/test-helper.ts @@ -149,15 +149,15 @@ export function wsStyle(sthis: SuperThis, port: number, msgP: MsgerParamsWithEnD }; } -export async function resolveToml() { +export async function resolveToml(backend: "D1" | "DO") { const tomlFile = "src/cloud/backend/wrangler.toml"; const tomeStr = await fs.readFile(tomlFile, "utf-8"); const wranglerFile = toml.parse(tomeStr) as unknown as { - env: { "test-reqRes": { vars: Env } }; + env: Record; }; return { tomlFile, - env: wranglerFile.env["test-reqRes"].vars, + env: wranglerFile.env[`test-reqRes-${backend}`].vars, }; } @@ -165,7 +165,7 @@ export function NodeHonoServerFactory() { return { name: "NodeHonoServer", factory: async (sthis: SuperThis, msgP: MsgerParams, remoteGestalt: Gestalt, _port: number) => { - const { env } = await resolveToml(); + const { env } = await resolveToml("D1"); sthis.env.sets(env as unknown as Record); const nhf = new NodeHonoFactory(sthis, { msgP, @@ -176,17 +176,17 @@ export function NodeHonoServerFactory() { }, }; } -export function CFHonoServerFactory() { +export function CFHonoServerFactory(backend: "D1" | "DO") { return { - name: "CFHonoServer", + name: `CFHonoServer(${backend})`, factory: async (_sthis: SuperThis, _msgP: MsgerParams, remoteGestalt: Gestalt, port: number) => { if (process.env.FP_WRANGLER_PORT) { return new HonoServer(new CFHonoFactory()); } - const { tomlFile } = await resolveToml(); + const { tomlFile } = await resolveToml(backend); $.verbose = !!process.env.FP_DEBUG; const runningWrangler = $` - wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]} --no-show-interactive-dev-session & + wrangler dev -c ${tomlFile} --port ${port} --env test-${remoteGestalt.protocolCapabilities[0]}-${backend} --no-show-interactive-dev-session & waitPid=$! echo "PID:$waitPid" wait $waitPid`; diff --git a/vitest.cf-worker.config.ts b/vitest.cf-worker.config.ts index a32f73ca..de606e3f 100644 --- a/vitest.cf-worker.config.ts +++ b/vitest.cf-worker.config.ts @@ -2,11 +2,11 @@ import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config"; import tsconfigPaths from "vite-tsconfig-paths"; export default defineWorkersConfig({ - plugins: [tsconfigPaths()], + plugins: [tsconfigPaths() as Plugin], test: { poolOptions: { workers: { - wrangler: { configPath: "./src/cloud/backend/wrangler.toml" }, + wrangler: { configPath: "./src/cloud/backend/wrangler.toml", environment: "test" }, }, }, name: "cf-worker", From 47858a81773c737bf995fed16437c3fd04da45da Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 9 Jan 2025 10:42:49 +0100 Subject: [PATCH 81/83] chore: added WSRoom for ws broadcast to all connected sockets --- src/cloud/backend/cf-dobj-abstract-sql.ts | 6 +- src/cloud/backend/cf-hono-server.ts | 69 +++++++++++-------- src/cloud/backend/wrangler.toml | 2 +- src/cloud/connection.test.ts | 2 +- src/cloud/hono-server.ts | 5 +- .../meta-merger/bettersql-abstract-sql.ts | 4 +- src/cloud/node-hono-server.ts | 32 +++++++-- src/cloud/ws-room.ts | 3 + 8 files changed, 83 insertions(+), 40 deletions(-) create mode 100644 src/cloud/ws-room.ts diff --git a/src/cloud/backend/cf-dobj-abstract-sql.ts b/src/cloud/backend/cf-dobj-abstract-sql.ts index 5f0493d3..9f8a5ac9 100644 --- a/src/cloud/backend/cf-dobj-abstract-sql.ts +++ b/src/cloud/backend/cf-dobj-abstract-sql.ts @@ -1,5 +1,5 @@ // import { DurableObject } from "cloudflare:workers"; -import { SQLDatabase, SQLParams, SQLStatement } from "../meta-merger/abstract-sql.js"; +import { SQLDatabase, sqliteCoerceParams, SQLParams, SQLStatement } from "../meta-merger/abstract-sql.js"; // import { Env } from "./env.js"; import { ExecSQLResult, FPDurableObject } from "./server.js"; @@ -11,11 +11,11 @@ export class CFDObjSQLStatement implements SQLStatement { this.sql = sql; } async run(...params: SQLParams): Promise { - const res = (await this.db.dobj.execSql(this.sql, params)) as ExecSQLResult; + const res = (await this.db.dobj.execSql(this.sql, sqliteCoerceParams(params))) as ExecSQLResult; return res.rawResults[0] as T; } async all(...params: SQLParams): Promise { - const res = (await this.db.dobj.execSql(this.sql, params)) as ExecSQLResult; + const res = (await this.db.dobj.execSql(this.sql, sqliteCoerceParams(params))) as ExecSQLResult; return res.rawResults as T[]; } } diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index 0646d159..6fc3a6aa 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -1,4 +1,4 @@ -import { HttpHeader, Logger, LoggerImpl, ResolveOnce, URI } from "@adviser/cement"; +import { HttpHeader, KeyedResolvOnce, Logger, LoggerImpl, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; import { ConnMiddleware, HonoServerFactory, RunTimeParams, HonoServerBase } from "../hono-server.js"; import { WSContext, WSContextInit, WSEvents } from "hono/ws"; @@ -11,6 +11,7 @@ import { CFWorkerSQLDatabase } from "../meta-merger/cf-worker-abstract-sql.js"; import { CFDObjSQLDatabase } from "./cf-dobj-abstract-sql.js"; import { Env } from "./env.js"; import { FPDurableObject } from "./server.js"; +import { WSRoom } from "../ws-room.js"; // function ensureLogger(env: Env, module = "Fireproof"): Logger { // const logger = new LoggerImpl() @@ -33,7 +34,7 @@ import { FPDurableObject } from "./server.js"; // return logger.Logger(); // } -const startedChs = new ResolveOnce(); +const startedChs = new KeyedResolvOnce(); export function getDurableObject(env: Env) { // console.log("getDurableObject", env); @@ -44,6 +45,13 @@ export function getDurableObject(env: Env) { return dObjNs.get(id); } +class CFWSRoom implements WSRoom { + acceptConnection(ws: WebSocket): void { + ws.accept(); + // this._wsConnections.set(ws.id, ws); + } +} + export class CFHonoFactory implements HonoServerFactory { readonly _onClose: () => void; constructor( @@ -71,29 +79,35 @@ export class CFHonoFactory implements HonoServerFactory { const gs = defaultGestalt(msgP, { id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - const ret = startedChs - .once(async () => { - const cfBackendMode = - c.env.CF_BACKEND_MODE && c.env.CF_BACKEND_MODE === "DURABLE_OBJECT" ? "DURABLE_OBJECT" : "D1"; - let db: SQLDatabase; - switch (cfBackendMode) { - case "DURABLE_OBJECT": - db = new CFDObjSQLDatabase(getDurableObject(c.env)); - break; - case "D1": - default: - { - const cfBackendKey = c.env.CF_BACKEND_KEY ?? "FP_D1"; - db = new CFWorkerSQLDatabase(c.env[cfBackendKey] as D1Database); - } - break; - } - const chs = new CFHonoServer(sthis, logger, ende, gs, db); - await chs.start(); - return chs; - }) - .then((chs) => fn({ sthis, logger, ende, impl: chs })); - return ret; // .then((v) => sthis.logger.Flush().then(() => v)) + + const wsRoom = new CFWSRoom(); + const cfBackendMode = c.env.CF_BACKEND_MODE && c.env.CF_BACKEND_MODE === "DURABLE_OBJECT" ? "DURABLE_OBJECT" : "D1"; + let db: SQLDatabase; + switch (cfBackendMode) { + case "DURABLE_OBJECT": { + db = new CFDObjSQLDatabase(getDurableObject(c.env)); + const chs = new CFHonoServer(sthis, logger, ende, gs, db, wsRoom); + // TODO WE NEED TO START THE DURABLE OBJECT + // but then on every request we import the schema + return chs.start().then((chs) => fn({ sthis, logger, ende, impl: chs })); + } + // break; + case "D1": + default: { + const cfBackendKey = c.env.CF_BACKEND_KEY ?? "FP_D1"; + return startedChs + .get(cfBackendKey) + .once(async () => { + db = new CFWorkerSQLDatabase(c.env[cfBackendKey] as D1Database); + const chs = new CFHonoServer(sthis, logger, ende, gs, db, wsRoom); + await chs.start(); + return chs; + }) + .then((chs) => fn({ sthis, logger, ende, impl: chs })); + } + // break; + } + // return ret; // .then((v) => sthis.logger.Flush().then(() => v)) } async start(_app: Hono): Promise { @@ -122,9 +136,10 @@ export class CFHonoServer extends HonoServerBase { ende: EnDeCoder, gs: Gestalt, sqlDb: SQLDatabase, + wsRoom: WSRoom, headers?: HttpHeader ) { - super(sthis, logger, gs, sqlDb, headers); + super(sthis, logger, gs, sqlDb, wsRoom, headers); this.ende = ende; // this.env = env; } @@ -178,7 +193,7 @@ export class CFHonoServer extends HonoServerBase { // wsCtx.send("Hellox from server"); wsEvents.onMessage?.(evt, wsCtx); }; - server.accept(); + this.wsRoom.acceptConnection(server); wsEvents.onOpen?.({} as Event, wsCtx); diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index 3d230712..b699e008 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -119,7 +119,7 @@ FP_DEBUG = "FPMetaGroups" FP_PROTOCOL = "ws" CF_BACKEND_MODE = "DURABLE_OBJECT" -[env.test-stream-D0.durable_objects] +[env.test-stream-DO.durable_objects] bindings = [ { name = "FP_DO", class_name = "FPDurableObject" }, ] diff --git a/src/cloud/connection.test.ts b/src/cloud/connection.test.ts index f00ded4b..43c4fa3a 100644 --- a/src/cloud/connection.test.ts +++ b/src/cloud/connection.test.ts @@ -73,7 +73,7 @@ describe("Connection", () => { sthis.env.sets((await resolveToml("D1")).env as unknown as Record); }); - describe.each([NodeHonoServerFactory(), CFHonoServerFactory("DO") /*, CFHonoServerFactory("DO")*/])( + describe.each([NodeHonoServerFactory(), CFHonoServerFactory("DO"), CFHonoServerFactory("D1")])( "$name - Connection", (honoServer) => { const port = +(process.env.FP_WRANGLER_PORT || 0) || 1024 + Math.floor(Math.random() * (65536 - 1024)); diff --git a/src/cloud/hono-server.ts b/src/cloud/hono-server.ts index cfa0a27e..b04fe3b1 100644 --- a/src/cloud/hono-server.ts +++ b/src/cloud/hono-server.ts @@ -31,6 +31,7 @@ import { } from "./msg-type-meta.js"; import { MetaMerger } from "./meta-merger/meta-merger.js"; import { SQLDatabase } from "./meta-merger/abstract-sql.js"; +import { WSRoom } from "./ws-room.js"; export interface RunTimeParams { readonly sthis: SuperThis; @@ -57,10 +58,12 @@ export abstract class HonoServerBase implements HonoServerImpl { readonly logger: Logger; readonly metaMerger: MetaMerger; readonly headers: HttpHeader; - constructor(sthis: SuperThis, logger: Logger, gs: Gestalt, sqlDb: SQLDatabase, headers?: HttpHeader) { + readonly wsRoom: WSRoom; + constructor(sthis: SuperThis, logger: Logger, gs: Gestalt, sqlDb: SQLDatabase, wsRoom: WSRoom, headers?: HttpHeader) { this.logger = logger; this._gs = gs; this.sthis = sthis; + this.wsRoom = wsRoom; this.metaMerger = new MetaMerger(sqlDb); this.headers = headers ? headers.Clone().Merge(CORS) : CORS.Clone(); } diff --git a/src/cloud/meta-merger/bettersql-abstract-sql.ts b/src/cloud/meta-merger/bettersql-abstract-sql.ts index d583cb98..e28bf869 100644 --- a/src/cloud/meta-merger/bettersql-abstract-sql.ts +++ b/src/cloud/meta-merger/bettersql-abstract-sql.ts @@ -10,12 +10,12 @@ export class BetterSQLStatement implements SQLStatement { async run(...iparams: SQLParams): Promise { const res = (await this.stmt.run(...sqliteCoerceParams(iparams))) as T; - console.log("run", res); + // console.log("run", res); return res; } async all(...params: SQLParams): Promise { const res = (await this.stmt.all(...sqliteCoerceParams(params))) as T[]; - console.log("all", res); + // console.log("all", res); return res; } } diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 66a8472f..8e4162b7 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -6,6 +6,7 @@ import { ensureLogger, SuperThis } from "@fireproof/core"; import { defaultMsgParams, jsonEnDe } from "./msger.js"; import { defaultGestalt, Gestalt, MsgerParams } from "./msg-types.js"; import { SQLDatabase } from "./meta-merger/abstract-sql.js"; +import { WSRoom } from "./ws-room.js"; interface ServerType { close(fn: () => void): void; @@ -19,6 +20,19 @@ export interface NodeHonoFactoryParams { readonly sql: SQLDatabase; } +const wsConnections = new Map(); +class NodeWSRoom implements WSRoom { + readonly sthis: SuperThis; + constructor(sthis: SuperThis) { + this.sthis = sthis; + } + acceptConnection(ws: WebSocket): void { + const id = this.sthis.nextId(12).str; + wsConnections.set(id, ws); + ws.accept(); + } +} + export class NodeHonoFactory implements HonoServerFactory { _upgradeWebSocket!: UpgradeWebSocket; _injectWebSocket!: (t: unknown) => void; @@ -43,17 +57,18 @@ export class NodeHonoFactory implements HonoServerFactory { const fpProtocol = sthis.env.get("FP_PROTOCOL"); const msgP = - this.params.msgP || + this.params.msgP ?? defaultMsgParams(sthis, { hasPersistent: true, protocolCapabilities: fpProtocol ? (fpProtocol === "ws" ? ["stream"] : ["reqRes"]) : ["reqRes", "stream"], }); const gs = - this.params.gs || + this.params.gs ?? defaultGestalt(msgP, { id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - const nhs = new NodeHonoServer(sthis, this, gs, this.params.sql); + const wsRoom = new NodeWSRoom(sthis); + const nhs = new NodeHonoServer(sthis, this, gs, this.params.sql, wsRoom); return nhs.start().then((nhs) => fn({ sthis, logger, ende, impl: nhs })); } @@ -88,8 +103,15 @@ export class NodeHonoFactory implements HonoServerFactory { export class NodeHonoServer extends HonoServerBase implements HonoServerImpl { readonly _upgradeWebSocket: UpgradeWebSocket; - constructor(sthis: SuperThis, factory: NodeHonoFactory, gs: Gestalt, sqldb: SQLDatabase, headers?: HttpHeader) { - super(sthis, sthis.logger, gs, sqldb, headers); + constructor( + sthis: SuperThis, + factory: NodeHonoFactory, + gs: Gestalt, + sqldb: SQLDatabase, + wsRoom: WSRoom, + headers?: HttpHeader + ) { + super(sthis, sthis.logger, gs, sqldb, wsRoom, headers); this._upgradeWebSocket = factory._upgradeWebSocket; } diff --git a/src/cloud/ws-room.ts b/src/cloud/ws-room.ts new file mode 100644 index 00000000..fe8538b7 --- /dev/null +++ b/src/cloud/ws-room.ts @@ -0,0 +1,3 @@ +export interface WSRoom { + acceptConnection(ws: WebSocket): void; +} From d30ec876e73db1148e9c274caac408c3b3146624 Mon Sep 17 00:00:00 2001 From: J Chris Anderson Date: Thu, 23 Jan 2025 14:16:18 -0800 Subject: [PATCH 82/83] try the ones that pass for me --- vitest.workspace.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vitest.workspace.ts b/vitest.workspace.ts index eea2d793..54246881 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -2,24 +2,24 @@ import { defineWorkspace } from "vitest/config"; import aws from "./vitest.aws.config.ts"; import betterSqlite3 from "./vitest.better-sqlite3.config.ts"; -import nodeSqlite3Wasm from "./vitest.node-sqlite3-wasm.config.ts"; +// import nodeSqlite3Wasm from "./vitest.node-sqlite3-wasm.config.ts"; import partykit from "./vitest.partykit.config.ts"; import cloud from "./vitest.cloud.config.ts"; import s3 from "./vitest.s3.config.ts"; // import connector from "./vitest.connector.config.ts"; -import netlify from "./vitest.netlify.config.ts"; -import ucan from "./vitest.ucan.config.ts"; +// import netlify from "./vitest.netlify.config.ts"; +// import ucan from "./vitest.ucan.config.ts"; import cfWorker from "./vitest.cf-worker.config.ts"; export default defineWorkspace([ - nodeSqlite3Wasm, + // nodeSqlite3Wasm, betterSqlite3, // connector, s3, aws, - netlify, + // netlify, partykit, cloud, cfWorker, - ucan, + // ucan, ]); From 7ccaa69465ddfbd80a6db20c9d91b782202927f6 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Fri, 24 Jan 2025 19:10:46 +0100 Subject: [PATCH 83/83] WIP --- .coderabbit.yaml | 2 +- package.json | 21 +- pnpm-lock.yaml | 194 +++++++++ setup.libsql.ts | 5 + setup.node-sqlite3-wasm.ts | 2 +- src/cloud/backend/cf-dobj-abstract-sql.ts | 226 +---------- src/cloud/backend/cf-hono-server.ts | 80 ++-- src/cloud/backend/env.d.ts | 18 +- src/cloud/backend/server.ts | 377 +----------------- src/cloud/backend/wrangler.toml | 34 +- src/cloud/meta-merger/meta-merger.test.ts | 6 +- src/cloud/node-hono-server.ts | 22 +- src/cloud/ws-room.ts | 4 +- src/coerce-binary.ts | 1 + .../v0.19/sqlite/libsql/sqlite-connection.ts | 79 ++++ src/sql/v0.19/sqlite_factory.ts | 11 +- tests/Dockerfile.connect-netlify | 1 + vitest.libsql.config.ts | 18 + vitest.workspace.ts | 3 + 19 files changed, 442 insertions(+), 662 deletions(-) create mode 100644 setup.libsql.ts create mode 100644 src/sql/v0.19/sqlite/libsql/sqlite-connection.ts create mode 100644 vitest.libsql.config.ts diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 4a839e76..91d1c97e 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -10,6 +10,6 @@ reviews: collapse_walkthrough: false auto_review: enabled: true - drafts: true + drafts: false chat: auto_reply: true diff --git a/package.json b/package.json index e41e5d02..bc29dcf0 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,22 @@ "description": "Live database connector for the web", "type": "module", "scripts": { - "publish": "pnpm run '/publish:/'", - "publish:aws": "tsx ./publish-package.ts ./dist/aws/package.json", - "publish:cloud": "tsx ./publish-package.ts ./dist/cloud/package.json", - "publish:netlify": "tsx ./publish-package.ts ./dist/netlify/package.json", - "publish:s3": "tsx ./publish-package.ts ./dist/s3/package.json", - "publish:partykit": "tsx ./publish-package.ts ./dist/partykit/package.json", - "publish:ucan": "tsx ./publish-package.ts ./dist/ucan/package.json", + "xpublish": "pnpm run '/publish:/'", + "xpublish:aws": "tsx ./publish-package.ts ./dist/aws/package.json", + "xpublish:cloud": "tsx ./publish-package.ts ./dist/cloud/package.json", + "xpublish:netlify": "tsx ./publish-package.ts ./dist/netlify/package.json", + "xpublish:s3": "tsx ./publish-package.ts ./dist/s3/package.json", + "xpublish:partykit": "tsx ./publish-package.ts ./dist/partykit/package.json", + "xpublish:ucan": "tsx ./publish-package.ts ./dist/ucan/package.json", "prebuild": "rm -rf dist", - "prepare": "pnpm run build", + "xprepare": "pnpm run build", "build": "pnpm run '/^build:/' && pnpm run '/^pub:/'", "build:tsc": "tsc", "build:tsup": "tsup", "pub:noop": "echo", "pub:aws": "tsx ./version-copy-package.ts ./dist/aws/package-aws.json && cp ./src/aws/README.md ./dist/aws/", "pub:cloud": "tsx ./version-copy-package.ts ./dist/cloud/package-cloud.json && cp ./src/cloud/client/README.md ./dist/cloud/", - "pub:netlify": "tsx ./version-copy-package.ts ./dist/netlify/package-netlify.json && cp ./src/netlify/server.ts ./dist/netlify/ && cp ./src/netlify/README.md ./dist/netlify/", + "pub:netlify": "tsx ./version-copy-package.ts ./dist/netlify/package-netlify.json && esbuild --format=esm --bundle src/netlify/server.ts > ./dist/netlify/server.js && cp ./src/netlify/README.md ./dist/netlify/", "pub:s3": "tsx ./version-copy-package.ts ./dist/s3/package-s3.json && cp ./src/s3/README.md ./dist/s3/", "pub:partykit": "tsx ./version-copy-package.ts ./dist/partykit/package-partykit.json && cp ./src/partykit/server.ts ./dist/partykit/ && cp ./src/partykit/README.md ./dist/partykit/", "pub:ucan": "tsx ./version-copy-package.ts ./dist/ucan/package-ucan.json && cp ./src/ucan/README.md ./dist/ucan/", @@ -95,12 +95,13 @@ "@aws-sdk/client-s3": "^3.717.0", "@cloudflare/vitest-pool-workers": "^0.5.34", "@cloudflare/workers-types": "^4.20241127.0", - "@fireproof/core": "^0.19.121", + "@fireproof/core": "v0.20-dev-fp-ns", "@fireproof/vendor": "^1.0.4", "@hono/node-server": "^1.13.7", "@hono/node-ws": "^1.0.4", "@ipld/dag-ucan": "^3.4.0", "@jspm/core": "^2.1.0", + "@libsql/client": "^0.14.0", "@netlify/blobs": "^8.1.0", "@ucanto/client": "^9.0.1", "@ucanto/core": "^10.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b13d8a47..a9d3d448 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@jspm/core': specifier: ^2.1.0 version: 2.1.0 + '@libsql/client': + specifier: ^0.14.0 + version: 0.14.0 '@netlify/blobs': specifier: ^8.1.0 version: 8.1.0 @@ -1375,10 +1378,64 @@ packages: '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} + '@libsql/client@0.14.0': + resolution: {integrity: sha512-/9HEKfn6fwXB5aTEEoMeFh4CtG0ZzbncBb1e++OCdVpgKZ/xyMsIVYXm0w7Pv4RUel803vE6LwniB3PqD72R0Q==} + + '@libsql/core@0.14.0': + resolution: {integrity: sha512-nhbuXf7GP3PSZgdCY2Ecj8vz187ptHlZQ0VRc751oB2C1W8jQUXKKklvt7t1LJiUTQBVJuadF628eUk+3cRi4Q==} + + '@libsql/darwin-arm64@0.4.7': + resolution: {integrity: sha512-yOL742IfWUlUevnI5PdnIT4fryY3LYTdLm56bnY0wXBw7dhFcnjuA7jrH3oSVz2mjZTHujxoITgAE7V6Z+eAbg==} + cpu: [arm64] + os: [darwin] + + '@libsql/darwin-x64@0.4.7': + resolution: {integrity: sha512-ezc7V75+eoyyH07BO9tIyJdqXXcRfZMbKcLCeF8+qWK5nP8wWuMcfOVywecsXGRbT99zc5eNra4NEx6z5PkSsA==} + cpu: [x64] + os: [darwin] + + '@libsql/hrana-client@0.7.0': + resolution: {integrity: sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==} + + '@libsql/isomorphic-fetch@0.3.1': + resolution: {integrity: sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==} + engines: {node: '>=18.0.0'} + + '@libsql/isomorphic-ws@0.1.5': + resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} + + '@libsql/linux-arm64-gnu@0.4.7': + resolution: {integrity: sha512-WlX2VYB5diM4kFfNaYcyhw5y+UJAI3xcMkEUJZPtRDEIu85SsSFrQ+gvoKfcVh76B//ztSeEX2wl9yrjF7BBCA==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-arm64-musl@0.4.7': + resolution: {integrity: sha512-6kK9xAArVRlTCpWeqnNMCoXW1pe7WITI378n4NpvU5EJ0Ok3aNTIC2nRPRjhro90QcnmLL1jPcrVwO4WD1U0xw==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-x64-gnu@0.4.7': + resolution: {integrity: sha512-CMnNRCmlWQqqzlTw6NeaZXzLWI8bydaXDke63JTUCvu8R+fj/ENsLrVBtPDlxQ0wGsYdXGlrUCH8Qi9gJep0yQ==} + cpu: [x64] + os: [linux] + + '@libsql/linux-x64-musl@0.4.7': + resolution: {integrity: sha512-nI6tpS1t6WzGAt1Kx1n1HsvtBbZ+jHn0m7ogNNT6pQHZQj7AFFTIMeDQw/i/Nt5H38np1GVRNsFe99eSIMs9XA==} + cpu: [x64] + os: [linux] + + '@libsql/win32-x64-msvc@0.4.7': + resolution: {integrity: sha512-7pJzOWzPm6oJUxml+PCDRzYQ4A1hTMHAciTAHfFK4fkbDZX33nWPVG7Y3vqdKtslcwAzwmrNDc6sXy2nwWnbiw==} + cpu: [x64] + os: [win32] + '@multiformats/murmur3@2.1.8': resolution: {integrity: sha512-6vId1C46ra3R1sbJUOFCZnsUIveR9oF20yhPmAFxPm0JfrX3/ZRCgP3YDrBzlGoEppOXnA9czHeYc0T9mB6hbA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} + '@neon-rs/load@0.0.4': + resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + '@netlify/blobs@8.1.0': resolution: {integrity: sha512-9hIbusvAZjSGBJ42OyFC2AxsEph1LuKQahMWFcPGEIsOqIYHhMRkYA7wSUMhH7naydjNmllpcp3pJLOK4RhFaQ==} engines: {node: ^14.16.0 || >=16.0.0} @@ -2230,6 +2287,10 @@ packages: data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} @@ -2276,6 +2337,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -2499,6 +2564,10 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -2545,6 +2614,10 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -2989,6 +3062,9 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3018,6 +3094,11 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + libsql@0.4.7: + resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} + cpu: [x64, arm64, wasm32] + os: [darwin, linux, win32] + lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} @@ -3209,6 +3290,10 @@ packages: resolution: {integrity: sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==} engines: {node: '>=10'} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -3218,6 +3303,10 @@ packages: encoding: optional: true + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -3464,6 +3553,9 @@ packages: prolly-trees@1.0.4: resolution: {integrity: sha512-vtnxfw5wnUHbGa0IIIk9B9DRztJWZw+t9d0s0iGxY/VzEGCg2EMl8GgGU3EhSquFLWapwbGjFTL1ipbezaXR3g==} + promise-limit@2.7.0: + resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} + property-is-enumerable-x@2.1.2: resolution: {integrity: sha512-lRqJh4yGnwiZUx7x8abWhfucNsImqwxbFoCQzRjfwJflOBenZoFq/YMlWJShdzBmqd9i2/RrrvFW8cBs1+H+3w==} engines: {node: '>=8.11.4', npm: 6.10.1} @@ -4128,6 +4220,10 @@ packages: engines: {node: '>=12.0.0'} hasBin: true + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -5427,11 +5523,69 @@ snapshots: '@jspm/core@2.1.0': {} + '@libsql/client@0.14.0': + dependencies: + '@libsql/core': 0.14.0 + '@libsql/hrana-client': 0.7.0 + js-base64: 3.7.7 + libsql: 0.4.7 + promise-limit: 2.7.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/core@0.14.0': + dependencies: + js-base64: 3.7.7 + + '@libsql/darwin-arm64@0.4.7': + optional: true + + '@libsql/darwin-x64@0.4.7': + optional: true + + '@libsql/hrana-client@0.7.0': + dependencies: + '@libsql/isomorphic-fetch': 0.3.1 + '@libsql/isomorphic-ws': 0.1.5 + js-base64: 3.7.7 + node-fetch: 3.3.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/isomorphic-fetch@0.3.1': {} + + '@libsql/isomorphic-ws@0.1.5': + dependencies: + '@types/ws': 8.5.13 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/linux-arm64-gnu@0.4.7': + optional: true + + '@libsql/linux-arm64-musl@0.4.7': + optional: true + + '@libsql/linux-x64-gnu@0.4.7': + optional: true + + '@libsql/linux-x64-musl@0.4.7': + optional: true + + '@libsql/win32-x64-msvc@0.4.7': + optional: true + '@multiformats/murmur3@2.1.8': dependencies: multiformats: 13.3.1 murmurhash3js-revisited: 3.0.0 + '@neon-rs/load@0.0.4': {} + '@netlify/blobs@8.1.0': {} '@noble/curves@1.6.0': @@ -6626,6 +6780,8 @@ snapshots: data-uri-to-buffer@2.0.2: {} + data-uri-to-buffer@4.0.1: {} + date-fns@4.1.0: {} debounce-fn@5.1.2: @@ -6662,6 +6818,8 @@ snapshots: delayed-stream@1.0.0: {} + detect-libc@2.0.2: {} + detect-libc@2.0.3: {} devalue@4.3.3: {} @@ -7012,6 +7170,11 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -7059,6 +7222,10 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + fs-constants@1.0.0: {} fsevents@2.3.3: @@ -7597,6 +7764,8 @@ snapshots: joycon@3.1.1: {} + js-base64@3.7.7: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -7622,6 +7791,19 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + libsql@0.4.7: + dependencies: + '@neon-rs/load': 0.0.4 + detect-libc: 2.0.2 + optionalDependencies: + '@libsql/darwin-arm64': 0.4.7 + '@libsql/darwin-x64': 0.4.7 + '@libsql/linux-arm64-gnu': 0.4.7 + '@libsql/linux-arm64-musl': 0.4.7 + '@libsql/linux-x64-gnu': 0.4.7 + '@libsql/linux-x64-musl': 0.4.7 + '@libsql/win32-x64-msvc': 0.4.7 + lilconfig@3.1.2: {} lines-and-columns@1.2.4: {} @@ -7823,12 +8005,20 @@ snapshots: dependencies: semver: 7.6.3 + node-domexception@1.0.0: {} + node-fetch@2.7.0(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 optionalDependencies: encoding: 0.1.13 + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + node-forge@1.3.1: {} node-sql-parser@3.9.4: @@ -8101,6 +8291,8 @@ snapshots: bl: 4.1.0 node-sql-parser: 3.9.4 + promise-limit@2.7.0: {} + property-is-enumerable-x@2.1.2: dependencies: simple-methodize-x: 1.0.4 @@ -8799,6 +8991,8 @@ snapshots: transitivePeerDependencies: - debug + web-streams-polyfill@3.3.3: {} + webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} diff --git a/setup.libsql.ts b/setup.libsql.ts new file mode 100644 index 00000000..52662f0f --- /dev/null +++ b/setup.libsql.ts @@ -0,0 +1,5 @@ +import { registerSqliteStoreProtocol } from "./src/sql/gateway-sql.js"; + +registerSqliteStoreProtocol(); +process.env.FP_STORAGE_URL = "sqlite://dist/fp-dir-libsql?taste=libsql"; +process.env.FP_KEYBAG_URL = "file://./dist/kb-dir-libsql"; diff --git a/setup.node-sqlite3-wasm.ts b/setup.node-sqlite3-wasm.ts index a39af714..c06ba69f 100644 --- a/setup.node-sqlite3-wasm.ts +++ b/setup.node-sqlite3-wasm.ts @@ -2,4 +2,4 @@ import { registerSqliteStoreProtocol } from "./src/sql/gateway-sql.js"; registerSqliteStoreProtocol(); process.env.FP_STORAGE_URL = "sqlite://dist/fp-dir-node-sqlite3-wasm?taste=node-sqlite3-wasm"; -process.env.FP_KEYBAG_URL = "file://./dist/kb-dir-node-sqlite3-warm"; +process.env.FP_KEYBAG_URL = "file://./dist/kb-dir-node-sqlite3-wasm"; diff --git a/src/cloud/backend/cf-dobj-abstract-sql.ts b/src/cloud/backend/cf-dobj-abstract-sql.ts index 9f8a5ac9..37e44ab6 100644 --- a/src/cloud/backend/cf-dobj-abstract-sql.ts +++ b/src/cloud/backend/cf-dobj-abstract-sql.ts @@ -1,7 +1,7 @@ // import { DurableObject } from "cloudflare:workers"; import { SQLDatabase, sqliteCoerceParams, SQLParams, SQLStatement } from "../meta-merger/abstract-sql.js"; // import { Env } from "./env.js"; -import { ExecSQLResult, FPDurableObject } from "./server.js"; +import { ExecSQLResult, FPBackendDurableObject } from "./server.js"; export class CFDObjSQLStatement implements SQLStatement { readonly sql: string; @@ -21,231 +21,11 @@ export class CFDObjSQLStatement implements SQLStatement { } export class CFDObjSQLDatabase implements SQLDatabase { - readonly dobj: DurableObjectStub; - constructor(dobj: DurableObjectStub) { + readonly dobj: DurableObjectStub; + constructor(dobj: DurableObjectStub) { this.dobj = dobj; } prepare(sql: string): SQLStatement { return new CFDObjSQLStatement(this, sql); } } - -// export class FPDurableObject extends DurableObject { -// // readonly sessions: Map = new Map(); -// // readonly lastMetaByTendant = new Map[]>(); -// // readonly wsEvents: WSEvents = {}; - -// // injectWSEvents(wsEvents: WSEvents): void { -// // Object.assign(this.wsEvents, wsEvents); -// // } -// // getSQLDatabase(): SQLDatabase { -// // return this._cfDObjSQLDatabase; -// // } - -// async execSql(sql: string, params: unknown[]): Promise { -// console.log("execSql", sql, params); -// const stmt = await this.ctx.storage.sql.exec(sql, params); -// return stmt; -// } - -// // webSocketError(_ws: WebSocket, error: unknown): void | Promise { -// // this.logger.Error().Any("error", error).Msg("webSocketError"); -// // this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); -// // } - -// // async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { -// // this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); -// // if (typeof msg !== "string") { -// // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); -// // return; -// // } - -// // return CFMsgProcessor.dispatch( -// // () => JSON.parse(msg.toString()), -// // { env: this.env }, -// // async (req: MsgBase, ictx: CFCtxBase) => { -// // if (req.auth) { -// // // do ucan magic -// // } -// // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; -// // group = { -// // ...group, -// // qs: { -// // ...group.qs, -// // q: { -// // ...group.qs.q, -// // [req.type]: { -// // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, -// // }, -// // }, -// // }, -// // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), -// // lastUsed: new Date(), -// // } satisfies FPMetaGroup; -// // ws.serializeAttachment(group); -// // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; -// // return { req, ctx }; -// // } -// // ).then((qs) => { -// // let group = { -// // ...qs.ctx.group, -// // qs: { -// // ...qs.ctx.group.qs, -// // s: { -// // ...qs.ctx.group.qs.s, -// // [qs.req.type]: { -// // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, -// // }, -// // }, -// // }, -// // } satisfies FPMetaGroup; -// // switch (true) { -// // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): -// // { -// // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; -// // ws.serializeAttachment(group); -// // // console.log("putMeta group", group); -// // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( -// // buildUpdateMetaEvent(qs, { -// // connId: qs.res.connId, -// // subscriberId: "later-overriden", -// // }) -// // ); -// // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); -// // } -// // break; -// // case MsgIsResSubscribeMeta(qs): -// // { -// // group = { ...group, group: qs.res } satisfies FPMetaGroup; -// // // console.log("subscribeMeta group", group); -// // ws.serializeAttachment(group); -// // this.updateMeta({ -// // connId: qs.res.connId, -// // subscriberId: "later-overriden", -// // tid: qs.res.tid, -// // type: "updateMeta", -// // key: qs.res.key, -// // metaId: "later-overriden", -// // metas: [], -// // version: qs.res.version, -// // }); -// // } -// // break; -// // } -// // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); -// // ws.send(JSON.stringify(qs.res)); -// // }); -// // } - -// // async fetch(_req: Request): Promise { -// // const { 0: fromClient, 1: toClient } = new WebSocketPair(); -// // this.ctx.acceptWebSocket(toClient); -// // // this.logger.Debug().Msg("fetch"); -// // this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); -// // return new Response(null, { -// // status: 101, -// // webSocket: fromClient, -// // }); - -// // // const path = URI.from(req.url).pathname; -// // // switch (path) { -// // // case "/fp": { -// // // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); -// // // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); -// // // } -// // // case "/ws": { -// // // const upgradeHeader = req.headers.get("Upgrade"); -// // // if (!upgradeHeader || upgradeHeader !== "websocket") { -// // // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); -// // // } -// // // const { 0: fromClient, 1: toClient } = new WebSocketPair(); -// // // this.ctx.acceptWebSocket(toClient); -// // // // this.logger.Debug().Msg("fetch"); -// // // return new Response(null, { -// // // status: 101, -// // // webSocket: fromClient, -// // // }); -// // // } -// // // default: { -// // // const logger = ensureLogger(this.env); -// // // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); -// // // } -// // // } -// // // return new Response("Not implemented", { status: 501 }); -// // } - -// // webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { -// // try { -// // // if (typeof this.env.WS_EVENTS.onClose === "function") { -// // this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); -// // // } -// // ws.close(code, reason); -// // // eslint-disable-next-line @typescript-eslint/no-unused-vars -// // } catch (e) { -// // // ignore -// // } finally { -// // this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); -// // } -// // } - -// // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { -// // const wsSocks = ctx.dobj.getWebSockets(); -// // const groupWs = wsSocks.map((ws) => ({ -// // ws, -// // group: ws.deserializeAttachment() as FPMetaGroup, -// // })); -// // const joinedMeta = groupWs.reduce((acc, { group }) => { -// // if (group && group.lastMeta) { -// // acc.push(...group.lastMeta.metas); -// // } -// // return acc -// // }, [] as CRDTEntry[]) -// // const now = new Date() -// // const joinedQS = { -// // req: { ...qs.req, metas: joinedMeta }, -// // res: qs.res, -// // } -// // return acc; -// // }, [] as CRDTEntry[]); -// // if (joinedMeta.length === 0) { -// // return []; -// // } -// // const now = new Date(); -// // const joinedUp = { -// // ...up, -// // metas: joinedMeta, -// // }; -// // groupWs.forEach(({ ws, group }) => { -// // // console.log("group->", group); -// // // group = { -// // // ...group, -// // // msgSeq: (group ? group.msgSeq : 0) + 1, -// // // } -// // group = { -// // ...group, -// // qs: { -// // ...group.qs, -// // s: { -// // ...group.qs.s, -// // [up.type]: { -// // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, -// // }, -// // }, -// // }, -// // lastUsed: now, -// // } satisfies FPMetaGroup; -// // ws.serializeAttachment(group); -// // const toSend = { -// // ...joinedUp, -// // subscriberId: group.group.subscriberId, -// // connId: group.group.connId, -// // }; -// // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); -// // ws.send( -// // // this is not the best way to do this -// // JSON.stringify(toSend) -// // ); -// // }); -// // return joinedMeta; -// // } -// } diff --git a/src/cloud/backend/cf-hono-server.ts b/src/cloud/backend/cf-hono-server.ts index 6fc3a6aa..c190a7bb 100644 --- a/src/cloud/backend/cf-hono-server.ts +++ b/src/cloud/backend/cf-hono-server.ts @@ -10,45 +10,41 @@ import { SQLDatabase } from "../meta-merger/abstract-sql.js"; import { CFWorkerSQLDatabase } from "../meta-merger/cf-worker-abstract-sql.js"; import { CFDObjSQLDatabase } from "./cf-dobj-abstract-sql.js"; import { Env } from "./env.js"; -import { FPDurableObject } from "./server.js"; import { WSRoom } from "../ws-room.js"; - -// function ensureLogger(env: Env, module = "Fireproof"): Logger { -// const logger = new LoggerImpl() -// .With() -// .Module(module) -// .SetDebug(env.FP_DEBUG) -// .SetExposeStack(!!env.FP_STACK || false); -// switch (env.FP_FORMAT) { -// case "jsonice": -// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2)); -// break; -// case "yaml": -// logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2)); -// break; -// case "json": -// default: -// logger.SetFormatter(new JSONFormatter(logger.TxtEnDe())); -// break; -// } -// return logger.Logger(); -// } +import { FPBackendDurableObject, FPRoomDurableObject } from "./server.js"; const startedChs = new KeyedResolvOnce(); -export function getDurableObject(env: Env) { +export function getBackendDurableObject(env: Env) { + // console.log("getDurableObject", env); + const cfBackendKey = env.CF_BACKEND_KEY ?? "FP_BACKEND_DO"; + const rany = env as unknown as Record>; + const dObjNs = rany[cfBackendKey]; + const id = dObjNs.idFromName(env.FP_BACKEND_DO_ID ?? cfBackendKey); + return dObjNs.get(id); +} + +export function getRoomDurableObject(env: Env) { // console.log("getDurableObject", env); - const cfBackendKey = env.CF_BACKEND_KEY ?? "FP_DO"; - const rany = env as unknown as Record>; + const cfBackendKey = env.CF_BACKEND_KEY ?? "FP_WS_ROOM"; + const rany = env as unknown as Record>; const dObjNs = rany[cfBackendKey]; - const id = dObjNs.idFromName(env.FP_DO_ID ?? cfBackendKey); + const id = dObjNs.idFromName(cfBackendKey); return dObjNs.get(id); } class CFWSRoom implements WSRoom { - acceptConnection(ws: WebSocket): void { - ws.accept(); - // this._wsConnections.set(ws.id, ws); + readonly dobj: DurableObjectStub; + constructor(dobj: DurableObjectStub) { + this.dobj = dobj; + } + async acceptConnection(ws: WebSocket, wse: WSEvents): Promise { + const ret = await this.dobj.acceptWebSocket(ws, wse); + const wsCtx = new WSContext(ws as WSContextInit); + wse.onOpen?.({} as Event, wsCtx); + // return Promise.resolve(); + // ws.accept(); + return ret; } } @@ -80,12 +76,12 @@ export class CFHonoFactory implements HonoServerFactory { id: fpProtocol ? (fpProtocol === "http" ? "HTTP-server" : "WS-server") : "FP-CF-Server", }); - const wsRoom = new CFWSRoom(); + const wsRoom = new CFWSRoom(c.env); const cfBackendMode = c.env.CF_BACKEND_MODE && c.env.CF_BACKEND_MODE === "DURABLE_OBJECT" ? "DURABLE_OBJECT" : "D1"; let db: SQLDatabase; switch (cfBackendMode) { case "DURABLE_OBJECT": { - db = new CFDObjSQLDatabase(getDurableObject(c.env)); + db = new CFDObjSQLDatabase(getBackendDurableObject(c.env)); const chs = new CFHonoServer(sthis, logger, ende, gs, db, wsRoom); // TODO WE NEED TO START THE DURABLE OBJECT // but then on every request we import the schema @@ -94,7 +90,7 @@ export class CFHonoFactory implements HonoServerFactory { // break; case "D1": default: { - const cfBackendKey = c.env.CF_BACKEND_KEY ?? "FP_D1"; + const cfBackendKey = c.env.CF_BACKEND_KEY ?? "FP_BACKEND_D1"; return startedChs .get(cfBackendKey) .once(async () => { @@ -174,28 +170,14 @@ export class CFHonoServer extends HonoServerBase { const wsEvents = await createEvents(c); // console.log("upgradeWebSocket", c.req.url); - const wsCtx = new WSContext(server as WSContextInit); + // const wsCtx = new WSContext(server as WSContextInit); // server.onopen = (ev) => { // console.log("onopen", ev); // wsEvents.onOpen?.(ev, wsCtx); // } - server.onerror = (err) => { - // console.log("onerror", err); - wsEvents.onError?.(err, wsCtx); - }; - server.onclose = (ev) => { - // console.log("onclose", ev); - wsEvents.onClose?.(ev, wsCtx); - }; - server.onmessage = (evt) => { - // console.log("onmessage", evt); - // wsCtx.send("Hellox from server"); - wsEvents.onMessage?.(evt, wsCtx); - }; - this.wsRoom.acceptConnection(server); - - wsEvents.onOpen?.({} as Event, wsCtx); + + await this.wsRoom.acceptConnection(server, wsEvents); // server.send("Hello from server"); diff --git a/src/cloud/backend/env.d.ts b/src/cloud/backend/env.d.ts index b6333a38..a3f757e1 100644 --- a/src/cloud/backend/env.d.ts +++ b/src/cloud/backend/env.d.ts @@ -3,7 +3,7 @@ import type { DurableObjectNamespace } from "@cloudflare/workers-types"; // import { WSEvents } from "hono/ws"; -import { FPDurableObject } from "./server.ts"; +import { FPRoomDurableObject, FPBackendDurableObject } from "./server.ts"; export interface Env { // bucket: R2Bucket; @@ -33,14 +33,20 @@ export interface Env { // default D1 CF_BACKEND_MODE: "D1" | "DURABLE_OBJECT"; - // default D1 "FP_D1" - // default DURABLE_OBJECT "FP_DO" + // default D1 "FP_BACKEND_D1" + // default DURABLE_OBJECT "FP_BACKEND_DO" CF_BACKEND_KEY?: string; - FP_DO: DurableObjectNamespace; + FP_BACKEND_D1: D1Database; + + FP_BACKEND_DO: DurableObjectNamespace; // default CF_BACKEND_KEY - FP_DO_ID: string; - FP_D1: D1Database; + FP_BACKEND_DO_ID: string; + + // default "FP_WS_ROOM" + CF_WS_ROOM_KEY: string; + + FP_WS_ROOM: DurableObjectNamespace; // WS_EVENTS: WSEvents; } diff --git a/src/cloud/backend/server.ts b/src/cloud/backend/server.ts index 20a402ff..c0f100b6 100644 --- a/src/cloud/backend/server.ts +++ b/src/cloud/backend/server.ts @@ -6,154 +6,7 @@ import { HonoServer } from "../hono-server.js"; import { Hono } from "hono"; import { Env } from "./env.js"; import { CFHonoFactory } from "./cf-hono-server.js"; -// import { SQLDatabase, SQLStatement } from "../meta-merger/abstract-sql.js"; -// import { WSContext, WSEvents } from "hono/ws"; - -// function json(data: T, status = 200) { -// return Response.json(data, { status, headers: CORS }); -// } - -// interface MsgStats { -// readonly msgSeq: number; -// } - -// interface FPMetaGroup { -// readonly group: ResSubscribeMeta; -// readonly connId: string; -// readonly qs: { -// readonly q: Record; -// readonly s: Record; -// }; -// readonly lastUsed: Date; -// readonly lastMeta: ReqPutMeta; -// } - -// // interface NextId { -// // nextId: SuperThis["nextId"]; -// // } -// // class NextIdImpl implements NextId { -// // nextId(bytes = 6): { str: string; bin: Uint8Array } { -// // const buf = new Uint8Array(bytes); -// // const bin = crypto.getRandomValues(buf); -// // return { -// // str: base58btc.encode(bin), -// // bin, -// // }; -// // } -// // } - -// // const sthis = new NextIdImpl(); - -// // const app = new Hono<{ Bindings: Env }>(); - -// interface CFCtxBaseParam { -// readonly env: Env; -// readonly module?: string; -// } - -// interface CFCtxBase extends CtxBase { -// readonly env: Env; -// } - -// type CFCtxWithGroup = CFCtxBase & { readonly group: FPMetaGroup }; - -// const serverId = "Cloudflare-Fireproof"; - -// class CFMsgProcessor extends MsgProcessorBase { - -// static dispatch( -// decodeFn: () => Promise, -// ctx: CFCtxBaseParam, -// reqFn?: (msg: Q, ctx: CFCtxBase) => Promise> -// ): Promise, CFCtxWithGroup>> { -// return new CFMsgProcessor({ -// env: ctx.env, -// logger: ensureLogger(ctx.env, ctx.module || "CFMsgProcessor"), -// }).dispatch(decodeFn, reqFn); -// } - -// constructor(cfp: CFCtxBase) { -// super(cfp.logger, cfp, "CFMsgProcessor") -// } - -// async dispatch( -// decodeFn: () => Promise, -// reqFn: (msg: Q, ctx: CFCtxBase) => Promise> = async (req) => ({ req }) -// ): Promise, CFCtxWithGroup>> { -// return super.dispatch(decodeFn, async (msg: Q, ctx: CFCtxBase) => { -// const { req, res, ctx: optCtx } = await reqFn(msg, ctx) -// return { req, res, ctx: optCtx || ctx} -// }) -// } - -// async delMeta(req: ReqDelMeta, ctx: CFCtxWithGroup): Promise { -// // delete meta does nothing in this implementation -// // if you delete meta basically you are deleting the whole ledger -// return buildResDelMeta(req, { -// params: req.params, -// status: "unsupported", -// connId: ctx.group.connId, -// }); -// } - -// async getMeta(req: ReqGetMeta, ctx: CFCtxWithGroup): Promise { -// const rSignedUrl = await calculatePreSignedUrl( -// { -// tid: req.tid, -// type: "reqSignedUrl", -// version: req.version, -// params: { ...req.params, method: "GET" }, -// }, -// ctx.env -// ); -// if (rSignedUrl.isErr()) { -// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); -// } -// return buildResGetMeta(req, { -// signedGetUrl: rSignedUrl.Ok().toString(), -// status: "found", -// metas: [], -// connId: "", -// }); -// } - -// async putMeta(req: ReqPutMeta, ctx: CFCtxWithGroup): Promise { -// const rSignedUrl = await calculatePreSignedUrl( -// { -// tid: req.tid, -// type: "reqSignedUrl", -// version: req.version, -// params: { ...req.params, method: "PUT" }, -// }, -// ctx.env -// ); -// if (rSignedUrl.isErr()) { -// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); -// } -// // roughly time ordered -// return buildResPutMeta(req, { -// // metaId should be a hash of metas. -// metaId: new Date().getTime().toString(), -// metas: req.metas, -// signedPutUrl: rSignedUrl.Ok().toString(), -// connId: ctx.group.connId, -// }); -// } - -// async signedUrl(req: Q, ctx: CFCtxBase): Promise { -// const rSignedUrl = await calculatePreSignedUrl(req, ctx.env); -// if (rSignedUrl.isErr()) { -// return buildErrorMsg(this.logger, req, rSignedUrl.Err()); -// } -// const resSignedUrl = buildResSignedUrl(req, rSignedUrl.Ok().toString()); -// return resSignedUrl; -// } - -// async subscribeMeta(req: ReqSubscribeMeta, ctx: CFCtxWithGroup): Promise { -// // console.log("subscribeMeta", req) -// return buildResSubscriptMeta(req, ctx.group); -// } -// } +import { WSContext, WSContextInit, WSEvents } from "hono/ws"; const app = new Hono(); const honoServer = new HonoServer(new CFHonoFactory()); @@ -180,18 +33,7 @@ export interface ExecSQLResult { readonly rawResults: unknown[]; } -export class FPDurableObject extends DurableObject { - // readonly sessions: Map = new Map(); - // readonly lastMetaByTendant = new Map[]>(); - // readonly wsEvents: WSEvents = {}; - - // injectWSEvents(wsEvents: WSEvents): void { - // Object.assign(this.wsEvents, wsEvents); - // } - // getSQLDatabase(): SQLDatabase { - // return this._cfDObjSQLDatabase; - // } - +export class FPBackendDurableObject extends DurableObject { async execSql(sql: string, params: unknown[]): Promise { const cursor = await this.ctx.storage.sql.exec(sql, ...params); const rawResults = cursor.toArray(); @@ -203,205 +45,28 @@ export class FPDurableObject extends DurableObject { // console.log("execSql", sql, params, res); return res; } +} - // webSocketError(_ws: WebSocket, error: unknown): void | Promise { - // this.logger.Error().Any("error", error).Msg("webSocketError"); - // this.env.WS_EVENTS.onError?.(error as Event, {} as WSContext); - // } - - // async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { - // this.env.WS_EVENTS.onMessage?.({ data: msg } as MessageEvent, ws as unknown as WSContext); - // if (typeof msg !== "string") { - // this.logger.Error().Any("fromWS", msg).Msg("webSocketMessage:binary"); - // return; - // } - - // return CFMsgProcessor.dispatch( - // () => JSON.parse(msg.toString()), - // { env: this.env }, - // async (req: MsgBase, ictx: CFCtxBase) => { - // if (req.auth) { - // // do ucan magic - // } - // let group = (ws.deserializeAttachment() || { qs: {} }) as FPMetaGroup; - // group = { - // ...group, - // qs: { - // ...group.qs, - // q: { - // ...group.qs.q, - // [req.type]: { - // msgSeq: group.qs?.q?.[req.type]?.msgSeq + 1, - // }, - // }, - // }, - // connId: group.connId || this.env.FP_META_GROUPS.newUniqueId().toString(), - // lastUsed: new Date(), - // } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // const ctx = { ...ictx, group } satisfies CFCtxWithGroup; - // return { req, ctx }; - // } - // ).then((qs) => { - // let group = { - // ...qs.ctx.group, - // qs: { - // ...qs.ctx.group.qs, - // s: { - // ...qs.ctx.group.qs.s, - // [qs.req.type]: { - // msgSeq: qs.ctx.group.qs?.s?.[qs.req.type]?.msgSeq + 1, - // }, - // }, - // }, - // } satisfies FPMetaGroup; - // switch (true) { - // case MsgIsReqPutMeta(qs.req) && MsgIsResPutMeta(qs): - // { - // group = { ...group, lastMeta: qs.req } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // // console.log("putMeta group", group); - // (qs.res as { metas: CRDTEntry[] }).metas = this.updateMeta( - // buildUpdateMetaEvent(qs, { - // connId: qs.res.connId, - // subscriberId: "later-overriden", - // }) - // ); - // this.logger.Debug().Any("putMeta", qs.res).Msg("webSocketMessage"); - // } - // break; - // case MsgIsResSubscribeMeta(qs): - // { - // group = { ...group, group: qs.res } satisfies FPMetaGroup; - // // console.log("subscribeMeta group", group); - // ws.serializeAttachment(group); - // this.updateMeta({ - // connId: qs.res.connId, - // subscriberId: "later-overriden", - // tid: qs.res.tid, - // type: "updateMeta", - // key: qs.res.key, - // metaId: "later-overriden", - // metas: [], - // version: qs.res.version, - // }); - // } - // break; - // } - // // this.logger.Debug().Any("ws.send", qs).Msg("webSocketMessage"); - // ws.send(JSON.stringify(qs.res)); - // }); - // } +export class FPRoomDurableObject extends DurableObject { + private wsEvents?: WSEvents; - // async fetch(_req: Request): Promise { - // const { 0: fromClient, 1: toClient } = new WebSocketPair(); - // this.ctx.acceptWebSocket(toClient); - // // this.logger.Debug().Msg("fetch"); - // this.env.WS_EVENTS.onOpen?.({} as Event, toClient as unknown as WSContext); - // return new Response(null, { - // status: 101, - // webSocket: fromClient, - // }); + async acceptWebSocket(ws: WebSocket, wsEvents: WSEvents): Promise { + this.ctx.acceptWebSocket(ws); + this.wsEvents = wsEvents; + } - // // const path = URI.from(req.url).pathname; - // // switch (path) { - // // case "/fp": { - // // const rq = await CFMsgProcessor.dispatch(() => req.json(), { env: this.env }); - // // return json(rq.res, MsgIsQSError(rq) ? 422 : 200); - // // } - // // case "/ws": { - // // const upgradeHeader = req.headers.get("Upgrade"); - // // if (!upgradeHeader || upgradeHeader !== "websocket") { - // // return new Response("Durable Object expected Upgrade: websocket", { status: 426 }); - // // } - // // const { 0: fromClient, 1: toClient } = new WebSocketPair(); - // // this.ctx.acceptWebSocket(toClient); - // // // this.logger.Debug().Msg("fetch"); - // // return new Response(null, { - // // status: 101, - // // webSocket: fromClient, - // // }); - // // } - // // default: { - // // const logger = ensureLogger(this.env); - // // return json(buildErrorMsg(logger, { tid: "internal" }, new NotFoundError(`Notfound:${path}`)), 404); - // // } - // // } - // // return new Response("Not implemented", { status: 501 }); - // } + webSocketError(ws: WebSocket, error: unknown): void | Promise { + const wsCtx = new WSContext(ws as WSContextInit); + this.wsEvents?.onError?.(error as Event, wsCtx); + } - // webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { - // try { - // // if (typeof this.env.WS_EVENTS.onClose === "function") { - // this.env.WS_EVENTS.onClose?.({ code, reason } as CloseEvent, {} as WSContext); - // // } - // ws.close(code, reason); - // // eslint-disable-next-line @typescript-eslint/no-unused-vars - // } catch (e) { - // // ignore - // } finally { - // this.logger.Debug().Str("code", code.toString()).Str("reason", reason).Msg("webSocketClose"); - // } - // } + async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer): Promise { + const wsCtx = new WSContext(ws as WSContextInit); + this.wsEvents?.onMessage?.({ data: msg } as MessageEvent, wsCtx); + } - // updateMeta(up: UpdateMetaEvent, ctx: CtxWithGroup): void { - // const wsSocks = ctx.dobj.getWebSockets(); - // const groupWs = wsSocks.map((ws) => ({ - // ws, - // group: ws.deserializeAttachment() as FPMetaGroup, - // })); - // const joinedMeta = groupWs.reduce((acc, { group }) => { - // if (group && group.lastMeta) { - // acc.push(...group.lastMeta.metas); - // } - // return acc - // }, [] as CRDTEntry[]) - // const now = new Date() - // const joinedQS = { - // req: { ...qs.req, metas: joinedMeta }, - // res: qs.res, - // } - // return acc; - // }, [] as CRDTEntry[]); - // if (joinedMeta.length === 0) { - // return []; - // } - // const now = new Date(); - // const joinedUp = { - // ...up, - // metas: joinedMeta, - // }; - // groupWs.forEach(({ ws, group }) => { - // // console.log("group->", group); - // // group = { - // // ...group, - // // msgSeq: (group ? group.msgSeq : 0) + 1, - // // } - // group = { - // ...group, - // qs: { - // ...group.qs, - // s: { - // ...group.qs.s, - // [up.type]: { - // msgSeq: group.qs?.s?.[up.type]?.msgSeq + 1, - // }, - // }, - // }, - // lastUsed: now, - // } satisfies FPMetaGroup; - // ws.serializeAttachment(group); - // const toSend = { - // ...joinedUp, - // subscriberId: group.group.subscriberId, - // connId: group.group.connId, - // }; - // this.logger.Debug().Any("event", toSend).Msg("updateMeta"); - // ws.send( - // // this is not the best way to do this - // JSON.stringify(toSend) - // ); - // }); - // return joinedMeta; - // } + webSocketClose(ws: WebSocket, code: number, reason: string): void | Promise { + const wsCtx = new WSContext(ws as WSContextInit); + this.wsEvents?.onClose?.({ code, reason } as CloseEvent, wsCtx); + } } diff --git a/src/cloud/backend/wrangler.toml b/src/cloud/backend/wrangler.toml index b699e008..dfdee3a2 100644 --- a/src/cloud/backend/wrangler.toml +++ b/src/cloud/backend/wrangler.toml @@ -17,12 +17,13 @@ compatibility_flags = ["nodejs_compat"] [durable_objects] bindings = [ # { name = "FP_DO", class_name = "FPDurableObject", script_name = "cf-dobj-abstract-sql" } - { name = "FP_DO", class_name = "FPDurableObject" } + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } ] [[migrations]] tag = "v1" # Should be unique for each entry -new_sqlite_classes = ["FPDurableObject"] +new_sqlite_classes = ["FPBackendDurableObject"] [observability] enabled = true @@ -46,17 +47,18 @@ CF_BACKEND_MODE = "DURABLE_OBJECT" # ] [[env.test.d1_databases]] -binding = "FP_D1" +binding = "FP_BACKEND_D1" database_name = "test-meta-merge" database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" [[env.test.migrations]] tag = "v1" # Should be unique for each entry -new_sqlite_classes = ["FPDurableObject"] +new_sqlite_classes = ["FPBackendDurableObject"] [env.test.durable_objects] bindings = [ - { name = "FP_DO", class_name = "FPDurableObject" }, + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } ] @@ -71,10 +73,16 @@ FP_DEBUG = "FPMetaGroups" FP_PROTOCOL = "http" [[env.test-reqRes-D1.d1_databases]] -binding = "FP_D1" +binding = "FP_BACKEND_D1" database_name = "test-meta-merge" database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" +[env.test-reqRes-D1.durable_objects] +bindings = [ + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } +] + [env.test-reqRes-DO.vars] VERSION = "FP-MSG-1.0" STORAGE_URL = "http://localhost:9000/testbucket" @@ -88,7 +96,8 @@ CF_BACKEND_MODE = "DURABLE_OBJECT" [env.test-reqRes-DO.durable_objects] bindings = [ - { name = "FP_DO", class_name = "FPDurableObject" }, + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } ] [env.test-stream-D1.vars] @@ -102,8 +111,14 @@ FP_DEBUG = "FPMetaGroups" FP_PROTOCOL = "ws" +[env.test-stream-D1.durable_objects] +bindings = [ + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } +] + [[env.test-stream-D1.d1_databases]] -binding = "FP_D1" +binding = "FP_BACKEND_D1" database_name = "test-meta-merge" database_id = "b8b452ed-b1d9-478f-b56c-c5e4545f157a" @@ -121,7 +136,8 @@ CF_BACKEND_MODE = "DURABLE_OBJECT" [env.test-stream-DO.durable_objects] bindings = [ - { name = "FP_DO", class_name = "FPDurableObject" }, + { name = "FP_BACKEND_DO", class_name = "FPBackendDurableObject" }, + { name = "FP_WS_ROOM", class_name = "FPRoomDurableObject" } ] diff --git a/src/cloud/meta-merger/meta-merger.test.ts b/src/cloud/meta-merger/meta-merger.test.ts index 4e0932eb..621715eb 100644 --- a/src/cloud/meta-merger/meta-merger.test.ts +++ b/src/cloud/meta-merger/meta-merger.test.ts @@ -4,7 +4,7 @@ import { CRDTEntry, ensureSuperThis } from "@fireproof/core"; import { runtimeFn } from "@adviser/cement"; import { SQLDatabase } from "./abstract-sql.js"; import type { Env } from "../backend/env.js"; -import { getDurableObject } from "../backend/cf-hono-server.js"; +import { getBackendDurableObject } from "../backend/cf-hono-server.js"; function sortCRDTEntries(rows: CRDTEntry[]) { return rows.sort((a, b) => a.cid.localeCompare(b.cid)); @@ -35,7 +35,7 @@ function getSQLFlavours(): { name: string; factory: () => Promise } factory: async () => { const { CFWorkerSQLDatabase } = await import("./cf-worker-abstract-sql.js"); const { env } = await import("cloudflare:test"); - return new CFWorkerSQLDatabase((env as Env).FP_D1); + return new CFWorkerSQLDatabase((env as Env).FP_BACKEND_D1); }, }, { @@ -43,7 +43,7 @@ function getSQLFlavours(): { name: string; factory: () => Promise } factory: async () => { const { CFDObjSQLDatabase } = await import("../backend/cf-dobj-abstract-sql.js"); const { env } = await import("cloudflare:test"); - return new CFDObjSQLDatabase(getDurableObject(env as Env)); + return new CFDObjSQLDatabase(getBackendDurableObject(env as Env)); }, }, ]; diff --git a/src/cloud/node-hono-server.ts b/src/cloud/node-hono-server.ts index 8e4162b7..53f75a1f 100644 --- a/src/cloud/node-hono-server.ts +++ b/src/cloud/node-hono-server.ts @@ -1,4 +1,4 @@ -import { UpgradeWebSocket, WSEvents } from "hono/ws"; +import { UpgradeWebSocket, WSContext, WSContextInit, WSEvents } from "hono/ws"; import { ConnMiddleware, HonoServerBase, HonoServerFactory, HonoServerImpl, RunTimeParams } from "./hono-server.js"; import { HttpHeader, URI } from "@adviser/cement"; import { Context, Hono } from "hono"; @@ -26,10 +26,28 @@ class NodeWSRoom implements WSRoom { constructor(sthis: SuperThis) { this.sthis = sthis; } - acceptConnection(ws: WebSocket): void { + acceptConnection(ws: WebSocket, wse: WSEvents): Promise { const id = this.sthis.nextId(12).str; wsConnections.set(id, ws); + + const wsCtx = new WSContext(ws as WSContextInit); + + ws.onerror = (err) => { + // console.log("onerror", err); + wse.onError?.(err, wsCtx); + }; + ws.onclose = (ev) => { + // console.log("onclose", ev); + wse.onClose?.(ev, wsCtx); + }; + ws.onmessage = (evt) => { + // console.log("onmessage", evt); + // wsCtx.send("Hellox from server"); + wse.onMessage?.(evt, wsCtx); + }; + ws.accept(); + return Promise.resolve(); } } diff --git a/src/cloud/ws-room.ts b/src/cloud/ws-room.ts index fe8538b7..ebe8e33b 100644 --- a/src/cloud/ws-room.ts +++ b/src/cloud/ws-room.ts @@ -1,3 +1,5 @@ +import { WSEvents } from "hono/ws"; + export interface WSRoom { - acceptConnection(ws: WebSocket): void; + acceptConnection(ws: WebSocket, wse: WSEvents): Promise; } diff --git a/src/coerce-binary.ts b/src/coerce-binary.ts index 5a4169b2..b76afc73 100644 --- a/src/coerce-binary.ts +++ b/src/coerce-binary.ts @@ -29,6 +29,7 @@ export function to_blob(input: ArrayBuffer | ArrayBufferView | Uint8Array | Blob } return new Blob([to_uint8(input)]); } + export function to_arraybuf(input: ArrayBuffer | ArrayBufferView | Uint8Array): ArrayBuffer { if (input instanceof ArrayBuffer) { return input; diff --git a/src/sql/v0.19/sqlite/libsql/sqlite-connection.ts b/src/sql/v0.19/sqlite/libsql/sqlite-connection.ts new file mode 100644 index 00000000..06f5a68d --- /dev/null +++ b/src/sql/v0.19/sqlite/libsql/sqlite-connection.ts @@ -0,0 +1,79 @@ +import type { Client } from "@libsql/client"; +import { KeyedResolvOnce, ResolveOnce, URI } from "@adviser/cement"; + +import { SQLOpts } from "../../../types.js"; +import { ensureSuperLog, SuperThis } from "@fireproof/core"; +import { ensureSQLOpts } from "../../../ensurer.js"; +import { Sqlite3Connection, TasteHandler } from "../../sqlite_factory.js"; + +class LS3Taste implements TasteHandler { + readonly taste = "libsql" as const; + + quoteTemplate(o: unknown): Record { + return o as Record; + } + toBlob(data: Uint8Array): unknown { + return Buffer.from(data); + } + fromBlob(data: unknown): Uint8Array { + return Uint8Array.from(data as Buffer); + } +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const onceImport = new ResolveOnce(); +const onceSQLiteConnections = new KeyedResolvOnce(); +export class V0_19LS3Connection extends Sqlite3Connection { + get client(): Client { + if (!this._client) { + throw this.logger.Error().Msg("client not connected").AsError(); + } + return this._client as Client; + } + + constructor(_sthis: SuperThis, url: URI, opts: Partial) { + const sthis = ensureSuperLog(_sthis, "V0_19LS3Connection", { url }); + super(sthis, url, ensureSQLOpts(sthis, url, opts), new LS3Taste()); + } + async connect(): Promise { + let fName = this.url.pathname; + if (!fName) { + throw this.logger.Error().Url(this.url).Msg("filename is empty").AsError(); + } + // const version = this.url.searchParams.get("version"); + // if (!version) { + // throw this.logger.Error().Str("url", this.url.toString()).Msg("version not found").AsError(); + // } + const hasName = this.url.getParam("name"); + if (hasName) { + fName = this.sthis.pathOps.join(fName, hasName); + if (!fName.endsWith(".sqlite")) { + fName += ".sqlite"; + } + } + this.logger.Debug().Str("filename", fName).Msg("to-connect"); + this._client = await onceSQLiteConnections.get(fName).once(async () => { + this.logger.Debug().Str("filename", fName).Msg("connect"); + const Sqlite3Database = await onceImport.once(async () => { + const sql = await import("better-sqlite3"); + return sql.default; + }); + if (hasName) { + await (await this.fs()).mkdir(this.sthis.pathOps.dirname(fName), { recursive: true }); + } + const db = new Sqlite3Database(fName, { + // verbose: console.log, + nativeBinding: "./node_modules/better-sqlite3/build/Release/better_sqlite3.node", + }); + // this.logger.Debug().Any("client", this.client).Msg("connected") + if (!db) { + throw this.logger.Error().Msg("connect failed").AsError(); + } + return db; + }); + } + async close(): Promise { + this.logger.Debug().Msg("close"); + await this.client.close(); + } +} diff --git a/src/sql/v0.19/sqlite_factory.ts b/src/sql/v0.19/sqlite_factory.ts index 3bc9e871..d32486d4 100644 --- a/src/sql/v0.19/sqlite_factory.ts +++ b/src/sql/v0.19/sqlite_factory.ts @@ -29,7 +29,7 @@ export async function v0_19sqliteMetaFactory(sthis: SuperThis, db: DBConnection) // prepare(sql: string): Sqlite3Statement; // } -export type Sqlite3Taste = "better-sqlite3" | "node-sqlite3-wasm"; +export type Sqlite3Taste = "better-sqlite3" | "node-sqlite3-wasm" | "libsql"; export interface TasteHandler { readonly taste: Sqlite3Taste; quoteTemplate(o: unknown): Record; @@ -68,6 +68,15 @@ export async function v0_19sqliteConnectionFactory( ): Promise { const upUrl = url.build().defParam("taste", "better-sqlite3").URI(); switch (upUrl.getParam("taste")) { + case "libsql": { + const { V0_19LS3Connection } = await import("./sqlite/libsql/sqlite-connection.js"); + sthis.logger.Debug().Str("databaseURL", upUrl.toString()).Msg("connecting to better-sqlite3"); + return { + dbConn: new V0_19LS3Connection(sthis, upUrl, opts), + url: upUrl.build().setParam("taste", "libsql").URI(), + }; + } + case "node-sqlite3-wasm": { const { V0_19NSWConnection } = await import("./sqlite/node-sqlite3-wasm/sqlite-connection.js"); sthis.logger.Debug().Str("databaseURL", upUrl.toString()).Msg("connecting to node-sqlite3-wasm"); diff --git a/tests/Dockerfile.connect-netlify b/tests/Dockerfile.connect-netlify index 403889e1..a436cd80 100644 --- a/tests/Dockerfile.connect-netlify +++ b/tests/Dockerfile.connect-netlify @@ -7,6 +7,7 @@ RUN curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh && deno #-- --no-modify-path --yes COPY src/netlify /usr/src/app/src/netlify COPY tests/connect-netlify/app /usr/src/app/tests/connect-netlify/app +COPY dist/netlify/server.js /usr/src/app/tests/connect-netlify/app/netlify/edge-functions/fireproof.js WORKDIR /usr/src/app/tests/connect-netlify/app RUN rm -rf node_modules && pnpm install && pnpm run copy-server && pnpm install -g netlify-cli CMD pnpm dev --no-open diff --git a/vitest.libsql.config.ts b/vitest.libsql.config.ts new file mode 100644 index 00000000..778772d7 --- /dev/null +++ b/vitest.libsql.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from "vitest/config"; + +import tsconfigPaths from "vite-tsconfig-paths"; + +export default defineConfig({ + plugins: [tsconfigPaths()], + test: { + name: "libsql", + include: ["src/sql/**/*test.?(c|m)[jt]s?(x)", "node_modules/@fireproof/core/tests/**/*test.?(c|m)[jt]s?(x)"], + exclude: [ + "node_modules/@fireproof/core/tests/react/**", + "node_modules/@fireproof/core/tests/fireproof/config.test.ts", + "node_modules/@fireproof/core/tests/fireproof/utils.test.ts", + ], + globals: true, + setupFiles: "./setup.libsql.ts", + }, +}); diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 54246881..a28908a4 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -3,6 +3,8 @@ import { defineWorkspace } from "vitest/config"; import aws from "./vitest.aws.config.ts"; import betterSqlite3 from "./vitest.better-sqlite3.config.ts"; // import nodeSqlite3Wasm from "./vitest.node-sqlite3-wasm.config.ts"; +import libsql from "./vitest.libsql.config.ts"; +// import nodeSqlite3Wasm from "./vitest.node-sqlite3-wasm.config.ts"; import partykit from "./vitest.partykit.config.ts"; import cloud from "./vitest.cloud.config.ts"; import s3 from "./vitest.s3.config.ts"; @@ -14,6 +16,7 @@ import cfWorker from "./vitest.cf-worker.config.ts"; export default defineWorkspace([ // nodeSqlite3Wasm, betterSqlite3, + libsql, // connector, s3, aws,