From bc47a8cabb19eece8cffeb16cb43316ccb33ad19 Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sat, 21 Mar 2026 22:29:58 +0900 Subject: [PATCH 1/5] Avoid multicodec in vocab-runtime Remove the CommonJS-only multicodec dependency from the multibase public key path in @fedify/vocab-runtime. This keeps key handling inside Fedify and avoids the Vite SSR crash that prevented Fresh 2 apps from importing @fedify/fedify without an externalization workaround. This also removes the temporary Fresh workaround from the example and integration guide, and updates the changelog for the regression. Fixes https://github.com/fedify-dev/fedify/issues/621 --- CHANGES.md | 10 + deno.lock | 231 ++++++++---------- docs/manual/integration.md | 25 -- examples/fresh/vite.config.ts | 12 - packages/fedify/deno.json | 1 - packages/fedify/package.json | 1 - packages/vocab-runtime/deno.json | 1 - packages/vocab-runtime/package.json | 1 - .../src/internal/multicodec.test.ts | 68 ++++++ .../vocab-runtime/src/internal/multicodec.ts | 53 ++++ packages/vocab-runtime/src/key.test.ts | 23 +- packages/vocab-runtime/src/key.ts | 17 +- packages/vocab/package.json | 1 - pnpm-lock.yaml | 84 +++---- 14 files changed, 297 insertions(+), 231 deletions(-) create mode 100644 packages/vocab-runtime/src/internal/multicodec.test.ts create mode 100644 packages/vocab-runtime/src/internal/multicodec.ts diff --git a/CHANGES.md b/CHANGES.md index e358a5fd5..905ef5d11 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,16 @@ Version 2.0.7 To be released. +### @fedify/vocab-runtime + + - Fixed multibase public key handling to stop relying on the deprecated + CommonJS-only `multicodec` package. This removes the Vite SSR crash that + prevented Fresh 2 applications from importing `@fedify/fedify` with + `TypeError: varint.encode is not a function`. Fresh 2 no longer needs a + Vite externalization workaround for Fedify. [[#621]] + +[#621]: https://github.com/fedify-dev/fedify/issues/621 + ### @fedify/init - Revived removed `fedify init` options. [[#632], [#638] by ChanHaeng Lee] diff --git a/deno.lock b/deno.lock index 0d9af5a51..046b2a4c2 100644 --- a/deno.lock +++ b/deno.lock @@ -68,12 +68,12 @@ "npm:@babel/core@^7.28.0": "7.29.0", "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0", "npm:@cfworker/json-schema@^4.1.1": "4.1.1", - "npm:@cloudflare/vitest-pool-workers@~0.8.31": "0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.10__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.10_@cloudflare+workers-types@4.20260210.0_tsx@4.21.0_yaml@2.8.2", + "npm:@cloudflare/vitest-pool-workers@~0.8.31": "0.8.71_vitest@3.2.4__@types+node@24.10.12_@types+node@24.10.12", "npm:@cloudflare/workers-types@^4.20250529.0": "4.20260210.0", "npm:@cloudflare/workers-types@^4.20250906.0": "4.20260210.0", "npm:@fxts/core@^1.21.1": "1.25.0", "npm:@hongminhee/localtunnel@0.3": "0.3.0", - "npm:@inquirer/prompts@^7.8.4": "7.10.1_@types+node@22.19.10", + "npm:@inquirer/prompts@^7.8.4": "7.10.1_@types+node@24.10.12", "npm:@jimp/core@^1.6.0": "1.6.0", "npm:@jimp/wasm-webp@^1.6.0": "1.6.0", "npm:@js-temporal/polyfill@~0.5.1": "0.5.1", @@ -87,11 +87,11 @@ "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", - "npm:@preact/signals@^2.2.1": "2.7.1_preact@10.19.6", - "npm:@preact/signals@^2.3.2": "2.7.1_preact@10.19.6", - "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2", + "npm:@preact/signals@^2.2.1": "2.7.1_preact@10.28.3", + "npm:@preact/signals@^2.3.2": "2.7.1_preact@10.28.3", + "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.28.3_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12", "npm:@standard-schema/spec@^1.1.0": "1.1.0", - "npm:@sveltejs/kit@2": "2.50.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2", + "npm:@sveltejs/kit@2": "2.50.2_@opentelemetry+api@1.9.0_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12", "npm:@types/amqplib@*": "0.10.8", "npm:@types/amqplib@~0.10.7": "0.10.8", "npm:@types/eslint@9": "9.6.1", @@ -127,20 +127,20 @@ "npm:hono@^4.8.3": "4.11.3", "npm:icojs@~0.19.5": "0.19.5", "npm:inquirer-toggle@^1.0.1": "1.0.1", - "npm:inquirer@^12.9.4": "12.11.1_@types+node@22.19.10", + "npm:inquirer@^12.9.4": "12.11.1_@types+node@24.10.12", "npm:ioredis@^5.8.2": "5.9.2", "npm:jimp@^1.6.0": "1.6.0", "npm:json-canon@^1.0.1": "1.0.1", "npm:json-preserve-indent@^1.1.3": "1.1.3", + "npm:jsonld@*": "9.0.0", "npm:jsonld@9": "9.0.0", "npm:koa@2": "2.16.3", "npm:miniflare@^4.20250523.0": "4.20250906.0", - "npm:multicodec@^3.2.1": "3.2.1", "npm:ora@^8.2.0": "8.2.0", "npm:pkijs@^3.2.5": "3.3.3", "npm:pkijs@^3.3.3": "3.3.3", "npm:postgres@^3.4.7": "3.4.8", - "npm:preact-render-to-string@^6.6.3": "6.6.5_preact@10.19.6", + "npm:preact-render-to-string@^6.6.3": "6.6.5_preact@10.28.3", "npm:preact@10.19.6": "10.19.6", "npm:preact@^10.27.0": "10.28.3", "npm:preact@^10.27.2": "10.28.3", @@ -154,9 +154,9 @@ "npm:uri-template-router@1": "1.0.0", "npm:url-template@^3.1.1": "3.1.1", "npm:valibot@^1.2.0": "1.2.0", - "npm:vite@^7.1.3": "7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vite@^7.1.4": "7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vitest@3.2": "3.2.4_@types+node@22.19.10_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", + "npm:vite@^7.1.3": "7.3.1_@types+node@24.10.12_tsx@4.21.0_yaml@2.8.2", + "npm:vite@^7.1.4": "7.3.1_@types+node@24.10.12_tsx@4.21.0_yaml@2.8.2", + "npm:vitest@3.2": "3.2.4_@types+node@24.10.12", "npm:wrangler@^4.17.0": "4.35.0_@cloudflare+workers-types@4.20260210.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", "npm:wrangler@^4.21.1": "4.35.0_@cloudflare+workers-types@4.20260210.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", "npm:yaml@^2.8.1": "2.8.2" @@ -654,7 +654,7 @@ "workerd" ] }, - "@cloudflare/vitest-pool-workers@0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.10__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.10_@cloudflare+workers-types@4.20260210.0_tsx@4.21.0_yaml@2.8.2": { + "@cloudflare/vitest-pool-workers@0.8.71_vitest@3.2.4__@types+node@24.10.12_@types+node@24.10.12": { "integrity": "sha512-keu2HCLQfRNwbmLBCDXJgCFpANTaYnQpE01fBOo4CNwiWHUT7SZGN7w64RKiSWRHyYppStXBuE5Ng7F42+flpg==", "dependencies": [ "@vitest/runner", @@ -1489,38 +1489,38 @@ "@inquirer/ansi@1.0.2": { "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==" }, - "@inquirer/checkbox@4.3.2_@types+node@22.19.10": { + "@inquirer/checkbox@4.3.2_@types+node@24.10.12": { "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/confirm@5.1.21_@types+node@22.19.10": { + "@inquirer/confirm@5.1.21_@types+node@24.10.12": { "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10" + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/core@10.3.2_@types+node@22.19.10": { + "@inquirer/core@10.3.2_@types+node@24.10.12": { "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dependencies": [ "@inquirer/ansi", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "cli-width", "mute-stream@2.0.0", "signal-exit", @@ -1528,7 +1528,7 @@ "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, "@inquirer/core@8.2.4": { @@ -1549,79 +1549,79 @@ "wrap-ansi@6.2.0" ] }, - "@inquirer/editor@4.2.23_@types+node@22.19.10": { + "@inquirer/editor@4.2.23_@types+node@24.10.12": { "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", "@inquirer/external-editor", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10" + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/expand@4.0.23_@types+node@22.19.10": { + "@inquirer/expand@4.0.23_@types+node@24.10.12": { "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/external-editor@1.0.3_@types+node@22.19.10": { + "@inquirer/external-editor@1.0.3_@types+node@24.10.12": { "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "dependencies": [ - "@types/node@22.19.10", + "@types/node@24.10.12", "chardet", "iconv-lite@0.7.2" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, "@inquirer/figures@1.0.15": { "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==" }, - "@inquirer/input@4.3.1_@types+node@22.19.10": { + "@inquirer/input@4.3.1_@types+node@24.10.12": { "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10" + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/number@3.0.23_@types+node@22.19.10": { + "@inquirer/number@3.0.23_@types+node@24.10.12": { "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10" + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/password@4.0.23_@types+node@22.19.10": { + "@inquirer/password@4.0.23_@types+node@24.10.12": { "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10" + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/prompts@7.10.1_@types+node@22.19.10": { + "@inquirer/prompts@7.10.1_@types+node@24.10.12": { "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dependencies": [ "@inquirer/checkbox", @@ -1634,49 +1634,49 @@ "@inquirer/rawlist", "@inquirer/search", "@inquirer/select", - "@types/node@22.19.10" + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/rawlist@4.1.11_@types+node@22.19.10": { + "@inquirer/rawlist@4.1.11_@types+node@24.10.12": { "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/search@3.2.2_@types+node@22.19.10": { + "@inquirer/search@3.2.2_@types+node@24.10.12": { "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, - "@inquirer/select@4.4.2_@types+node@22.19.10": { + "@inquirer/select@4.4.2_@types+node@24.10.12": { "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, "@inquirer/type@1.5.5": { @@ -1685,13 +1685,13 @@ "mute-stream@1.0.0" ] }, - "@inquirer/type@3.0.10_@types+node@22.19.10": { + "@inquirer/type@3.0.10_@types+node@24.10.12": { "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", "dependencies": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, "@ioredis/commands@1.5.0": { @@ -2144,26 +2144,26 @@ "@preact/signals-core@1.13.0": { "integrity": "sha512-slT6XeTCAbdql61GVLlGU4x7XHI7kCZV5Um5uhE4zLX4ApgiiXc0UYFvVOKq06xcovzp7p+61l68oPi563ARKg==" }, - "@preact/signals@2.7.1_preact@10.19.6": { + "@preact/signals@2.7.1_preact@10.28.3": { "integrity": "sha512-mP2+wMYHqDXVKFGzjqkL6CiHj3okB8eVTTJUZBrSVGozi/XfA+zZRCEALKKZYRoSoqLyT4J6qM4lhwT9155s1Q==", "dependencies": [ "@preact/signals-core", - "preact@10.19.6" + "preact@10.28.3" ] }, "@prefresh/babel-plugin@0.5.2": { "integrity": "sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==" }, - "@prefresh/core@1.5.9_preact@10.19.6": { + "@prefresh/core@1.5.9_preact@10.28.3": { "integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==", "dependencies": [ - "preact@10.19.6" + "preact@10.28.3" ] }, "@prefresh/utils@1.2.1": { "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" }, - "@prefresh/vite@2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "@prefresh/vite@2.4.11_preact@10.28.3_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==", "dependencies": [ "@babel/core", @@ -2171,7 +2171,7 @@ "@prefresh/core", "@prefresh/utils", "@rollup/pluginutils", - "preact@10.19.6", + "preact@10.28.3", "vite" ] }, @@ -2519,7 +2519,7 @@ "acorn@8.15.0" ] }, - "@sveltejs/kit@2.50.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "@sveltejs/kit@2.50.2_@opentelemetry+api@1.9.0_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==", "dependencies": [ "@opentelemetry/api", @@ -2545,7 +2545,7 @@ ], "bin": true }, - "@sveltejs/vite-plugin-svelte-inspector@5.0.2_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "@sveltejs/vite-plugin-svelte-inspector@5.0.2_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@24.10.12___tsx@4.21.0___yaml@2.8.2__@types+node@24.10.12_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", "dependencies": [ "@sveltejs/vite-plugin-svelte", @@ -2554,7 +2554,7 @@ "vite" ] }, - "@sveltejs/vite-plugin-svelte@6.2.4_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "@sveltejs/vite-plugin-svelte@6.2.4_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "dependencies": [ "@sveltejs/vite-plugin-svelte-inspector", @@ -2745,7 +2745,7 @@ "tinyrainbow" ] }, - "@vitest/mocker@3.2.4_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "@vitest/mocker@3.2.4_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dependencies": [ "@vitest/spy", @@ -4047,20 +4047,20 @@ "@inquirer/core@8.2.4" ] }, - "inquirer@12.11.1_@types+node@22.19.10": { + "inquirer@12.11.1_@types+node@24.10.12": { "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/core@10.3.2_@types+node@24.10.12", "@inquirer/prompts", - "@inquirer/type@3.0.10_@types+node@22.19.10", - "@types/node@22.19.10", + "@inquirer/type@3.0.10_@types+node@24.10.12", + "@types/node@24.10.12", "mute-stream@2.0.0", "run-async", "rxjs" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ] }, "ioredis@5.9.2": { @@ -4481,17 +4481,6 @@ "ms@2.1.3": { "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "multicodec@3.2.1": { - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dependencies": [ - "uint8arrays", - "varint" - ], - "deprecated": true - }, - "multiformats@9.9.0": { - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" - }, "mute-stream@1.0.0": { "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==" }, @@ -4747,10 +4736,10 @@ "postgres@3.4.8": { "integrity": "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==" }, - "preact-render-to-string@6.6.5_preact@10.19.6": { + "preact-render-to-string@6.6.5_preact@10.28.3": { "integrity": "sha512-O6MHzYNIKYaiSX3bOw0gGZfEbOmlIDtDfWwN1JJdc/T3ihzRT6tGGSEWE088dWrEDGa1u7101q+6fzQnO9XCPA==", "dependencies": [ - "preact@10.19.6" + "preact@10.28.3" ] }, "preact@10.19.6": { @@ -5521,12 +5510,6 @@ "uint8array-extras@1.5.0": { "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==" }, - "uint8arrays@3.1.1": { - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "dependencies": [ - "multiformats" - ] - }, "unconfig-core@7.4.2": { "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", "dependencies": [ @@ -5642,9 +5625,6 @@ "valibot@1.2.0": { "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==" }, - "varint@6.0.0": { - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" - }, "vary@1.1.2": { "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, @@ -5662,7 +5642,7 @@ "vfile-message" ] }, - "vite-node@3.2.4_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "vite-node@3.2.4_@types+node@24.10.12": { "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dependencies": [ "cac", @@ -5673,10 +5653,10 @@ ], "bin": true }, - "vite@7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3": { + "vite@7.3.1_@types+node@24.10.12_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dependencies": [ - "@types/node@22.19.10", + "@types/node@24.10.12", "esbuild@0.27.3", "fdir", "picomatch@4.0.3", @@ -5690,13 +5670,13 @@ "fsevents" ], "optionalPeers": [ - "@types/node@22.19.10", + "@types/node@24.10.12", "tsx", "yaml" ], "bin": true }, - "vitefu@1.1.1_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "vitefu@1.1.1_vite@7.3.1__@types+node@24.10.12__tsx@4.21.0__yaml@2.8.2_@types+node@24.10.12": { "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", "dependencies": [ "vite" @@ -5705,11 +5685,11 @@ "vite" ] }, - "vitest@3.2.4_@types+node@22.19.10_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2": { + "vitest@3.2.4_@types+node@24.10.12": { "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dependencies": [ "@types/chai", - "@types/node@22.19.10", + "@types/node@24.10.12", "@vitest/expect", "@vitest/mocker", "@vitest/pretty-format", @@ -5734,7 +5714,7 @@ "why-is-node-running" ], "optionalPeers": [ - "@types/node@22.19.10" + "@types/node@24.10.12" ], "bin": true }, @@ -6048,7 +6028,6 @@ "npm:fetch-mock@^12.5.2", "npm:json-canon@^1.0.1", "npm:jsonld@9", - "npm:multicodec@^3.2.1", "npm:pkijs@^3.3.3", "npm:structured-field-values@^2.0.4", "npm:uri-template-router@1", @@ -6062,7 +6041,6 @@ "npm:json-canon@^1.0.1", "npm:jsonld@9", "npm:miniflare@^4.20250523.0", - "npm:multicodec@^3.2.1", "npm:structured-field-values@^2.0.4", "npm:tsx@^4.19.4", "npm:uri-template-router@1", @@ -6139,8 +6117,7 @@ ], "packageJson": { "dependencies": [ - "npm:jsonld@9", - "npm:multicodec@^3.2.1" + "npm:jsonld@9" ] } }, @@ -6150,13 +6127,11 @@ "npm:asn1js@^3.0.6", "npm:byte-encodings@^1.0.11", "npm:fetch-mock@^12.5.4", - "npm:multicodec@^3.2.1", "npm:pkijs@^3.2.5" ], "packageJson": { "dependencies": [ - "npm:@types/node@^24.2.1", - "npm:multicodec@^3.2.1" + "npm:@types/node@^24.2.1" ] } }, diff --git a/docs/manual/integration.md b/docs/manual/integration.md index c0f49f674..7d5fb2add 100644 --- a/docs/manual/integration.md +++ b/docs/manual/integration.md @@ -795,31 +795,6 @@ deno add jsr:@fedify/fresh > [!NOTE] > The `@fedify/fresh` package only supports Fresh 2.x. -> [!WARNING] -> Due to `@fedify/fedify`'s `multicodec` dependency CJS issue, you should -> externalize `@fedify/fedify` in `vite.config.ts`. -> -> ~~~~ typescript -> import { fresh } from "@fresh/plugin-vite"; -> import { defineConfig } from "vite"; -> -> export default defineConfig({ -> plugins: [fresh()], -> ssr: { -> external: [ -> "@fedify/fedify", -> ], -> }, -> build: { -> rollupOptions: { -> external: [ -> "@fedify/fedify", -> ], -> }, -> }, -> }); -> ~~~~ - > [!WARNING] > Due to `@fedify/fedify` use `Temporal` inside, you should add `deno.unstable` > to `compilerOptions.libs` field of `deno.json`. diff --git a/examples/fresh/vite.config.ts b/examples/fresh/vite.config.ts index eeff3645e..b5e505459 100644 --- a/examples/fresh/vite.config.ts +++ b/examples/fresh/vite.config.ts @@ -3,16 +3,4 @@ import { defineConfig } from "vite"; export default defineConfig({ plugins: [fresh()], - ssr: { - external: [ - "@fedify/fedify", - ], - }, - build: { - rollupOptions: { - external: [ - "@fedify/fedify", - ], - }, - }, }); diff --git a/packages/fedify/deno.json b/packages/fedify/deno.json index 99993c5ca..1bceec75a 100644 --- a/packages/fedify/deno.json +++ b/packages/fedify/deno.json @@ -22,7 +22,6 @@ "fetch-mock": "npm:fetch-mock@^12.5.2", "json-canon": "npm:json-canon@^1.0.1", "jsonld": "npm:jsonld@^9.0.0", - "multicodec": "npm:multicodec@^3.2.1", "pkijs": "npm:pkijs@^3.3.3", "structured-field-values": "npm:structured-field-values@^2.0.4", "uri-template-router": "npm:uri-template-router@^1.0.0", diff --git a/packages/fedify/package.json b/packages/fedify/package.json index f827ba73a..108688391 100644 --- a/packages/fedify/package.json +++ b/packages/fedify/package.json @@ -143,7 +143,6 @@ "es-toolkit": "catalog:", "json-canon": "^1.0.1", "jsonld": "^9.0.0", - "multicodec": "^3.2.1", "structured-field-values": "^2.0.4", "uri-template-router": "^1.0.0", "url-template": "^3.1.1", diff --git a/packages/vocab-runtime/deno.json b/packages/vocab-runtime/deno.json index 16f9d6795..f6ef8d898 100644 --- a/packages/vocab-runtime/deno.json +++ b/packages/vocab-runtime/deno.json @@ -16,7 +16,6 @@ "asn1js": "npm:asn1js@^3.0.6", "byte-encodings": "npm:byte-encodings@^1.0.11", "fetch-mock": "npm:fetch-mock@^12.5.4", - "multicodec": "npm:multicodec@^3.2.1", "pkijs": "npm:pkijs@^3.2.5" }, "exclude": [ diff --git a/packages/vocab-runtime/package.json b/packages/vocab-runtime/package.json index 1066f78f2..c88a4fc9e 100644 --- a/packages/vocab-runtime/package.json +++ b/packages/vocab-runtime/package.json @@ -68,7 +68,6 @@ "@opentelemetry/api": "catalog:", "asn1js": "catalog:", "byte-encodings": "catalog:", - "multicodec": "^3.2.1", "pkijs": "catalog:" } } diff --git a/packages/vocab-runtime/src/internal/multicodec.test.ts b/packages/vocab-runtime/src/internal/multicodec.test.ts new file mode 100644 index 000000000..973015d90 --- /dev/null +++ b/packages/vocab-runtime/src/internal/multicodec.test.ts @@ -0,0 +1,68 @@ +import { deepStrictEqual, throws } from "node:assert"; +import { test } from "node:test"; +import { + addMulticodecPrefix, + getMulticodecPrefix, + removeMulticodecPrefix, +} from "./multicodec.ts"; + +test("getMulticodecPrefix() decodes supported multicodec prefixes", () => { + deepStrictEqual( + getMulticodecPrefix(Uint8Array.from([0xed, 0x01, 0xaa])), + { code: 0xed, prefixLength: 2 }, + ); + deepStrictEqual( + getMulticodecPrefix(Uint8Array.from([0x85, 0x24, 0xaa])), + { code: 0x1205, prefixLength: 2 }, + ); +}); + +test("removeMulticodecPrefix() strips the varint prefix", () => { + deepStrictEqual( + removeMulticodecPrefix(Uint8Array.from([0xed, 0x01, 0x11, 0x22])), + Uint8Array.from([0x11, 0x22]), + ); +}); + +test("addMulticodecPrefix() prepends the varint-encoded code", () => { + deepStrictEqual( + addMulticodecPrefix(0xed, Uint8Array.from([0x11, 0x22])), + Uint8Array.from([0xed, 0x01, 0x11, 0x22]), + ); + deepStrictEqual( + addMulticodecPrefix(0x1205, Uint8Array.from([0x11, 0x22])), + Uint8Array.from([0x85, 0x24, 0x11, 0x22]), + ); +}); + +test("multicodec helpers round-trip prefixed payloads", () => { + const payload = Uint8Array.from([0xde, 0xad, 0xbe, 0xef]); + const prefixed = addMulticodecPrefix(0x1205, payload); + deepStrictEqual(getMulticodecPrefix(prefixed), { + code: 0x1205, + prefixLength: 2, + }); + deepStrictEqual(removeMulticodecPrefix(prefixed), payload); +}); + +test("multicodec helpers reject malformed prefixes", () => { + throws( + () => getMulticodecPrefix(new Uint8Array([])), + new TypeError("Invalid multicodec prefix."), + ); + throws( + () => getMulticodecPrefix(Uint8Array.from([0x80])), + new TypeError("Invalid multicodec prefix."), + ); + throws( + () => + getMulticodecPrefix( + Uint8Array.from([0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80]), + ), + new TypeError("Invalid multicodec prefix."), + ); + throws( + () => addMulticodecPrefix(-1, Uint8Array.from([0x00])), + new TypeError("Invalid multicodec code."), + ); +}); diff --git a/packages/vocab-runtime/src/internal/multicodec.ts b/packages/vocab-runtime/src/internal/multicodec.ts new file mode 100644 index 000000000..c930de0a4 --- /dev/null +++ b/packages/vocab-runtime/src/internal/multicodec.ts @@ -0,0 +1,53 @@ +const INVALID_MULTICODEC_PREFIX = "Invalid multicodec prefix."; + +export interface MulticodecPrefix { + code: number; + prefixLength: number; +} + +export function getMulticodecPrefix( + data: Uint8Array, +): MulticodecPrefix { + if (data.length < 1) throw new TypeError(INVALID_MULTICODEC_PREFIX); + let code = 0; + let shift = 0; + for (let i = 0; i < data.length; i++) { + const byte = data[i]; + code += (byte & 0x7f) * 2 ** shift; + if (code > Number.MAX_SAFE_INTEGER) { + throw new TypeError(INVALID_MULTICODEC_PREFIX); + } + if ((byte & 0x80) === 0) { + return { code, prefixLength: i + 1 }; + } + shift += 7; + if (shift >= 53) throw new TypeError(INVALID_MULTICODEC_PREFIX); + } + throw new TypeError(INVALID_MULTICODEC_PREFIX); +} + +export function removeMulticodecPrefix(data: Uint8Array): Uint8Array { + const { prefixLength } = getMulticodecPrefix(data); + return data.slice(prefixLength); +} + +export function addMulticodecPrefix( + code: number, + payload: Uint8Array, +): Uint8Array { + if (!Number.isSafeInteger(code) || code < 0) { + throw new TypeError("Invalid multicodec code."); + } + const prefix: number[] = []; + let value = code; + do { + let byte = value & 0x7f; + value = Math.floor(value / 0x80); + if (value > 0) byte |= 0x80; + prefix.push(byte); + } while (value > 0); + const prefixed = new Uint8Array(prefix.length + payload.length); + prefixed.set(prefix); + prefixed.set(payload, prefix.length); + return prefixed; +} diff --git a/packages/vocab-runtime/src/key.test.ts b/packages/vocab-runtime/src/key.test.ts index 9c4b03f2b..7c423b2db 100644 --- a/packages/vocab-runtime/src/key.test.ts +++ b/packages/vocab-runtime/src/key.test.ts @@ -1,4 +1,4 @@ -import { deepStrictEqual } from "node:assert"; +import { deepStrictEqual, rejects } from "node:assert"; import { test } from "node:test"; import { exportJwk, importJwk } from "./jwk.ts"; import { @@ -9,6 +9,7 @@ import { importPkcs1, importSpki, } from "./key.ts"; +import { encodeMultibase } from "./multibase/mod.ts"; // cSpell: disable const rsaSpki = "-----BEGIN PUBLIC KEY-----\n" + @@ -122,6 +123,26 @@ test("importMultibase()", async () => { deepStrictEqual(await exportJwk(ed25519Key), ed25519Jwk); }); +test("importMultibase() rejects malformed multicodec prefixes", async () => { + const decoder = new TextDecoder(); + await rejects( + () => + importMultibaseKey( + decoder.decode(encodeMultibase("base58btc", new Uint8Array([]))), + ), + new TypeError("Invalid multicodec prefix."), + ); + await rejects( + () => + importMultibaseKey( + decoder.decode( + encodeMultibase("base58btc", Uint8Array.from([0x80])), + ), + ), + new TypeError("Invalid multicodec prefix."), + ); +}); + test("exportMultibaseKey()", async () => { const rsaKey = await importJwk(rsaJwk, "public"); const rsaMb = await exportMultibaseKey(rsaKey); diff --git a/packages/vocab-runtime/src/key.ts b/packages/vocab-runtime/src/key.ts index d4fecc07d..3e7f4e749 100644 --- a/packages/vocab-runtime/src/key.ts +++ b/packages/vocab-runtime/src/key.ts @@ -1,10 +1,13 @@ import { Integer, Sequence } from "asn1js"; import { decodeBase64, encodeBase64 } from "byte-encodings/base64"; import { decodeBase64Url } from "byte-encodings/base64url"; -import { decodeHex } from "byte-encodings/hex"; -import { addPrefix, getCodeFromData, rmPrefix } from "multicodec"; import { createPublicKey } from "node:crypto"; import { PublicKeyInfo } from "pkijs"; +import { + addMulticodecPrefix, + getMulticodecPrefix, + removeMulticodecPrefix, +} from "./internal/multicodec.ts"; import { validateCryptoKey } from "./jwk.ts"; import { decodeMultibase, encodeMultibase } from "./multibase/mod.ts"; @@ -101,8 +104,8 @@ export function importPem(pem: string): Promise { */ export async function importMultibaseKey(key: string): Promise { const decoded = decodeMultibase(key); - const code: number = getCodeFromData(decoded); - const content = rmPrefix(decoded); + const { code } = getMulticodecPrefix(decoded); + const content = removeMulticodecPrefix(decoded); if (code === 0x1205) { // rsa-pub const keyObject = createPublicKey({ // deno-lint-ignore no-explicit-any @@ -177,11 +180,9 @@ export async function exportMultibaseKey(key: CryptoKey): Promise { "Unsupported key type: " + JSON.stringify(key.algorithm), ); } - const codeHex = code.toString(16); - const codeBytes = decodeHex(codeHex.length % 2 < 1 ? codeHex : "0" + codeHex); - const prefixed = addPrefix(codeBytes, new Uint8Array(content)); + const prefixed = addMulticodecPrefix(code, new Uint8Array(content)); const encoded = encodeMultibase("base58btc", prefixed); return new TextDecoder().decode(encoded); } -// cSpell: ignore multicodec pkijs +// cSpell: ignore pkijs diff --git a/packages/vocab/package.json b/packages/vocab/package.json index 01e0d8ea2..e69d331ff 100644 --- a/packages/vocab/package.json +++ b/packages/vocab/package.json @@ -48,7 +48,6 @@ "es-toolkit": "catalog:", "@fedify/vocab-runtime": "workspace:*", "jsonld": "^9.0.0", - "multicodec": "^3.2.1", "pkijs": "catalog:" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a92e27611..0fb01fc26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1038,9 +1038,6 @@ importers: jsonld: specifier: ^9.0.0 version: 9.0.0 - multicodec: - specifier: ^3.2.1 - version: 3.2.1 structured-field-values: specifier: ^2.0.4 version: 2.0.4 @@ -1476,9 +1473,6 @@ importers: jsonld: specifier: ^9.0.0 version: 9.0.0 - multicodec: - specifier: ^3.2.1 - version: 3.2.1 pkijs: specifier: 'catalog:' version: 3.3.3 @@ -1519,9 +1513,6 @@ importers: byte-encodings: specifier: 'catalog:' version: 1.0.11 - multicodec: - specifier: ^3.2.1 - version: 3.2.1 pkijs: specifier: 'catalog:' version: 3.3.3 @@ -7288,13 +7279,6 @@ packages: muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} - multicodec@3.2.1: - resolution: {integrity: sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==} - deprecated: This module has been superseded by the multiformats module - - multiformats@9.9.0: - resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} - mustache@4.2.0: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true @@ -8750,9 +8734,6 @@ packages: resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==} engines: {node: '>=18'} - uint8arrays@3.1.1: - resolution: {integrity: sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==} - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -8853,9 +8834,6 @@ packages: typescript: optional: true - varint@6.0.0: - resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -13893,8 +13871,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13913,8 +13891,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13937,22 +13915,22 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 - eslint: 8.57.1 + eslint: 9.32.0(jiti@2.5.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -13963,7 +13941,22 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.1 + eslint: 8.57.1 + get-tsconfig: 4.10.1 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -13978,25 +13971,25 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -14029,7 +14022,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -14040,7 +14033,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -14058,7 +14051,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -14069,7 +14062,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -15802,13 +15795,6 @@ snapshots: muggle-string@0.4.1: {} - multicodec@3.2.1: - dependencies: - uint8arrays: 3.1.1 - varint: 6.0.0 - - multiformats@9.9.0: {} - mustache@4.2.0: {} mute-stream@1.0.0: {} @@ -17375,10 +17361,6 @@ snapshots: uint8array-extras@1.4.0: {} - uint8arrays@3.1.1: - dependencies: - multiformats: 9.9.0 - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -17517,8 +17499,6 @@ snapshots: optionalDependencies: typescript: 5.9.3 - varint@6.0.0: {} - vary@1.1.2: {} vfile-message@4.0.2: From 43619175c649866c211c9f2f35d09d9c0098443f Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sat, 21 Mar 2026 22:42:28 +0900 Subject: [PATCH 2/5] Use jsonld ESM entrypoint in source Switch the source-facing JSON-LD imports used by Fedify to the package's ESM entrypoint so Deno, Cloudflare Workers, and other source-based runtimes do not have to go through CommonJS interop. This also updates the code generator regression test and the Fresh example used for manual verification. https://github.com/fedify-dev/fedify/issues/621 --- CHANGES.md | 7 +++ deno.lock | 2 + examples/fresh/federation.ts | 43 +++++++++++-------- packages/fedify/src/sig/ld.ts | 3 +- .../src/__snapshots__/class.test.ts.deno.snap | 2 +- .../src/__snapshots__/class.test.ts.node.snap | 2 +- .../src/__snapshots__/class.test.ts.snap | 2 +- packages/vocab-tools/src/class.test.ts | 7 ++- packages/vocab-tools/src/class.ts | 2 +- 9 files changed, 47 insertions(+), 23 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 905ef5d11..93425272d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,13 @@ To be released. [#621]: https://github.com/fedify-dev/fedify/issues/621 +### @fedify/fedify + + - Switched Fedify's JSR-facing JSON-LD imports to jsonld's ESM entrypoint + so source-based runtimes such as Deno, Cloudflare Workers, and Fresh 2's + Vite SSR pipeline do not have to evaluate the package through CommonJS + interop when loading Linked Data signature support. [[#621]] + ### @fedify/init - Revived removed `fedify init` options. [[#632], [#638] by ChanHaeng Lee] diff --git a/deno.lock b/deno.lock index 046b2a4c2..344652413 100644 --- a/deno.lock +++ b/deno.lock @@ -50,6 +50,7 @@ "jsr:@std/json@^1.0.2": "1.0.2", "jsr:@std/jsonc@^1.0.2": "1.0.2", "jsr:@std/media-types@^1.1.0": "1.1.0", + "jsr:@std/path@*": "1.1.4", "jsr:@std/path@0.224": "0.224.0", "jsr:@std/path@1": "1.1.4", "jsr:@std/path@^1.0.4": "1.1.4", @@ -59,6 +60,7 @@ "jsr:@std/path@^1.1.2": "1.1.4", "jsr:@std/path@^1.1.4": "1.1.4", "jsr:@std/semver@^1.0.6": "1.0.8", + "jsr:@std/testing@*": "0.224.0", "jsr:@std/testing@0.224": "0.224.0", "jsr:@std/url@~0.225.1": "0.225.1", "jsr:@std/uuid@^1.0.9": "1.1.0", diff --git a/examples/fresh/federation.ts b/examples/fresh/federation.ts index 0b5d79af6..33dabaa93 100644 --- a/examples/fresh/federation.ts +++ b/examples/fresh/federation.ts @@ -1,4 +1,5 @@ import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // Create the federation instance export const federation = createFederation({ @@ -6,21 +7,29 @@ export const federation = createFederation({ }); // Set up a NodeInfo dispatcher for the federation instance -federation - .setNodeInfoDispatcher("/nodeinfo/2.1", () => { - return { - software: { - name: "fresh-example", // Lowercase, digits, and hyphens only. - version: "1.0.0", - homepage: new URL("https://your-software.com/"), - }, - protocols: ["activitypub"], - usage: { - // Usage statistics is hard-coded here for demonstration purposes. - // You should replace these with real statistics: - users: { total: 100, activeHalfyear: 50, activeMonth: 20 }, - localPosts: 1000, - localComments: 2000, - }, - }; +federation.setNodeInfoDispatcher("/nodeinfo/2.1", () => { + return { + software: { + name: "fresh-example", // Lowercase, digits, and hyphens only. + version: "1.0.0", + homepage: new URL("https://your-software.com/"), + }, + protocols: ["activitypub"], + usage: { + // Usage statistics is hard-coded here for demonstration purposes. + // You should replace these with real statistics: + users: { total: 100, activeHalfyear: 50, activeMonth: 20 }, + localPosts: 1000, + localComments: 2000, + }, + }; +}); + +federation.setActorDispatcher("/users/{identifier}", (ctx, identifier) => { + if (identifier !== "sample") return null; + return new Person({ + id: ctx.getActorUri(identifier), + name: "Sample", + preferredUsername: identifier, }); +}); diff --git a/packages/fedify/src/sig/ld.ts b/packages/fedify/src/sig/ld.ts index 120bb6f09..be4fc86b2 100644 --- a/packages/fedify/src/sig/ld.ts +++ b/packages/fedify/src/sig/ld.ts @@ -4,7 +4,8 @@ import { getLogger } from "@logtape/logtape"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; import { decodeBase64, encodeBase64 } from "byte-encodings/base64"; import { encodeHex } from "byte-encodings/hex"; -import jsonld from "jsonld"; +// @ts-ignore TS7016 +import jsonld from "jsonld/dist/jsonld.esm.js"; import metadata from "../../deno.json" with { type: "json" }; import { fetchKey, type KeyCache, validateCryptoKey } from "./key.ts"; diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap index 29f7be5ad..20d07201c 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap @@ -3,7 +3,7 @@ export const snapshot = {}; snapshot[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const // @ts-ignore TS7016 -import jsonld from \\"jsonld\\"; +import jsonld from \\"jsonld/dist/jsonld.esm.js\\"; import { getLogger } from \\"@logtape/logtape\\"; import { type Span, SpanStatusCode, type TracerProvider, trace } from \\"@opentelemetry/api\\"; diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap index 9da6f60f3..6f1239e2f 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap @@ -1,7 +1,7 @@ exports[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const // @ts-ignore TS7016 -import jsonld from \\"jsonld\\"; +import jsonld from \\"jsonld/dist/jsonld.esm.js\\"; import { getLogger } from \\"@logtape/logtape\\"; import { type Span, SpanStatusCode, type TracerProvider, trace } from \\"@opentelemetry/api\\"; diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.snap index 677e3f441..30a44df36 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.snap @@ -3,7 +3,7 @@ exports[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const // @ts-ignore TS7016 -import jsonld from "jsonld"; +import jsonld from "jsonld/dist/jsonld.esm.js"; import { getLogger } from "@logtape/logtape"; import { type Span, SpanStatusCode, type TracerProvider, trace } from "@opentelemetry/api"; diff --git a/packages/vocab-tools/src/class.test.ts b/packages/vocab-tools/src/class.test.ts index 9f6d8018d..ddf0fbe0a 100644 --- a/packages/vocab-tools/src/class.test.ts +++ b/packages/vocab-tools/src/class.test.ts @@ -1,4 +1,4 @@ -import { deepStrictEqual } from "node:assert"; +import { deepStrictEqual, match } from "node:assert"; import { basename, dirname, extname, join } from "node:path"; import { test } from "node:test"; import metadata from "../deno.json" with { type: "json" }; @@ -64,6 +64,11 @@ test("sortTopologically()", () => { ); }); +test("generateClasses() imports the browser-safe jsonld entrypoint", async () => { + const entireCode = await getEntireCode(); + match(entireCode, /import jsonld from "jsonld\/dist\/jsonld\.esm\.js";/); +}); + if ("Deno" in globalThis) { const { assertSnapshot } = await import("@std/testing/snapshot"); Deno.test("generateClasses()", async (t) => { diff --git a/packages/vocab-tools/src/class.ts b/packages/vocab-tools/src/class.ts index ea544dd1a..e33a3a304 100644 --- a/packages/vocab-tools/src/class.ts +++ b/packages/vocab-tools/src/class.ts @@ -119,7 +119,7 @@ export async function* generateClasses( ): AsyncIterable { yield "// deno-lint-ignore-file ban-unused-ignore prefer-const\n"; yield "// @ts-ignore TS7016\n"; - yield 'import jsonld from "jsonld";\n'; + yield 'import jsonld from "jsonld/dist/jsonld.esm.js";\n'; yield 'import { getLogger } from "@logtape/logtape";\n'; yield `import { type Span, SpanStatusCode, type TracerProvider, trace } from "@opentelemetry/api";\n`; From a620dc16f0ae77e9b56b0ea54218771ebf816983 Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sat, 21 Mar 2026 23:00:37 +0900 Subject: [PATCH 3/5] Use Deno 2.7.7 for Fresh development Deno 2.7.7 fixes the upstream Fresh/Vite dev server crash that prevented final verification of the Fedify fixes for Fresh 2. Update the repository's default Deno version and document the known-good baseline for the Fresh integration example. https://github.com/fedify-dev/fedify/issues/621 https://github.com/denoland/deno/releases/tag/v2.7.7 --- .github/actions/setup-deno/action.yaml | 2 +- CHANGES.md | 4 +++- docs/manual/integration.md | 5 +++++ examples/fresh/README.md | 6 +++++- mise.toml | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-deno/action.yaml b/.github/actions/setup-deno/action.yaml index 21cb49cdc..d6d8f3d9e 100644 --- a/.github/actions/setup-deno/action.yaml +++ b/.github/actions/setup-deno/action.yaml @@ -6,4 +6,4 @@ runs: steps: - uses: denoland/setup-deno@v2 with: - deno-version: 2.7.6 # Keep in sync with mise.toml + deno-version: 2.7.7 # Keep in sync with mise.toml diff --git a/CHANGES.md b/CHANGES.md index 93425272d..56f1c63f2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,7 +23,9 @@ To be released. - Switched Fedify's JSR-facing JSON-LD imports to jsonld's ESM entrypoint so source-based runtimes such as Deno, Cloudflare Workers, and Fresh 2's Vite SSR pipeline do not have to evaluate the package through CommonJS - interop when loading Linked Data signature support. [[#621]] + interop when loading Linked Data signature support. Fresh 2 development + mode has been verified on Deno 2.7.7 after an upstream Deno 2.7.6 dev + server regression was fixed. [[#621]] ### @fedify/init diff --git a/docs/manual/integration.md b/docs/manual/integration.md index 7d5fb2add..95906a6d0 100644 --- a/docs/manual/integration.md +++ b/docs/manual/integration.md @@ -795,6 +795,11 @@ deno add jsr:@fedify/fresh > [!NOTE] > The `@fedify/fresh` package only supports Fresh 2.x. +> [!NOTE] +> Fresh 2 development mode has been verified with Deno 2.7.7. Deno 2.7.6 had +> an upstream Vite/esbuild regression that caused +> `Callback called multiple times` before Fedify code could run. + > [!WARNING] > Due to `@fedify/fedify` use `Temporal` inside, you should add `deno.unstable` > to `compilerOptions.libs` field of `deno.json`. diff --git a/examples/fresh/README.md b/examples/fresh/README.md index c6332821a..667f7a8b0 100644 --- a/examples/fresh/README.md +++ b/examples/fresh/README.md @@ -4,6 +4,10 @@ Fedify–Fresh integration example This is a simple example of how to integrate Fedify into an [Fresh] application. +Use Deno 2.7.7 or later. Deno 2.7.6 had an upstream Fresh/Vite dev-server +regression that caused `Callback called multiple times` errors before Fedify +code could run. + [Fresh]: https://fresh.deno.dev/ @@ -26,7 +30,7 @@ Running the example 3. Move to example folder ~~~~ sh - cd ../../examples/fresh + cd examples/fresh ~~~~ 4. Start the server: diff --git a/mise.toml b/mise.toml index efe004a9f..9f207d501 100644 --- a/mise.toml +++ b/mise.toml @@ -1,6 +1,6 @@ [tools] bun = "1.2.22" -deno = "2.7.6" +deno = "2.7.7" node = "22" pnpm = "10.28.0" From b894fbc2d1262643b7eddf84da5d9491f29e6e5c Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sat, 21 Mar 2026 23:13:35 +0900 Subject: [PATCH 4/5] Adjust CHANGES.md --- CHANGES.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 56f1c63f2..605868748 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,16 +8,6 @@ Version 2.0.7 To be released. -### @fedify/vocab-runtime - - - Fixed multibase public key handling to stop relying on the deprecated - CommonJS-only `multicodec` package. This removes the Vite SSR crash that - prevented Fresh 2 applications from importing `@fedify/fedify` with - `TypeError: varint.encode is not a function`. Fresh 2 no longer needs a - Vite externalization workaround for Fedify. [[#621]] - -[#621]: https://github.com/fedify-dev/fedify/issues/621 - ### @fedify/fedify - Switched Fedify's JSR-facing JSON-LD imports to jsonld's ESM entrypoint @@ -25,7 +15,18 @@ To be released. Vite SSR pipeline do not have to evaluate the package through CommonJS interop when loading Linked Data signature support. Fresh 2 development mode has been verified on Deno 2.7.7 after an upstream Deno 2.7.6 dev - server regression was fixed. [[#621]] + server regression was fixed. [[#621], [#639]] + +[#621]: https://github.com/fedify-dev/fedify/issues/621 +[#639]: https://github.com/fedify-dev/fedify/pull/639 + +### @fedify/vocab-runtime + + - Fixed multibase public key handling to stop relying on the deprecated + CommonJS-only `multicodec` package. This removes the Vite SSR crash that + prevented Fresh 2 applications from importing `@fedify/fedify` with + `TypeError: varint.encode is not a function`. Fresh 2 no longer needs a + Vite externalization workaround for Fedify. [[#621], [#639]] ### @fedify/init From 40546420cf93192c7caa704006f0629ef59fe5c2 Mon Sep 17 00:00:00 2001 From: Hong Minhee Date: Sun, 22 Mar 2026 00:48:01 +0900 Subject: [PATCH 5/5] Use vocab-runtime jsonld subpath Move the jsonld ESM shim into @fedify/vocab-runtime and expose it through the new jsonld subpath export. This avoids fragile relative imports in generated vocab sources while keeping JSR-safe packaging for the deep jsonld ESM entrypoint. Update Fedify's Linked Data signature code, the vocab code generator, snapshots, and CHANGES.md to use the shared runtime module. https://github.com/fedify-dev/fedify/pull/639#discussion_r2969710910 Co-Authored-By: OpenAI Codex --- .gitignore | 1 + CHANGES.md | 18 ++++++++++++------ deno.lock | 4 +++- packages/fedify/src/sig/ld.ts | 3 +-- packages/fixture/deno.json | 1 + packages/fixture/package.json | 2 +- packages/fixture/tsdown.config.ts | 17 +++++++++++++---- packages/vocab-runtime/deno.json | 4 +++- packages/vocab-runtime/package.json | 11 +++++++++++ packages/vocab-runtime/src/jsonld.ts | 4 ++++ packages/vocab-runtime/tsdown.config.ts | 2 +- .../src/__snapshots__/class.test.ts.deno.snap | 3 +-- .../src/__snapshots__/class.test.ts.node.snap | 3 +-- .../src/__snapshots__/class.test.ts.snap | 3 +-- packages/vocab-tools/src/class.test.ts | 2 +- packages/vocab-tools/src/class.ts | 3 +-- packages/vocab/deno.json | 1 + packages/vocab/package.json | 4 ++-- packages/vocab/tsdown.config.ts | 17 +++++++++++++---- pnpm-lock.yaml | 3 +++ 20 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 packages/vocab-runtime/src/jsonld.ts diff --git a/.gitignore b/.gitignore index 3c36dafdb..16c02ffd9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .pnpm-store/ .vocab-codegen.lock/ dist/ +dist-tests/ node_modules/ package-lock.json repomix-output.xml diff --git a/CHANGES.md b/CHANGES.md index 605868748..9cfa6796d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,12 +10,13 @@ To be released. ### @fedify/fedify - - Switched Fedify's JSR-facing JSON-LD imports to jsonld's ESM entrypoint - so source-based runtimes such as Deno, Cloudflare Workers, and Fresh 2's - Vite SSR pipeline do not have to evaluate the package through CommonJS - interop when loading Linked Data signature support. Fresh 2 development - mode has been verified on Deno 2.7.7 after an upstream Deno 2.7.6 dev - server regression was fixed. [[#621], [#639]] + - Switched Fedify's source-based JSON-LD loading to the new + `@fedify/vocab-runtime/jsonld` subpath so generated vocabulary code and + Linked Data signature support no longer have to evaluate `jsonld` through + a CommonJS-sensitive package root in Fresh 2, Deno, and other ESM-first + runtimes. Fresh 2 development mode has been verified on Deno 2.7.7 + after an upstream Deno 2.7.6 dev server regression was fixed. + [[#621], [#639]] [#621]: https://github.com/fedify-dev/fedify/issues/621 [#639]: https://github.com/fedify-dev/fedify/pull/639 @@ -28,6 +29,11 @@ To be released. `TypeError: varint.encode is not a function`. Fresh 2 no longer needs a Vite externalization workaround for Fedify. [[#621], [#639]] + - Added the new `@fedify/vocab-runtime/jsonld` subpath export so generated + vocabulary code and other Fedify runtime code can share a JSR-safe wrapper + around `jsonld`'s ESM entrypoint instead of depending on fragile relative + shims or the package-root import path. [[#621], [#639]] + ### @fedify/init - Revived removed `fedify init` options. [[#632], [#638] by ChanHaeng Lee] diff --git a/deno.lock b/deno.lock index 344652413..ea59815e0 100644 --- a/deno.lock +++ b/deno.lock @@ -6129,11 +6129,13 @@ "npm:asn1js@^3.0.6", "npm:byte-encodings@^1.0.11", "npm:fetch-mock@^12.5.4", + "npm:jsonld@9", "npm:pkijs@^3.2.5" ], "packageJson": { "dependencies": [ - "npm:@types/node@^24.2.1" + "npm:@types/node@^24.2.1", + "npm:jsonld@9" ] } }, diff --git a/packages/fedify/src/sig/ld.ts b/packages/fedify/src/sig/ld.ts index be4fc86b2..49a84e4c4 100644 --- a/packages/fedify/src/sig/ld.ts +++ b/packages/fedify/src/sig/ld.ts @@ -1,11 +1,10 @@ import { Activity, CryptographicKey, getTypeId, Object } from "@fedify/vocab"; import { type DocumentLoader, getDocumentLoader } from "@fedify/vocab-runtime"; +import jsonld from "@fedify/vocab-runtime/jsonld"; import { getLogger } from "@logtape/logtape"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; import { decodeBase64, encodeBase64 } from "byte-encodings/base64"; import { encodeHex } from "byte-encodings/hex"; -// @ts-ignore TS7016 -import jsonld from "jsonld/dist/jsonld.esm.js"; import metadata from "../../deno.json" with { type: "json" }; import { fetchKey, type KeyCache, validateCryptoKey } from "./key.ts"; diff --git a/packages/fixture/deno.json b/packages/fixture/deno.json index 968c8d9d7..a56a3981b 100644 --- a/packages/fixture/deno.json +++ b/packages/fixture/deno.json @@ -7,6 +7,7 @@ }, "exclude": [ "dist", + "dist-tests", "node_modules" ], "tasks": { diff --git a/packages/fixture/package.json b/packages/fixture/package.json index 4b0bcb673..774677bb1 100644 --- a/packages/fixture/package.json +++ b/packages/fixture/package.json @@ -49,7 +49,7 @@ "prepack": "pnpm build", "prepublish": "pnpm build", "pretest": "pnpm build", - "test": "cd dist/ && node --test" + "test": "cd dist-tests && node --test" }, "private": true } diff --git a/packages/fixture/tsdown.config.ts b/packages/fixture/tsdown.config.ts index 33891667d..bd1d1646f 100644 --- a/packages/fixture/tsdown.config.ts +++ b/packages/fixture/tsdown.config.ts @@ -1,7 +1,15 @@ -import { cp, glob } from "node:fs/promises"; -import { join, sep } from "node:path"; +import { glob, mkdir, readFile, writeFile } from "node:fs/promises"; +import { dirname, join, sep } from "node:path"; import { defineConfig } from "tsdown"; +async function copyFileSafely( + source: string, + destination: string, +): Promise { + await mkdir(dirname(destination), { recursive: true }); + await writeFile(destination, await readFile(source)); +} + export default [ defineConfig({ entry: ["src/mod.ts"], @@ -12,18 +20,19 @@ export default [ hooks: { "build:done": async (ctx) => { for await (const file of glob("src/fixtures/**/*.json")) { - await cp( + await copyFileSafely( file, join(ctx.options.outDir, file.replace(`src${sep}`, "")), - { force: true }, ); } }, }, }), defineConfig({ + outDir: "dist-tests", entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) .map((f) => f.replace(sep, "/")), + dts: false, format: ["esm", "cjs"], platform: "node", external: [ diff --git a/packages/vocab-runtime/deno.json b/packages/vocab-runtime/deno.json index f6ef8d898..a034f2bb9 100644 --- a/packages/vocab-runtime/deno.json +++ b/packages/vocab-runtime/deno.json @@ -3,7 +3,8 @@ "version": "2.0.7", "license": "MIT", "exports": { - ".": "./src/mod.ts" + ".": "./src/mod.ts", + "./jsonld": "./src/jsonld.ts" }, "description": "Runtime library for @fedify/vocab", "author": { @@ -16,6 +17,7 @@ "asn1js": "npm:asn1js@^3.0.6", "byte-encodings": "npm:byte-encodings@^1.0.11", "fetch-mock": "npm:fetch-mock@^12.5.4", + "jsonld": "npm:jsonld@^9.0.0", "pkijs": "npm:pkijs@^3.2.5" }, "exclude": [ diff --git a/packages/vocab-runtime/package.json b/packages/vocab-runtime/package.json index c88a4fc9e..77f2b3ed2 100644 --- a/packages/vocab-runtime/package.json +++ b/packages/vocab-runtime/package.json @@ -35,6 +35,16 @@ "require": "./dist/mod.cjs", "default": "./dist/mod.js" }, + "./jsonld": { + "types": { + "import": "./dist/jsonld.d.ts", + "require": "./dist/jsonld.d.cts", + "default": "./dist/jsonld.d.ts" + }, + "import": "./dist/jsonld.js", + "require": "./dist/jsonld.cjs", + "default": "./dist/jsonld.js" + }, "./package.json": "./package.json" }, "scripts": { @@ -68,6 +78,7 @@ "@opentelemetry/api": "catalog:", "asn1js": "catalog:", "byte-encodings": "catalog:", + "jsonld": "^9.0.0", "pkijs": "catalog:" } } diff --git a/packages/vocab-runtime/src/jsonld.ts b/packages/vocab-runtime/src/jsonld.ts new file mode 100644 index 000000000..940373d1f --- /dev/null +++ b/packages/vocab-runtime/src/jsonld.ts @@ -0,0 +1,4 @@ +// @ts-ignore TS7016 +import jsonld from "jsonld/dist/jsonld.esm.js"; + +export default jsonld as typeof import("jsonld"); diff --git a/packages/vocab-runtime/tsdown.config.ts b/packages/vocab-runtime/tsdown.config.ts index 092a423d5..f11970bc6 100644 --- a/packages/vocab-runtime/tsdown.config.ts +++ b/packages/vocab-runtime/tsdown.config.ts @@ -4,7 +4,7 @@ import { defineConfig } from "tsdown"; export default [ defineConfig({ - entry: ["src/mod.ts"], + entry: ["src/mod.ts", "src/jsonld.ts"], dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } }, format: ["esm", "cjs"], platform: "neutral", diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap index 20d07201c..105f68588 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snap @@ -2,8 +2,7 @@ export const snapshot = {}; snapshot[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const -// @ts-ignore TS7016 -import jsonld from \\"jsonld/dist/jsonld.esm.js\\"; +import jsonld from \\"@fedify/vocab-runtime/jsonld\\"; import { getLogger } from \\"@logtape/logtape\\"; import { type Span, SpanStatusCode, type TracerProvider, trace } from \\"@opentelemetry/api\\"; diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap index 6f1239e2f..6de725299 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.node.snap @@ -1,7 +1,6 @@ exports[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const -// @ts-ignore TS7016 -import jsonld from \\"jsonld/dist/jsonld.esm.js\\"; +import jsonld from \\"@fedify/vocab-runtime/jsonld\\"; import { getLogger } from \\"@logtape/logtape\\"; import { type Span, SpanStatusCode, type TracerProvider, trace } from \\"@opentelemetry/api\\"; diff --git a/packages/vocab-tools/src/__snapshots__/class.test.ts.snap b/packages/vocab-tools/src/__snapshots__/class.test.ts.snap index 30a44df36..aaf9529f1 100644 --- a/packages/vocab-tools/src/__snapshots__/class.test.ts.snap +++ b/packages/vocab-tools/src/__snapshots__/class.test.ts.snap @@ -2,8 +2,7 @@ exports[`generateClasses() 1`] = ` "// deno-lint-ignore-file ban-unused-ignore prefer-const -// @ts-ignore TS7016 -import jsonld from "jsonld/dist/jsonld.esm.js"; +import jsonld from "@fedify/vocab-runtime/jsonld"; import { getLogger } from "@logtape/logtape"; import { type Span, SpanStatusCode, type TracerProvider, trace } from "@opentelemetry/api"; diff --git a/packages/vocab-tools/src/class.test.ts b/packages/vocab-tools/src/class.test.ts index ddf0fbe0a..f58f82dee 100644 --- a/packages/vocab-tools/src/class.test.ts +++ b/packages/vocab-tools/src/class.test.ts @@ -66,7 +66,7 @@ test("sortTopologically()", () => { test("generateClasses() imports the browser-safe jsonld entrypoint", async () => { const entireCode = await getEntireCode(); - match(entireCode, /import jsonld from "jsonld\/dist\/jsonld\.esm\.js";/); + match(entireCode, /import jsonld from "@fedify\/vocab-runtime\/jsonld";/); }); if ("Deno" in globalThis) { diff --git a/packages/vocab-tools/src/class.ts b/packages/vocab-tools/src/class.ts index e33a3a304..94a3f4de7 100644 --- a/packages/vocab-tools/src/class.ts +++ b/packages/vocab-tools/src/class.ts @@ -118,8 +118,7 @@ export async function* generateClasses( types: Record, ): AsyncIterable { yield "// deno-lint-ignore-file ban-unused-ignore prefer-const\n"; - yield "// @ts-ignore TS7016\n"; - yield 'import jsonld from "jsonld/dist/jsonld.esm.js";\n'; + yield 'import jsonld from "@fedify/vocab-runtime/jsonld";\n'; yield 'import { getLogger } from "@logtape/logtape";\n'; yield `import { type Span, SpanStatusCode, type TracerProvider, trace } from "@opentelemetry/api";\n`; diff --git a/packages/vocab/deno.json b/packages/vocab/deno.json index 117c9fcf7..843e259da 100644 --- a/packages/vocab/deno.json +++ b/packages/vocab/deno.json @@ -18,6 +18,7 @@ }, "exclude": [ "dist/", + "dist-tests/", "node_modules/", "src/*.yaml", "!src/vocab.ts" diff --git a/packages/vocab/package.json b/packages/vocab/package.json index e69d331ff..20367295a 100644 --- a/packages/vocab/package.json +++ b/packages/vocab/package.json @@ -64,9 +64,9 @@ "prepack": "pnpm build", "prepublish": "pnpm build", "pretest": "pnpm build", - "test": "cd dist/ && node --test", + "test": "cd dist-tests && node --test", "pretest:bun": "pnpm build", - "test:bun": "cd dist/ && bun test --timeout 60000" + "test:bun": "cd dist-tests && bun test --timeout 60000" }, "keywords": [ "Fedify", diff --git a/packages/vocab/tsdown.config.ts b/packages/vocab/tsdown.config.ts index ba1fc2d91..1c4154fcc 100644 --- a/packages/vocab/tsdown.config.ts +++ b/packages/vocab/tsdown.config.ts @@ -1,7 +1,15 @@ -import { cp, glob } from "node:fs/promises"; -import { join, sep } from "node:path"; +import { glob, mkdir, readFile, writeFile } from "node:fs/promises"; +import { dirname, join, sep } from "node:path"; import { defineConfig } from "tsdown"; +async function copyFileSafely( + source: string, + destination: string, +): Promise { + await mkdir(dirname(destination), { recursive: true }); + await writeFile(destination, await readFile(source)); +} + export default [ defineConfig({ entry: [ @@ -25,8 +33,10 @@ export default [ }, }), defineConfig({ + outDir: "dist-tests", entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) .map((f) => f.replace(sep, "/")), + dts: false, external: [/^node:/, "@fedify/fixture"], inputOptions: { onwarn(warning, defaultHandler) { @@ -50,10 +60,9 @@ export default [ hooks: { "build:done": async (ctx) => { for await (const file of glob("src/**/*.yaml")) { - await cp( + await copyFileSafely( file, join(ctx.options.outDir, file.replace(`src${sep}`, "")), - { force: true }, ); } }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0fb01fc26..6fc210677 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1513,6 +1513,9 @@ importers: byte-encodings: specifier: 'catalog:' version: 1.0.11 + jsonld: + specifier: ^9.0.0 + version: 9.0.0 pkijs: specifier: 'catalog:' version: 3.3.3