diff --git a/AGENTS.md b/AGENTS.md index b9b19173f..4609f2747 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -65,8 +65,8 @@ The repository is organized as a monorepo with the following packages: - *src/sig/*: Signature implementation - *src/testing/*: Testing utilities. Most have been migrated to `packages/fixture`(`@fedify/fixture`), except for modules that have dependencies on `@fedify/fedify`. - *src/utils/*: Utility functions - - *src/vocab/*: ActivityPub vocabulary implementation - - *src/webfinger/*: WebFinger protocol implementation + - ~~src/vocab/~~: **Don't use.** Moved to `@fedify/vocab`. If user code imports from here, notice and suggest migration. + - ~~src/webfinger/~~: **Don't use.** Moved to `@fedify/webfinger`. If user code imports from here, notice and suggest migration. - ~~src/x/~~: **Don't use.** This directory will be removed in version 2.0.0. Use packages from the `@fedify` scope, which are located in the `packages/` directory (e.g., `@fedify/hono` is in `packages/hono/`). - *packages/cli/*: Fedify CLI implementation (@fedify/cli, built with Deno) - *packages/amqp/*: AMQP/RabbitMQ driver (@fedify/amqp) @@ -89,6 +89,8 @@ The repository is organized as a monorepo with the following packages: - *packages/sqlite/*: SQLite driver (@fedify/sqlite) - *packages/sveltekit/*: SvelteKit integration (@fedify/sveltekit) - *packages/testing/*: Testing utilities (@fedify/testing) + - *packages/vocab/*: Activity Vocabulary library (@fedify/vocab) + - *packages/webfinger/*: WebFinger client library for ActivityPub (@fedify/webfinger) - *packages/vocab-runtime/*: Runtime utilities and types (@fedify/vocab-runtime) - *packages/vocab-tools/*: Utilities and types for code-generated Activity Vocabulary APIs (@fedify/vocab-runtime) - *docs/*: Documentation built with Node.js and VitePress diff --git a/CHANGES.md b/CHANGES.md index 9daaab355..6c1b6164c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -250,6 +250,26 @@ To be released. [#466]: https://github.com/fedify-dev/fedify/issues/466 [#478]: https://github.com/fedify-dev/fedify/pull/478 +### @fedify/webfinger + + - Created WebFinger utilities as the *@fedify/webfinger* package. + This package provides tools for working with WebFinger resources, + including parsing and generating WebFinger documents. + [[#517] by ChanHaeng Lee] + +[#517]: https://github.com/fedify-dev/fedify/pull/517 + +### @fedify/vocab + + - Created ActivityPub Vocabulary API package as the *@fedify/vocab* package. + This package contains the generated Activity Vocabulary classes and + related types, separated from the main *@fedify/fedify* package to + improve modularity and enable custom vocabulary extensions. + [[#437], [#517] by ChanHaeng Lee] + +[#437]: https://github.com/fedify-dev/fedify/issues/437 +[#517]: https://github.com/fedify-dev/fedify/pull/517 + Version 1.10.0 -------------- diff --git a/deno.json b/deno.json index b2c914566..6226e321e 100644 --- a/deno.json +++ b/deno.json @@ -19,8 +19,10 @@ "./packages/sqlite", "./packages/sveltekit", "./packages/testing", + "./packages/vocab", "./packages/vocab-runtime", "./packages/vocab-tools", + "./packages/webfinger", "./examples/hono-sample", "./examples/fresh" ], @@ -51,7 +53,7 @@ "json-preserve-indent": "npm:json-preserve-indent@^1.1.3", "postgres": "npm:postgres@^3.4.7", "preact": "npm:preact@10.19.6", - "tsdown": "npm:tsdown@^0.12.9" + "tsdown": "npm:tsdown@^0.18.4" }, "unstable": [ "fs", @@ -78,7 +80,13 @@ }, "nodeModulesDir": "auto", "tasks": { - "codegen": "deno task -f @fedify/cli codegen", + "build": { + "command": "pnpm --recursive --filter '@fedify/*' --parallel --silent build", + "dependencies": [ + "install" + ] + }, + "codegen": "deno task -f @fedify/vocab compile", "check-versions": "deno run --allow-read --allow-write scripts/check_versions.ts", "check-all": { "command": "deno fmt --check && deno lint && deno check --unstable-temporal $(deno eval 'import m from \"./deno.json\" with { type: \"json\" }; for (let p of m.workspace) console.log(p)')", @@ -93,8 +101,27 @@ "codegen" ] }, + "pnpm:build-vocab-runtime": { + "command": "pnpm -C packages/vocab-runtime build" + }, + "pnpm:build-vocab-tools": { + "command": "pnpm -C packages/vocab-tools build" + }, "pnpm:build-fixture": { - "command": "cd packages/fixture && pnpm build" + "command": "pnpm -C packages/fixture build" + }, + "pnpm:build-webfinger": { + "command": "pnpm -C packages/webfinger build" + }, + "pnpm:build-vocab": { + "command": "pnpm -C packages/vocab build", + "dependencies": [ + "install", + "pnpm:build-vocab-runtime", + "pnpm:build-vocab-tools", + "pnpm:build-fixture", + "pnpm:build-webfinger" + ] }, "test": { "command": "deno test --check --doc --allow-all --unstable-kv --trace-leaks --parallel", @@ -105,17 +132,13 @@ "test:node": { "command": "pnpm run --recursive --filter '!{docs}' test", "dependencies": [ - "codegen", - "install", - "pnpm:build-fixture" + "build" ] }, "test:bun": { "command": "pnpm run --recursive --filter '!{docs}' test:bun", "dependencies": [ - "codegen", - "install", - "pnpm:build-fixture" + "build" ] }, "test-all": { diff --git a/deno.lock b/deno.lock index caf2c7a61..927d33a09 100644 --- a/deno.lock +++ b/deno.lock @@ -1,20 +1,13 @@ { "version": "5", "specifiers": { - "jsr:@alinea/suite@~0.6.3": "0.6.3", "jsr:@david/console-static-text@0.3": "0.3.0", "jsr:@david/dax@~0.43.2": "0.43.2", "jsr:@david/path@0.2": "0.2.0", "jsr:@david/which@~0.4.1": "0.4.1", - "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.0", - "jsr:@deno/loader@~0.3.2": "0.3.9", - "jsr:@deno/loader@~0.3.3": "0.3.9", "jsr:@fresh/build-id@1": "1.0.1", - "jsr:@fresh/core@2": "2.2.0", "jsr:@fresh/core@^2.1.4": "2.2.0", - "jsr:@fresh/plugin-vite@^1.0.7": "1.0.7", "jsr:@hongminhee/localtunnel@0.3": "0.3.0", - "jsr:@hono/hono@^4.7.1": "4.11.3", "jsr:@hono/hono@^4.8.3": "4.11.3", "jsr:@logtape/file@^1.3.5": "1.3.5", "jsr:@logtape/logtape@^1.0.4": "1.3.5", @@ -22,77 +15,50 @@ "jsr:@optique/core@~0.8.2": "0.8.4", "jsr:@optique/core@~0.8.4": "0.8.4", "jsr:@optique/run@~0.8.2": "0.8.4", - "jsr:@std/assert@0.224": "0.224.0", - "jsr:@std/assert@0.226": "0.226.0", - "jsr:@std/assert@^1.0.13": "1.0.16", - "jsr:@std/async@^1.0.13": "1.0.16", "jsr:@std/bytes@^1.0.5": "1.0.6", - "jsr:@std/bytes@^1.0.6": "1.0.6", - "jsr:@std/dotenv@~0.225.5": "0.225.6", "jsr:@std/encoding@^1.0.10": "1.0.10", - "jsr:@std/fmt@0.224": "0.224.0", "jsr:@std/fmt@1": "1.0.8", - "jsr:@std/fmt@^1.0.7": "1.0.8", "jsr:@std/fmt@^1.0.8": "1.0.8", - "jsr:@std/fs@0.224": "0.224.0", "jsr:@std/fs@1": "1.0.21", "jsr:@std/fs@^1.0.19": "1.0.21", - "jsr:@std/fs@^1.0.3": "1.0.21", "jsr:@std/html@^1.0.5": "1.0.5", "jsr:@std/http@^1.0.21": "1.0.23", - "jsr:@std/internal@0.224": "0.224.0", - "jsr:@std/internal@1": "1.0.12", "jsr:@std/internal@^1.0.12": "1.0.12", "jsr:@std/io@0.225": "0.225.2", - "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@0.224": "0.224.0", "jsr:@std/path@1": "1.1.4", "jsr:@std/path@^1.0.6": "1.1.4", - "jsr:@std/path@^1.1.1": "1.1.4", "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.7", - "jsr:@std/testing@0.224": "0.224.0", - "jsr:@std/uuid@^1.0.9": "1.1.0", - "jsr:@std/yaml@*": "1.0.10", - "jsr:@std/yaml@^1.0.8": "1.0.10", "npm:@alinea/suite@~0.6.3": "0.6.3", - "npm:@babel/core@^7.28.0": "7.28.5", - "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.28.5", "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.3__vite@7.3.0___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260103.0_tsx@4.21.0_yaml@2.8.2", - "npm:@cloudflare/workers-types@^4.20250529.0": "4.20260103.0", - "npm:@cloudflare/workers-types@^4.20250906.0": "4.20260103.0", + "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.3__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260109.0_tsx@4.21.0_yaml@2.8.2", + "npm:@cloudflare/workers-types@^4.20250529.0": "4.20260109.0", + "npm:@cloudflare/workers-types@^4.20250906.0": "4.20260109.0", "npm:@fxts/core@^1.21.1": "1.23.0", "npm:@hongminhee/localtunnel@0.3": "0.3.0", "npm:@inquirer/prompts@^7.8.4": "7.10.1_@types+node@22.19.3", "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", - "npm:@mjackson/node-fetch-server@0.7": "0.7.0", "npm:@multiformats/base-x@^4.0.1": "4.0.1", "npm:@nestjs/common@^11.0.1": "11.1.11_reflect-metadata@0.2.2_rxjs@7.8.2", "npm:@opentelemetry/api@^1.9.0": "1.9.0", - "npm:@opentelemetry/core@2": "2.2.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/sdk-trace-base@2": "2.2.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/core@2": "2.3.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/sdk-trace-base@2": "2.3.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/semantic-conventions@^1.27.0": "1.38.0", - "npm:@optique/core@~0.8.2": "0.8.6", - "npm:@optique/run@~0.8.2": "0.8.6", + "npm:@optique/core@~0.8.2": "0.8.7", + "npm:@optique/run@~0.8.2": "0.8.7", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", "npm:@preact/signals@^2.2.1": "2.5.1_preact@10.19.6", "npm:@preact/signals@^2.3.2": "2.5.1_preact@10.19.6", - "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.19.6_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", - "npm:@sveltejs/kit@2": "2.49.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.46.1___acorn@8.15.0__vite@7.3.0___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", - "npm:@types/amqplib@*": "0.10.8", + "npm:@sveltejs/kit@2": "2.49.4_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", "npm:@types/amqplib@~0.10.7": "0.10.8", "npm:@types/eslint@9": "9.6.1", "npm:@types/estree@^1.0.8": "1.0.8", "npm:@types/node@^22.16.0": "22.19.3", "npm:@types/node@^24.2.1": "24.10.4", - "npm:@typescript-eslint/parser@^8.49.0": "8.51.0_eslint@9.39.2_typescript@5.9.3", - "npm:@typescript-eslint/utils@8": "8.51.0_eslint@9.39.2_typescript@5.9.3", + "npm:@typescript-eslint/parser@^8.49.0": "8.52.0_eslint@9.39.2_typescript@5.9.3", + "npm:@typescript-eslint/utils@8": "8.52.0_eslint@9.39.2_typescript@5.9.3", "npm:amqplib@~0.10.9": "0.10.9", "npm:asn1js@^3.0.6": "3.0.7", "npm:asn1js@^3.0.7": "3.0.7", @@ -105,10 +71,8 @@ "npm:es-toolkit@^1.30.0": "1.43.0", "npm:es-toolkit@^1.31.0": "1.43.0", "npm:es-toolkit@^1.39.10": "1.43.0", + "npm:es-toolkit@^1.42.0": "1.43.0", "npm:es-toolkit@^1.43.0": "1.43.0", - "npm:esbuild-wasm@~0.25.11": "0.25.12", - "npm:esbuild@0.25.7": "0.25.7", - "npm:esbuild@~0.25.5": "0.25.12", "npm:eslint@9": "9.39.2", "npm:express@4": "4.22.1", "npm:fast-check@^3.22.0": "3.23.2", @@ -121,7 +85,7 @@ "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.3", - "npm:ioredis@^5.8.2": "5.8.2", + "npm:ioredis@^5.8.2": "5.9.1", "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", @@ -132,31 +96,24 @@ "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.7", + "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@10.19.6": "10.19.6", - "npm:preact@^10.27.0": "10.28.1", - "npm:preact@^10.27.2": "10.28.1", - "npm:rollup@^4.50.0": "4.54.0", + "npm:preact@^10.27.2": "10.28.2", "npm:shiki@^1.6.4": "1.29.2", "npm:srvx@~0.8.7": "0.8.16", "npm:structured-field-values@^2.0.4": "2.0.4", - "npm:tsdown@~0.12.9": "0.12.9_rolldown@1.0.0-beta.58", + "npm:tsdown@~0.18.4": "0.18.4_rolldown@1.0.0-beta.57", "npm:tsx@^4.19.4": "4.21.0", "npm:uri-template-router@1": "1.0.0", "npm:url-template@^3.1.1": "3.1.1", - "npm:urlpattern-polyfill@^10.1.0": "10.1.0", - "npm:vite@^7.1.3": "7.3.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vite@^7.1.4": "7.3.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vitest@3.2": "3.2.4_@types+node@22.19.3_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", - "npm:wrangler@^4.17.0": "4.35.0_@cloudflare+workers-types@4.20260103.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", - "npm:wrangler@^4.21.1": "4.35.0_@cloudflare+workers-types@4.20260103.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", + "npm:vite@^7.1.3": "7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", + "npm:vitest@3.2": "3.2.4_@types+node@22.19.3_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", + "npm:wrangler@^4.17.0": "4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", + "npm:wrangler@^4.21.1": "4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", "npm:yaml@^2.8.1": "2.8.2" }, "jsr": { - "@alinea/suite@0.6.3": { - "integrity": "7d24a38729663b84d8a263d64ff7e3f8c72ac7cbb1db8ec5f414d0416b6b72e2" - }, "@david/console-static-text@0.3.0": { "integrity": "2dfb46ecee525755f7989f94ece30bba85bd8ffe3e8666abc1bf926e1ee0698d" }, @@ -182,17 +139,6 @@ "@david/which@0.4.1": { "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" }, - "@deno/esbuild-plugin@1.2.0": { - "integrity": "04ddd0fca9416d8a2866263928a53b9d5ed08dfca064d64504a0aaf9800c709e", - "dependencies": [ - "jsr:@deno/loader@~0.3.3", - "jsr:@std/path@^1.1.1", - "npm:esbuild@~0.25.5" - ] - }, - "@deno/loader@0.3.9": { - "integrity": "703d44656f7da0fa4a4a7f8a5105b5b41320821286508c2967b4252a00a2506f" - }, "@fresh/build-id@1.0.1": { "integrity": "12a2ec25fd52ae9ec68c26848a5696cd1c9b537f7c983c7e56e4fb1e7e816c20", "dependencies": [ @@ -202,44 +148,18 @@ "@fresh/core@2.2.0": { "integrity": "b3c00f82288a2c4c8ec85e4abb67b080b366ec5971860f2f2898eb281ea1a80f", "dependencies": [ - "jsr:@deno/esbuild-plugin", "jsr:@fresh/build-id", - "jsr:@std/encoding", "jsr:@std/fmt@^1.0.8", "jsr:@std/fs@^1.0.19", "jsr:@std/html", "jsr:@std/http", - "jsr:@std/jsonc", - "jsr:@std/media-types", "jsr:@std/path@^1.1.2", - "jsr:@std/semver", - "jsr:@std/uuid", "npm:@opentelemetry/api", "npm:@preact/signals@^2.2.1", - "npm:esbuild-wasm", - "npm:esbuild@0.25.7", "npm:preact-render-to-string", - "npm:preact@^10.27.0", "npm:preact@^10.27.2" ] }, - "@fresh/plugin-vite@1.0.7": { - "integrity": "0dd7048f7c5d5cf7f62b29b4653a18cfa4dc81e074c4c0ab9e8166cce639cbeb", - "dependencies": [ - "jsr:@deno/loader@~0.3.2", - "jsr:@fresh/core@2", - "jsr:@fresh/core@^2.1.4", - "jsr:@std/dotenv", - "jsr:@std/fmt@^1.0.7", - "jsr:@std/path@1", - "npm:@babel/core", - "npm:@babel/preset-react", - "npm:@mjackson/node-fetch-server", - "npm:@prefresh/vite", - "npm:rollup", - "npm:vite@^7.1.4" - ] - }, "@hongminhee/localtunnel@0.3.0": { "integrity": "4ad858acd963b5fad45b188d54cf751ac8fbe0aae495e1d3ce607e3730270ff4", "dependencies": [ @@ -267,53 +187,19 @@ "jsr:@optique/core@~0.8.4" ] }, - "@std/assert@0.224.0": { - "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", - "dependencies": [ - "jsr:@std/fmt@0.224", - "jsr:@std/internal@0.224" - ] - }, - "@std/assert@0.226.0": { - "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3", - "dependencies": [ - "jsr:@std/internal@1" - ] - }, - "@std/assert@1.0.16": { - "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", - "dependencies": [ - "jsr:@std/internal@^1.0.12" - ] - }, - "@std/async@1.0.16": { - "integrity": "6c9e43035313b67b5de43e2b3ee3eadb39a488a0a0a3143097f112e025d3ee9a" - }, "@std/bytes@1.0.6": { "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" }, - "@std/dotenv@0.225.6": { - "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" - }, "@std/encoding@1.0.10": { "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" }, - "@std/fmt@0.224.0": { - "integrity": "e20e9a2312a8b5393272c26191c0a68eda8d2c4b08b046bad1673148f1d69851" - }, "@std/fmt@1.0.8": { "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" }, - "@std/fs@0.224.0": { - "integrity": "52a5ec89731ac0ca8f971079339286f88c571a4d61686acf75833f03a89d8e69", - "dependencies": [ - "jsr:@std/path@0.224" - ] - }, "@std/fs@1.0.21": { "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd", "dependencies": [ - "jsr:@std/internal@^1.0.12", + "jsr:@std/internal", "jsr:@std/path@^1.1.4" ] }, @@ -321,16 +207,7 @@ "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" }, "@std/http@1.0.23": { - "integrity": "6634e9e034c589bf35101c1b5ee5bbf052a5987abca20f903e58bdba85c80dee", - "dependencies": [ - "jsr:@std/encoding" - ] - }, - "@std/internal@0.224.0": { - "integrity": "afc50644f9cdf4495eeb80523a8f6d27226b4b36c45c7c195dfccad4b8509291", - "dependencies": [ - "jsr:@std/fmt@0.224" - ] + "integrity": "6634e9e034c589bf35101c1b5ee5bbf052a5987abca20f903e58bdba85c80dee" }, "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" @@ -338,87 +215,20 @@ "@std/io@0.225.2": { "integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7", "dependencies": [ - "jsr:@std/bytes@^1.0.5" + "jsr:@std/bytes" ] }, - "@std/json@1.0.2": { - "integrity": "d9e5497801c15fb679f55a2c01c7794ad7a5dfda4dd1bebab5e409cb5e0d34d4" - }, - "@std/jsonc@1.0.2": { - "integrity": "909605dae3af22bd75b1cbda8d64a32cf1fd2cf6efa3f9e224aba6d22c0f44c7", - "dependencies": [ - "jsr:@std/json" - ] - }, - "@std/media-types@1.1.0": { - "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" - }, - "@std/path@0.224.0": { - "integrity": "55bca6361e5a6d158b9380e82d4981d82d338ec587de02951e2b7c3a24910ee6" - }, "@std/path@1.1.4": { "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", "dependencies": [ - "jsr:@std/internal@^1.0.12" - ] - }, - "@std/semver@1.0.7": { - "integrity": "7d5f65391762dc4358abde80fc3354086ddb40101f140295e60f290c138887d0" - }, - "@std/testing@0.224.0": { - "integrity": "371b8a929aa7132240d5dd766a439be8f780ef5c176ab194e0bcab72370c761e", - "dependencies": [ - "jsr:@std/assert@0.224", - "jsr:@std/fmt@0.224", - "jsr:@std/fs@0.224", - "jsr:@std/path@0.224" - ] - }, - "@std/uuid@1.1.0": { - "integrity": "6268db2ccf172849c9be80763354ca305d49ef4af41fe995623d44fcc3f7457c", - "dependencies": [ - "jsr:@std/bytes@^1.0.6" + "jsr:@std/internal" ] - }, - "@std/yaml@1.0.10": { - "integrity": "245706ea3511cc50c8c6d00339c23ea2ffa27bd2c7ea5445338f8feff31fa58e" } }, "npm": { "@alinea/suite@0.6.3": { "integrity": "sha512-4oGhbwAGq3rQeuuq9ylmybMkIT1mAl6e+DiiTLwwmwNzHFQiVihishgOpkIGrs0fGVSD4T8jOLyNTuQ30RtVuQ==" }, - "@babel/code-frame@7.27.1": { - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dependencies": [ - "@babel/helper-validator-identifier", - "js-tokens@4.0.0", - "picocolors" - ] - }, - "@babel/compat-data@7.28.5": { - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==" - }, - "@babel/core@7.28.5": { - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dependencies": [ - "@babel/code-frame", - "@babel/generator", - "@babel/helper-compilation-targets", - "@babel/helper-module-transforms", - "@babel/helpers", - "@babel/parser", - "@babel/template", - "@babel/traverse", - "@babel/types", - "@jridgewell/remapping", - "convert-source-map", - "debug@4.4.3", - "gensync", - "json5", - "semver@6.3.1" - ] - }, "@babel/generator@7.28.5": { "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dependencies": [ @@ -429,60 +239,12 @@ "jsesc" ] }, - "@babel/helper-annotate-as-pure@7.27.3": { - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dependencies": [ - "@babel/types" - ] - }, - "@babel/helper-compilation-targets@7.27.2": { - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dependencies": [ - "@babel/compat-data", - "@babel/helper-validator-option", - "browserslist", - "lru-cache@5.1.1", - "semver@6.3.1" - ] - }, - "@babel/helper-globals@7.28.0": { - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" - }, - "@babel/helper-module-imports@7.27.1": { - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dependencies": [ - "@babel/traverse", - "@babel/types" - ] - }, - "@babel/helper-module-transforms@7.28.3_@babel+core@7.28.5": { - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-imports", - "@babel/helper-validator-identifier", - "@babel/traverse" - ] - }, - "@babel/helper-plugin-utils@7.27.1": { - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==" - }, "@babel/helper-string-parser@7.27.1": { "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" }, "@babel/helper-validator-identifier@7.28.5": { "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" }, - "@babel/helper-validator-option@7.27.1": { - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==" - }, - "@babel/helpers@7.28.4": { - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dependencies": [ - "@babel/template", - "@babel/types" - ] - }, "@babel/parser@7.28.5": { "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dependencies": [ @@ -490,78 +252,6 @@ ], "bin": true }, - "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.28.5": { - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.28.5": { - "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.28.5": { - "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", - "dependencies": [ - "@babel/core", - "@babel/plugin-transform-react-jsx" - ] - }, - "@babel/plugin-transform-react-jsx@7.27.1_@babel+core@7.28.5": { - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-module-imports", - "@babel/helper-plugin-utils", - "@babel/plugin-syntax-jsx", - "@babel/types" - ] - }, - "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.28.5": { - "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-plugin-utils" - ] - }, - "@babel/preset-react@7.28.5_@babel+core@7.28.5": { - "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-validator-option", - "@babel/plugin-transform-react-display-name", - "@babel/plugin-transform-react-jsx", - "@babel/plugin-transform-react-jsx-development", - "@babel/plugin-transform-react-pure-annotations" - ] - }, - "@babel/template@7.27.2": { - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dependencies": [ - "@babel/code-frame", - "@babel/parser", - "@babel/types" - ] - }, - "@babel/traverse@7.28.5": { - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dependencies": [ - "@babel/code-frame", - "@babel/generator", - "@babel/helper-globals", - "@babel/parser", - "@babel/template", - "@babel/types", - "debug@4.4.3" - ] - }, "@babel/types@7.28.5": { "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dependencies": [ @@ -594,7 +284,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.3__vite@7.3.0___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260103.0_tsx@4.21.0_yaml@2.8.2": { + "@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.3__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260109.0_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-keu2HCLQfRNwbmLBCDXJgCFpANTaYnQpE01fBOo4CNwiWHUT7SZGN7w64RKiSWRHyYppStXBuE5Ng7F42+flpg==", "dependencies": [ "@vitest/runner", @@ -603,7 +293,7 @@ "cjs-module-lexer", "devalue", "miniflare", - "semver@7.7.3", + "semver", "vitest", "wrangler", "zod@3.25.76" @@ -634,8 +324,8 @@ "os": ["win32"], "cpu": ["x64"] }, - "@cloudflare/workers-types@4.20260103.0": { - "integrity": "sha512-jANmoGpJcXARnwlkvrQOeWyjYD1quTfHcs+++Z544XRHOSfLc4XSlts7snIhbiIGgA5bo66zDhraF+9lKUr2hw==" + "@cloudflare/workers-types@4.20260109.0": { + "integrity": "sha512-90vx2lVm+fhQyE8FKqNhT8JBI8GuY0biAwxTzvzeRIdWVo2ArCpUfYMYq4kzaGTfA6NwCmXmBFSgnqfG6OFxLw==" }, "@colors/colors@1.5.0": { "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" @@ -650,18 +340,18 @@ "integrity": "sha512-OGju/GYp0V72qlZ/Pd4jGEwqBwT/Za/tw+Z3AC7lgMheGqsbhTZrtc5iLz9z59G/Q53QyE2fnjHV8N9wjBpiWA==", "dependencies": [ "ky", - "undici@6.22.0" + "undici@6.23.0" ] }, - "@emnapi/core@1.7.1": { - "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "@emnapi/core@1.8.1": { + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", "dependencies": [ "@emnapi/wasi-threads", "tslib" ] }, - "@emnapi/runtime@1.7.1": { - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "@emnapi/runtime@1.8.1": { + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "dependencies": [ "tslib" ] @@ -672,516 +362,256 @@ "tslib" ] }, - "@esbuild/aix-ppc64@0.25.12": { - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "os": ["aix"], - "cpu": ["ppc64"] - }, "@esbuild/aix-ppc64@0.25.4": { "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/aix-ppc64@0.25.7": { - "integrity": "sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==", - "os": ["aix"], - "cpu": ["ppc64"] - }, "@esbuild/aix-ppc64@0.27.2": { "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/android-arm64@0.25.12": { - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "os": ["android"], - "cpu": ["arm64"] - }, "@esbuild/android-arm64@0.25.4": { "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm64@0.25.7": { - "integrity": "sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==", - "os": ["android"], - "cpu": ["arm64"] - }, "@esbuild/android-arm64@0.27.2": { "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm@0.25.12": { - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "os": ["android"], - "cpu": ["arm"] - }, "@esbuild/android-arm@0.25.4": { "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-arm@0.25.7": { - "integrity": "sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==", - "os": ["android"], - "cpu": ["arm"] - }, "@esbuild/android-arm@0.27.2": { "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-x64@0.25.12": { - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "os": ["android"], - "cpu": ["x64"] - }, "@esbuild/android-x64@0.25.4": { "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "os": ["android"], "cpu": ["x64"] }, - "@esbuild/android-x64@0.25.7": { - "integrity": "sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==", - "os": ["android"], - "cpu": ["x64"] - }, "@esbuild/android-x64@0.27.2": { "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "os": ["android"], "cpu": ["x64"] }, - "@esbuild/darwin-arm64@0.25.12": { - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "os": ["darwin"], - "cpu": ["arm64"] - }, "@esbuild/darwin-arm64@0.25.4": { "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-arm64@0.25.7": { - "integrity": "sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==", - "os": ["darwin"], - "cpu": ["arm64"] - }, "@esbuild/darwin-arm64@0.27.2": { "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-x64@0.25.12": { - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "os": ["darwin"], - "cpu": ["x64"] - }, "@esbuild/darwin-x64@0.25.4": { "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/darwin-x64@0.25.7": { - "integrity": "sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==", - "os": ["darwin"], - "cpu": ["x64"] - }, "@esbuild/darwin-x64@0.27.2": { "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/freebsd-arm64@0.25.12": { - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, "@esbuild/freebsd-arm64@0.25.4": { "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-arm64@0.25.7": { - "integrity": "sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, "@esbuild/freebsd-arm64@0.27.2": { "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-x64@0.25.12": { - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "os": ["freebsd"], - "cpu": ["x64"] - }, "@esbuild/freebsd-x64@0.25.4": { "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/freebsd-x64@0.25.7": { - "integrity": "sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==", - "os": ["freebsd"], - "cpu": ["x64"] - }, "@esbuild/freebsd-x64@0.27.2": { "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/linux-arm64@0.25.12": { - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "os": ["linux"], - "cpu": ["arm64"] - }, "@esbuild/linux-arm64@0.25.4": { "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm64@0.25.7": { - "integrity": "sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==", - "os": ["linux"], - "cpu": ["arm64"] - }, "@esbuild/linux-arm64@0.27.2": { "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm@0.25.12": { - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "os": ["linux"], - "cpu": ["arm"] - }, "@esbuild/linux-arm@0.25.4": { "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-arm@0.25.7": { - "integrity": "sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==", - "os": ["linux"], - "cpu": ["arm"] - }, "@esbuild/linux-arm@0.27.2": { "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-ia32@0.25.12": { - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "os": ["linux"], - "cpu": ["ia32"] - }, "@esbuild/linux-ia32@0.25.4": { "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-ia32@0.25.7": { - "integrity": "sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==", - "os": ["linux"], - "cpu": ["ia32"] - }, "@esbuild/linux-ia32@0.27.2": { "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-loong64@0.25.12": { - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "os": ["linux"], - "cpu": ["loong64"] - }, "@esbuild/linux-loong64@0.25.4": { "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-loong64@0.25.7": { - "integrity": "sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==", - "os": ["linux"], - "cpu": ["loong64"] - }, "@esbuild/linux-loong64@0.27.2": { "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-mips64el@0.25.12": { - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "os": ["linux"], - "cpu": ["mips64el"] - }, "@esbuild/linux-mips64el@0.25.4": { "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-mips64el@0.25.7": { - "integrity": "sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==", - "os": ["linux"], - "cpu": ["mips64el"] - }, "@esbuild/linux-mips64el@0.27.2": { "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-ppc64@0.25.12": { - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "os": ["linux"], - "cpu": ["ppc64"] - }, "@esbuild/linux-ppc64@0.25.4": { "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-ppc64@0.25.7": { - "integrity": "sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==", - "os": ["linux"], - "cpu": ["ppc64"] - }, "@esbuild/linux-ppc64@0.27.2": { "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-riscv64@0.25.12": { - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "os": ["linux"], - "cpu": ["riscv64"] - }, "@esbuild/linux-riscv64@0.25.4": { "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-riscv64@0.25.7": { - "integrity": "sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==", - "os": ["linux"], - "cpu": ["riscv64"] - }, "@esbuild/linux-riscv64@0.27.2": { "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-s390x@0.25.12": { - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "os": ["linux"], - "cpu": ["s390x"] - }, "@esbuild/linux-s390x@0.25.4": { "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-s390x@0.25.7": { - "integrity": "sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==", - "os": ["linux"], - "cpu": ["s390x"] - }, "@esbuild/linux-s390x@0.27.2": { "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-x64@0.25.12": { - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "os": ["linux"], - "cpu": ["x64"] - }, "@esbuild/linux-x64@0.25.4": { "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/linux-x64@0.25.7": { - "integrity": "sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==", - "os": ["linux"], - "cpu": ["x64"] - }, "@esbuild/linux-x64@0.27.2": { "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/netbsd-arm64@0.25.12": { - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "os": ["netbsd"], - "cpu": ["arm64"] - }, "@esbuild/netbsd-arm64@0.25.4": { "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-arm64@0.25.7": { - "integrity": "sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==", - "os": ["netbsd"], - "cpu": ["arm64"] - }, "@esbuild/netbsd-arm64@0.27.2": { "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-x64@0.25.12": { - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "os": ["netbsd"], - "cpu": ["x64"] - }, "@esbuild/netbsd-x64@0.25.4": { "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/netbsd-x64@0.25.7": { - "integrity": "sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==", - "os": ["netbsd"], - "cpu": ["x64"] - }, "@esbuild/netbsd-x64@0.27.2": { "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-arm64@0.25.12": { - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "os": ["openbsd"], - "cpu": ["arm64"] - }, "@esbuild/openbsd-arm64@0.25.4": { "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-arm64@0.25.7": { - "integrity": "sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==", - "os": ["openbsd"], - "cpu": ["arm64"] - }, "@esbuild/openbsd-arm64@0.27.2": { "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-x64@0.25.12": { - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "os": ["openbsd"], - "cpu": ["x64"] - }, "@esbuild/openbsd-x64@0.25.4": { "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-x64@0.25.7": { - "integrity": "sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==", - "os": ["openbsd"], - "cpu": ["x64"] - }, "@esbuild/openbsd-x64@0.27.2": { "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/openharmony-arm64@0.25.12": { - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "os": ["openharmony"], - "cpu": ["arm64"] - }, - "@esbuild/openharmony-arm64@0.25.7": { - "integrity": "sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==", - "os": ["openharmony"], - "cpu": ["arm64"] - }, "@esbuild/openharmony-arm64@0.27.2": { "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@esbuild/sunos-x64@0.25.12": { - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "os": ["sunos"], - "cpu": ["x64"] - }, "@esbuild/sunos-x64@0.25.4": { "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/sunos-x64@0.25.7": { - "integrity": "sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==", - "os": ["sunos"], - "cpu": ["x64"] - }, "@esbuild/sunos-x64@0.27.2": { "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/win32-arm64@0.25.12": { - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "os": ["win32"], - "cpu": ["arm64"] - }, "@esbuild/win32-arm64@0.25.4": { "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-arm64@0.25.7": { - "integrity": "sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==", - "os": ["win32"], - "cpu": ["arm64"] - }, "@esbuild/win32-arm64@0.27.2": { "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-ia32@0.25.12": { - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "os": ["win32"], - "cpu": ["ia32"] - }, "@esbuild/win32-ia32@0.25.4": { "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-ia32@0.25.7": { - "integrity": "sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==", - "os": ["win32"], - "cpu": ["ia32"] - }, "@esbuild/win32-ia32@0.27.2": { "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-x64@0.25.12": { - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "os": ["win32"], - "cpu": ["x64"] - }, "@esbuild/win32-x64@0.25.4": { "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "os": ["win32"], "cpu": ["x64"] }, - "@esbuild/win32-x64@0.25.7": { - "integrity": "sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==", - "os": ["win32"], - "cpu": ["x64"] - }, "@esbuild/win32-x64@0.27.2": { "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "os": ["win32"], @@ -1518,7 +948,7 @@ "dependencies": [ "@types/node@22.19.3", "chardet", - "iconv-lite@0.7.1" + "iconv-lite@0.7.2" ], "optionalPeers": [ "@types/node@22.19.3" @@ -1634,8 +1064,8 @@ "@types/node@22.19.3" ] }, - "@ioredis/commands@1.4.0": { - "integrity": "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==" + "@ioredis/commands@1.5.0": { + "integrity": "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==" }, "@jimp/bmp@0.22.12_@jimp+custom@0.22.12": { "integrity": "sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g==", @@ -1967,15 +1397,12 @@ "wasm-feature-detect" ] }, - "@logtape/logtape@1.3.5": { - "integrity": "sha512-G+MxWB7Tbv/2764519+Cp6rKXUdRbe/GiRwTvlm/Wv/sNsiquRnx9Hzr9eXaIpAYLT4PrBlkthjJ4gmqdSPrFg==" + "@logtape/logtape@1.3.6": { + "integrity": "sha512-OaK8eal8zcjB0GZbllXKgUC2T9h/GyNLQyQXjJkf1yum7SZKTWs9gs/t8NMS0kVVaSnA7bhU0Sjws/Iy4e0/IQ==" }, "@lukeed/csprng@1.1.0": { "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==" }, - "@mjackson/node-fetch-server@0.7.0": { - "integrity": "sha512-un8diyEBKU3BTVj3GzlTPA1kIjCkGdD+AMYQy31Gf9JCkfoZzwgJ79GUtHrF2BN3XPNMLpubbzPcxys+a3uZEw==" - }, "@multiformats/base-x@4.0.1": { "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==" }, @@ -2005,23 +1432,23 @@ "@opentelemetry/api@1.9.0": { "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, - "@opentelemetry/core@2.2.0_@opentelemetry+api@1.9.0": { - "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", + "@opentelemetry/core@2.3.0_@opentelemetry+api@1.9.0": { + "integrity": "sha512-PcmxJQzs31cfD0R2dE91YGFcLxOSN4Bxz7gez5UwSUjCai8BwH/GI5HchfVshHkWdTkUs0qcaPJgVHKXUp7I3A==", "dependencies": [ "@opentelemetry/api", "@opentelemetry/semantic-conventions" ] }, - "@opentelemetry/resources@2.2.0_@opentelemetry+api@1.9.0": { - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "@opentelemetry/resources@2.3.0_@opentelemetry+api@1.9.0": { + "integrity": "sha512-shlr2l5g+87J8wqYlsLyaUsgKVRO7RtX70Ckd5CtDOWtImZgaUDmf4Z2ozuSKQLM2wPDR0TE/3bPVBNJtRm/cQ==", "dependencies": [ "@opentelemetry/api", "@opentelemetry/core", "@opentelemetry/semantic-conventions" ] }, - "@opentelemetry/sdk-trace-base@2.2.0_@opentelemetry+api@1.9.0": { - "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", + "@opentelemetry/sdk-trace-base@2.3.0_@opentelemetry+api@1.9.0": { + "integrity": "sha512-B0TQ2e9h0ETjpI+eGmCz8Ojb+lnYms0SE3jFwEKrN/PK4aSVHU28AAmnOoBmfub+I3jfgPwvDJgomBA5a7QehQ==", "dependencies": [ "@opentelemetry/api", "@opentelemetry/core", @@ -2032,17 +1459,20 @@ "@opentelemetry/semantic-conventions@1.38.0": { "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==" }, - "@optique/core@0.8.6": { - "integrity": "sha512-PpxBi9Fxhfbj90Xh0kyiG1lGRmJgt/iMhwT8E4Ra6RyO2yxBSRNDjfSxL3XjNEIAEdBzJ9GTyqgide/L79H7SQ==" + "@optique/core@0.8.7": { + "integrity": "sha512-5n775SS8aVO7vIW+87sXPJV8SaLq51qxbFS+ptYnFecY6fkpIFYUU2GiPQUr/m8fG6fRuM4RUPJuy6VCXkKfOQ==" }, - "@optique/run@0.8.6": { - "integrity": "sha512-EdOJ/5zBFzsLwpocPwVbOEIKpC6r7hY1QzY0XWKr6KmwRTVj7o1bALGww3cBpi152rGhyqEdNzAovtj0uKlItQ==", + "@optique/run@0.8.7": { + "integrity": "sha512-DF5qMXyP8/l7e7qqM/Yhyb72Ki8DGgxtpN0icLvox4q0NTGgDXEbK7mkEkmVp+ks8VCN/CpFeJACRcHue71Svg==", "dependencies": [ "@optique/core" ] }, - "@oxc-project/types@0.106.0": { - "integrity": "sha512-QdsH3rZq480VnOHSHgPYOhjL8O8LBdcnSjM408BpPCCUc0JYYZPG9Gafl9i3OcGk/7137o+gweb4cCv3WAUykg==" + "@oxc-project/types@0.103.0": { + "integrity": "sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==" + }, + "@oxc-project/types@0.107.0": { + "integrity": "sha512-QFDRbYfV2LVx8tyqtyiah3jQPUj1mK2+RYwxyFWyGoys6XJnwTdlzO6rdNNHOPorHAu5Uo34oWRKcvNpbJarmQ==" }, "@pinojs/redact@0.4.0": { "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" @@ -2080,220 +1510,274 @@ "preact@10.19.6" ] }, - "@prefresh/babel-plugin@0.5.2": { - "integrity": "sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==" - }, - "@prefresh/core@1.5.9_preact@10.19.6": { - "integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==", - "dependencies": [ - "preact@10.19.6" - ] - }, - "@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.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==", - "dependencies": [ - "@babel/core", - "@prefresh/babel-plugin", - "@prefresh/core", - "@prefresh/utils", - "@rollup/pluginutils", - "preact@10.19.6", - "vite" - ] - }, "@quansync/fs@1.0.0": { "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", "dependencies": [ "quansync" ] }, - "@rolldown/binding-android-arm64@1.0.0-beta.58": { - "integrity": "sha512-mWj5eE4Qc8TbPdGGaaLvBb9XfDPvE1EmZkJQgiGKwchkWH4oAJcRAKMTw7ZHnb1L+t7Ah41sBkAecaIsuUgsug==", + "@rolldown/binding-android-arm64@1.0.0-beta.57": { + "integrity": "sha512-GoOVDy8bjw9z1K30Oo803nSzXJS/vWhFijFsW3kzvZCO8IZwFnNa6pGctmbbJstKl3Fv6UBwyjJQN6msejW0IQ==", "os": ["android"], "cpu": ["arm64"] }, - "@rolldown/binding-darwin-arm64@1.0.0-beta.58": { - "integrity": "sha512-wFxUymI/5R8bH8qZFYDfAxAN9CyISEIYke+95oZPiv6EWo88aa5rskjVcCpKA532R+klFmdqjbbaD56GNmTF4Q==", + "@rolldown/binding-android-arm64@1.0.0-beta.59": { + "integrity": "sha512-6yLLgyswYwiCfls9+hoNFY9F8TQdwo15hpXDHzlAR0X/GojeKF+AuNcXjYNbOJ4zjl/5D6lliE8CbpB5t1OWIQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@rolldown/binding-darwin-arm64@1.0.0-beta.57": { + "integrity": "sha512-9c4FOhRGpl+PX7zBK5p17c5efpF9aSpTPgyigv57hXf5NjQUaJOOiejPLAtFiKNBIfm5Uu6yFkvLKzOafNvlTw==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@rolldown/binding-darwin-arm64@1.0.0-beta.59": { + "integrity": "sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rolldown/binding-darwin-x64@1.0.0-beta.58": { - "integrity": "sha512-ybp3MkPj23VDV9PhtRwdU5qrGhlViWRV5BjKwO6epaSlUD5lW0WyY+roN3ZAzbma/9RrMTgZ/a/gtQq8YXOcqw==", + "@rolldown/binding-darwin-x64@1.0.0-beta.57": { + "integrity": "sha512-6RsB8Qy4LnGqNGJJC/8uWeLWGOvbRL/KG5aJ8XXpSEupg/KQtlBEiFaYU/Ma5Usj1s+bt3ItkqZYAI50kSplBA==", "os": ["darwin"], "cpu": ["x64"] }, - "@rolldown/binding-freebsd-x64@1.0.0-beta.58": { - "integrity": "sha512-Evxj3yh7FWvyklUYZa0qTVT9N2zX9TPDqGF056hl8hlCZ9/ndQ2xMv6uw9PD1VlLpukbsqL+/C6M0qwipL0QMg==", + "@rolldown/binding-darwin-x64@1.0.0-beta.59": { + "integrity": "sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@rolldown/binding-freebsd-x64@1.0.0-beta.57": { + "integrity": "sha512-uA9kG7+MYkHTbqwv67Tx+5GV5YcKd33HCJIi0311iYBd25yuwyIqvJfBdt1VVB8tdOlyTb9cPAgfCki8nhwTQg==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.58": { - "integrity": "sha512-tYeXprDOrEgVHUbPXH6MPso4cM/c6RTkmJNICMQlYdki4hGMh92aj3yU6CKs+4X5gfG0yj5kVUw/L4M685SYag==", + "@rolldown/binding-freebsd-x64@1.0.0-beta.59": { + "integrity": "sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.57": { + "integrity": "sha512-3KkS0cHsllT2T+Te+VZMKHNw6FPQihYsQh+8J4jkzwgvAQpbsbXmrqhkw3YU/QGRrD8qgcOvBr6z5y6Jid+rmw==", "os": ["linux"], "cpu": ["arm"] }, - "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.58": { - "integrity": "sha512-N78vmZzP6zG967Ohr+MasCjmKtis0geZ1SOVmxrA0/bklTQSzH5kHEjW5Qn+i1taFno6GEre1E40v0wuWsNOQw==", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59": { + "integrity": "sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.57": { + "integrity": "sha512-A3/wu1RgsHhqP3rVH2+sM81bpk+Qd2XaHTl8LtX5/1LNR7QVBFBCpAoiXwjTdGnI5cMdBVi7Z1pi52euW760Fw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59": { + "integrity": "sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==", "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-arm64-musl@1.0.0-beta.58": { - "integrity": "sha512-l+p4QVtG72C7wI2SIkNQw/KQtSjuYwS3rV6AKcWrRBF62ClsFUcif5vLaZIEbPrCXu5OFRXigXFJnxYsVVZqdQ==", + "@rolldown/binding-linux-arm64-musl@1.0.0-beta.57": { + "integrity": "sha512-d0kIVezTQtazpyWjiJIn5to8JlwfKITDqwsFv0Xc6s31N16CD2PC/Pl2OtKgS7n8WLOJbfqgIp5ixYzTAxCqMg==", "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-x64-gnu@1.0.0-beta.58": { - "integrity": "sha512-urzJX0HrXxIh0FfxwWRjfPCMeInU9qsImLQxHBgLp5ivji1EEUnOfux8KxPPnRQthJyneBrN2LeqUix9DYrNaQ==", + "@rolldown/binding-linux-arm64-musl@1.0.0-beta.59": { + "integrity": "sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rolldown/binding-linux-x64-gnu@1.0.0-beta.57": { + "integrity": "sha512-E199LPijo98yrLjPCmETx8EF43sZf9t3guSrLee/ej1rCCc3zDVTR4xFfN9BRAapGVl7/8hYqbbiQPTkv73kUg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rolldown/binding-linux-x64-gnu@1.0.0-beta.59": { + "integrity": "sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rolldown/binding-linux-x64-musl@1.0.0-beta.57": { + "integrity": "sha512-++EQDpk/UJ33kY/BNsh7A7/P1sr/jbMuQ8cE554ZIy+tCUWCivo9zfyjDUoiMdnxqX6HLJEqqGnbGQOvzm2OMQ==", "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-linux-x64-musl@1.0.0-beta.58": { - "integrity": "sha512-7ijfVK3GISnXIwq/1FZo+KyAUJjL3kWPJ7rViAL6MWeEBhEgRzJ0yEd9I8N9aut8Y8ab+EKFJyRNMWZuUBwQ0A==", + "@rolldown/binding-linux-x64-musl@1.0.0-beta.59": { + "integrity": "sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==", "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-openharmony-arm64@1.0.0-beta.58": { - "integrity": "sha512-/m7sKZCS+cUULbzyJTIlv8JbjNohxbpAOA6cM+lgWgqVzPee3U6jpwydrib328JFN/gF9A99IZEnuGYqEDJdww==", + "@rolldown/binding-openharmony-arm64@1.0.0-beta.57": { + "integrity": "sha512-voDEBcNqxbUv/GeXKFtxXVWA+H45P/8Dec4Ii/SbyJyGvCqV1j+nNHfnFUIiRQ2Q40DwPe/djvgYBs9PpETiMA==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@rolldown/binding-openharmony-arm64@1.0.0-beta.59": { + "integrity": "sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@rolldown/binding-wasm32-wasi@1.0.0-beta.58": { - "integrity": "sha512-6SZk7zMgv+y3wFFQ9qE5P9NnRHcRsptL1ypmudD26PDY+PvFCvfHRkJNfclWnvacVGxjowr7JOL3a9fd1wWhUw==", + "@rolldown/binding-wasm32-wasi@1.0.0-beta.57": { + "integrity": "sha512-bRhcF7NLlCnpkzLVlVhrDEd0KH22VbTPkPTbMjlYvqhSmarxNIq5vtlQS8qmV7LkPKHrNLWyJW/V/sOyFba26Q==", + "dependencies": [ + "@napi-rs/wasm-runtime" + ], + "cpu": ["wasm32"] + }, + "@rolldown/binding-wasm32-wasi@1.0.0-beta.59": { + "integrity": "sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==", "dependencies": [ "@napi-rs/wasm-runtime" ], "cpu": ["wasm32"] }, - "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.58": { - "integrity": "sha512-sFqfYPnBZ6xBhMkadB7UD0yjEDRvs7ipR3nCggblN+N4ODCXY6qhg/bKL39+W+dgQybL7ErD4EGERVbW9DAWvg==", + "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.57": { + "integrity": "sha512-rnDVGRks2FQ2hgJ2g15pHtfxqkGFGjJQUDWzYznEkE8Ra2+Vag9OffxdbJMZqBWXHVM0iS4dv8qSiEn7bO+n1Q==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59": { + "integrity": "sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==", "os": ["win32"], "cpu": ["arm64"] }, - "@rolldown/binding-win32-x64-msvc@1.0.0-beta.58": { - "integrity": "sha512-AnFWJdAqB8+IDPcGrATYs67Kik/6tnndNJV2jGRmwlbeNiQQ8GhRJU8ETRlINfII0pqi9k4WWLnb00p1QCxw/Q==", + "@rolldown/binding-win32-x64-msvc@1.0.0-beta.57": { + "integrity": "sha512-OqIUyNid1M4xTj6VRXp/Lht/qIP8fo25QyAZlCP+p6D2ATCEhyW4ZIFLnC9zAGN/HMbXoCzvwfa8Jjg/8J4YEg==", "os": ["win32"], "cpu": ["x64"] }, - "@rolldown/pluginutils@1.0.0-beta.58": { - "integrity": "sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w==" + "@rolldown/binding-win32-x64-msvc@1.0.0-beta.59": { + "integrity": "sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==", + "os": ["win32"], + "cpu": ["x64"] }, - "@rollup/pluginutils@4.2.1": { - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dependencies": [ - "estree-walker@2.0.2", - "picomatch@2.3.1" - ] + "@rolldown/pluginutils@1.0.0-beta.57": { + "integrity": "sha512-aQNelgx14tGA+n2tNSa9x6/jeoCL9fkDeCei7nOKnHx0fEFRRMu5ReiITo+zZD5TzWDGGRjbSYCs93IfRIyTuQ==" + }, + "@rolldown/pluginutils@1.0.0-beta.59": { + "integrity": "sha512-aoh6LAJRyhtazs98ydgpNOYstxUlsOV1KJXcpf/0c0vFcUA8uyd/hwKRhqE/AAPNqAho9RliGsvitCoOzREoVA==" }, - "@rollup/rollup-android-arm-eabi@4.54.0": { - "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "@rollup/rollup-android-arm-eabi@4.55.1": { + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "os": ["android"], "cpu": ["arm"] }, - "@rollup/rollup-android-arm64@4.54.0": { - "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "@rollup/rollup-android-arm64@4.55.1": { + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "os": ["android"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-arm64@4.54.0": { - "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==", + "@rollup/rollup-darwin-arm64@4.55.1": { + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-x64@4.54.0": { - "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "@rollup/rollup-darwin-x64@4.55.1": { + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "os": ["darwin"], "cpu": ["x64"] }, - "@rollup/rollup-freebsd-arm64@4.54.0": { - "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "@rollup/rollup-freebsd-arm64@4.55.1": { + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@rollup/rollup-freebsd-x64@4.54.0": { - "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "@rollup/rollup-freebsd-x64@4.55.1": { + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rollup/rollup-linux-arm-gnueabihf@4.54.0": { - "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "@rollup/rollup-linux-arm-gnueabihf@4.55.1": { + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm-musleabihf@4.54.0": { - "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "@rollup/rollup-linux-arm-musleabihf@4.55.1": { + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm64-gnu@4.54.0": { - "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "@rollup/rollup-linux-arm64-gnu@4.55.1": { + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-arm64-musl@4.54.0": { - "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "@rollup/rollup-linux-arm64-musl@4.55.1": { + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-loong64-gnu@4.54.0": { - "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "@rollup/rollup-linux-loong64-gnu@4.55.1": { + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-loong64-musl@4.55.1": { + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "os": ["linux"], "cpu": ["loong64"] }, - "@rollup/rollup-linux-ppc64-gnu@4.54.0": { - "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "@rollup/rollup-linux-ppc64-gnu@4.55.1": { + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rollup/rollup-linux-riscv64-gnu@4.54.0": { - "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "@rollup/rollup-linux-ppc64-musl@4.55.1": { + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-riscv64-gnu@4.55.1": { + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-riscv64-musl@4.54.0": { - "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "@rollup/rollup-linux-riscv64-musl@4.55.1": { + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-s390x-gnu@4.54.0": { - "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "@rollup/rollup-linux-s390x-gnu@4.55.1": { + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "os": ["linux"], "cpu": ["s390x"] }, - "@rollup/rollup-linux-x64-gnu@4.54.0": { - "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "@rollup/rollup-linux-x64-gnu@4.55.1": { + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-linux-x64-musl@4.54.0": { - "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "@rollup/rollup-linux-x64-musl@4.55.1": { + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-openharmony-arm64@4.54.0": { - "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "@rollup/rollup-openbsd-x64@4.55.1": { + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-openharmony-arm64@4.55.1": { + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-arm64-msvc@4.54.0": { - "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "@rollup/rollup-win32-arm64-msvc@4.55.1": { + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "os": ["win32"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-ia32-msvc@4.54.0": { - "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "@rollup/rollup-win32-ia32-msvc@4.55.1": { + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "os": ["win32"], "cpu": ["ia32"] }, - "@rollup/rollup-win32-x64-gnu@4.54.0": { - "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "@rollup/rollup-win32-x64-gnu@4.55.1": { + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "os": ["win32"], "cpu": ["x64"] }, - "@rollup/rollup-win32-x64-msvc@4.54.0": { - "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "@rollup/rollup-win32-x64-msvc@4.55.1": { + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "os": ["win32"], "cpu": ["x64"] }, @@ -2363,8 +1847,8 @@ "acorn@8.15.0" ] }, - "@sveltejs/kit@2.49.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.46.1___acorn@8.15.0__vite@7.3.0___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", + "@sveltejs/kit@2.49.4_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "integrity": "sha512-JFtOqDoU0DI/+QSG8qnq5bKcehVb3tCHhOG4amsSYth5/KgO4EkJvi42xSAiyKmXAAULW1/Zdb6lkgGEgSxdZg==", "dependencies": [ "@opentelemetry/api", "@standard-schema/spec", @@ -2389,22 +1873,22 @@ ], "bin": true }, - "@sveltejs/vite-plugin-svelte-inspector@5.0.1_@sveltejs+vite-plugin-svelte@6.2.1__svelte@5.46.1___acorn@8.15.0__vite@7.3.0___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==", + "@sveltejs/vite-plugin-svelte-inspector@5.0.2_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", "dependencies": [ "@sveltejs/vite-plugin-svelte", - "debug@4.4.3", + "obug", "svelte", "vite" ] }, - "@sveltejs/vite-plugin-svelte@6.2.1_svelte@5.46.1__acorn@8.15.0_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", + "@sveltejs/vite-plugin-svelte@6.2.3_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "integrity": "sha512-a+uxqQ9j6Lxmq4plbGaNdM9hgDCZyxAv/yvuyF5iWoA2H5icZkqD3rdK155ZQgFLX2lc3NvahHG4OgKpYqYPiQ==", "dependencies": [ "@sveltejs/vite-plugin-svelte-inspector", - "debug@4.4.3", "deepmerge", "magic-string", + "obug", "svelte", "vite", "vitefu" @@ -2506,8 +1990,8 @@ "@types/wrap-ansi@3.0.0": { "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" }, - "@typescript-eslint/parser@8.51.0_eslint@9.39.2_typescript@5.9.3": { - "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", + "@typescript-eslint/parser@8.52.0_eslint@9.39.2_typescript@5.9.3": { + "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", "dependencies": [ "@typescript-eslint/scope-manager", "@typescript-eslint/types", @@ -2518,8 +2002,8 @@ "typescript" ] }, - "@typescript-eslint/project-service@8.51.0_typescript@5.9.3": { - "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", + "@typescript-eslint/project-service@8.52.0_typescript@5.9.3": { + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", "dependencies": [ "@typescript-eslint/tsconfig-utils", "@typescript-eslint/types", @@ -2527,24 +2011,24 @@ "typescript" ] }, - "@typescript-eslint/scope-manager@8.51.0": { - "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", + "@typescript-eslint/scope-manager@8.52.0": { + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", "dependencies": [ "@typescript-eslint/types", "@typescript-eslint/visitor-keys" ] }, - "@typescript-eslint/tsconfig-utils@8.51.0_typescript@5.9.3": { - "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", + "@typescript-eslint/tsconfig-utils@8.52.0_typescript@5.9.3": { + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", "dependencies": [ "typescript" ] }, - "@typescript-eslint/types@8.51.0": { - "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==" + "@typescript-eslint/types@8.52.0": { + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==" }, - "@typescript-eslint/typescript-estree@8.51.0_typescript@5.9.3": { - "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", + "@typescript-eslint/typescript-estree@8.52.0_typescript@5.9.3": { + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", "dependencies": [ "@typescript-eslint/project-service", "@typescript-eslint/tsconfig-utils", @@ -2552,14 +2036,14 @@ "@typescript-eslint/visitor-keys", "debug@4.4.3", "minimatch@9.0.5", - "semver@7.7.3", + "semver", "tinyglobby", "ts-api-utils", "typescript" ] }, - "@typescript-eslint/utils@8.51.0_eslint@9.39.2_typescript@5.9.3": { - "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", + "@typescript-eslint/utils@8.52.0_eslint@9.39.2_typescript@5.9.3": { + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", "dependencies": [ "@eslint-community/eslint-utils", "@typescript-eslint/scope-manager", @@ -2569,8 +2053,8 @@ "typescript" ] }, - "@typescript-eslint/visitor-keys@8.51.0": { - "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", + "@typescript-eslint/visitor-keys@8.52.0": { + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", "dependencies": [ "@typescript-eslint/types", "eslint-visitor-keys@4.2.1" @@ -2589,11 +2073,11 @@ "tinyrainbow" ] }, - "@vitest/mocker@3.2.4_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "@vitest/mocker@3.2.4_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dependencies": [ "@vitest/spy", - "estree-walker@3.0.3", + "estree-walker", "magic-string", "vite" ], @@ -2783,15 +2267,11 @@ "base64-js@1.5.1": { "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "baseline-browser-mapping@2.9.11": { - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", - "bin": true - }, "birpc@0.2.14": { "integrity": "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==" }, - "birpc@2.9.0": { - "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==" + "birpc@4.0.0": { + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==" }, "blake3-wasm@2.1.5": { "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==" @@ -2832,17 +2312,6 @@ "balanced-match" ] }, - "browserslist@4.28.1": { - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dependencies": [ - "baseline-browser-mapping", - "caniuse-lite", - "electron-to-chromium", - "node-releases", - "update-browserslist-db" - ], - "bin": true - }, "buffer-more-ints@1.0.0": { "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, @@ -2896,9 +2365,6 @@ "callsites@3.1.0": { "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, - "caniuse-lite@1.0.30001762": { - "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==" - }, "canonicalize@2.1.0": { "integrity": "sha512-F705O3xrsUtgt98j7leetNhTWPe+5S72rlL5O4jA1pKqBVQ/dT1O1D6PFxmSXvc0SUOinWS57DKx0I3CHrXJHQ==", "bin": true @@ -2935,14 +2401,8 @@ "chardet@2.1.1": { "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==" }, - "check-error@2.1.1": { - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==" - }, - "chokidar@4.0.3": { - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dependencies": [ - "readdirp" - ] + "check-error@2.1.3": { + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==" }, "cjs-module-lexer@1.4.3": { "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" @@ -3035,9 +2495,6 @@ "content-type@1.0.5": { "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, - "convert-source-map@2.0.0": { - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, "cookie-es@1.2.2": { "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==" }, @@ -3149,9 +2606,6 @@ "dequal" ] }, - "diff@8.0.2": { - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==" - }, "dts-resolver@2.1.3": { "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==" }, @@ -3166,9 +2620,6 @@ "ee-first@1.1.1": { "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, - "electron-to-chromium@1.5.267": { - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==" - }, "emoji-regex-xs@1.0.0": { "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==" }, @@ -3218,43 +2669,6 @@ "es-toolkit@1.43.0": { "integrity": "sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==" }, - "esbuild-wasm@0.25.12": { - "integrity": "sha512-rZqkjL3Y6FwLpSHzLnaEy8Ps6veCNo1kZa9EOfJvmWtBq5dJH4iVjfmOO6Mlkv9B0tt9WFPFmb/VxlgJOnueNg==", - "bin": true - }, - "esbuild@0.25.12": { - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "optionalDependencies": [ - "@esbuild/aix-ppc64@0.25.12", - "@esbuild/android-arm@0.25.12", - "@esbuild/android-arm64@0.25.12", - "@esbuild/android-x64@0.25.12", - "@esbuild/darwin-arm64@0.25.12", - "@esbuild/darwin-x64@0.25.12", - "@esbuild/freebsd-arm64@0.25.12", - "@esbuild/freebsd-x64@0.25.12", - "@esbuild/linux-arm@0.25.12", - "@esbuild/linux-arm64@0.25.12", - "@esbuild/linux-ia32@0.25.12", - "@esbuild/linux-loong64@0.25.12", - "@esbuild/linux-mips64el@0.25.12", - "@esbuild/linux-ppc64@0.25.12", - "@esbuild/linux-riscv64@0.25.12", - "@esbuild/linux-s390x@0.25.12", - "@esbuild/linux-x64@0.25.12", - "@esbuild/netbsd-arm64@0.25.12", - "@esbuild/netbsd-x64@0.25.12", - "@esbuild/openbsd-arm64@0.25.12", - "@esbuild/openbsd-x64@0.25.12", - "@esbuild/openharmony-arm64@0.25.12", - "@esbuild/sunos-x64@0.25.12", - "@esbuild/win32-arm64@0.25.12", - "@esbuild/win32-ia32@0.25.12", - "@esbuild/win32-x64@0.25.12" - ], - "scripts": true, - "bin": true - }, "esbuild@0.25.4": { "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "optionalDependencies": [ @@ -3287,39 +2701,6 @@ "scripts": true, "bin": true }, - "esbuild@0.25.7": { - "integrity": "sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==", - "optionalDependencies": [ - "@esbuild/aix-ppc64@0.25.7", - "@esbuild/android-arm@0.25.7", - "@esbuild/android-arm64@0.25.7", - "@esbuild/android-x64@0.25.7", - "@esbuild/darwin-arm64@0.25.7", - "@esbuild/darwin-x64@0.25.7", - "@esbuild/freebsd-arm64@0.25.7", - "@esbuild/freebsd-x64@0.25.7", - "@esbuild/linux-arm@0.25.7", - "@esbuild/linux-arm64@0.25.7", - "@esbuild/linux-ia32@0.25.7", - "@esbuild/linux-loong64@0.25.7", - "@esbuild/linux-mips64el@0.25.7", - "@esbuild/linux-ppc64@0.25.7", - "@esbuild/linux-riscv64@0.25.7", - "@esbuild/linux-s390x@0.25.7", - "@esbuild/linux-x64@0.25.7", - "@esbuild/netbsd-arm64@0.25.7", - "@esbuild/netbsd-x64@0.25.7", - "@esbuild/openbsd-arm64@0.25.7", - "@esbuild/openbsd-x64@0.25.7", - "@esbuild/openharmony-arm64@0.25.7", - "@esbuild/sunos-x64@0.25.7", - "@esbuild/win32-arm64@0.25.7", - "@esbuild/win32-ia32@0.25.7", - "@esbuild/win32-x64@0.25.7" - ], - "scripts": true, - "bin": true - }, "esbuild@0.27.2": { "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "optionalDependencies": [ @@ -3344,7 +2725,7 @@ "@esbuild/netbsd-x64@0.27.2", "@esbuild/openbsd-arm64@0.27.2", "@esbuild/openbsd-x64@0.27.2", - "@esbuild/openharmony-arm64@0.27.2", + "@esbuild/openharmony-arm64", "@esbuild/sunos-x64@0.27.2", "@esbuild/win32-arm64@0.27.2", "@esbuild/win32-ia32@0.27.2", @@ -3447,9 +2828,6 @@ "estraverse@5.3.0": { "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" }, - "estree-walker@2.0.2": { - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, "estree-walker@3.0.3": { "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dependencies": [ @@ -3573,7 +2951,7 @@ "process-warning@5.0.0", "rfdc", "secure-json-parse", - "semver@7.7.3", + "semver", "toad-cache" ] }, @@ -3586,10 +2964,10 @@ "fdir@6.5.0_picomatch@4.0.3": { "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dependencies": [ - "picomatch@4.0.3" + "picomatch" ], "optionalPeers": [ - "picomatch@4.0.3" + "picomatch" ] }, "fetch-mock@12.6.0": { @@ -3645,8 +3023,8 @@ "unpipe" ] }, - "find-my-way@9.3.0": { - "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", + "find-my-way@9.4.0": { + "integrity": "sha512-5Ye4vHsypZRYtS01ob/iwHzGRUDELlsoCftI/OZFhcLs1M0tkGPcXldE80TAZC5yYuJMBPJQQ43UHlqbJWiX2w==", "dependencies": [ "fast-deep-equal", "fast-querystring", @@ -3687,9 +3065,6 @@ "generator-function@2.0.1": { "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==" }, - "gensync@1.0.0-beta.2": { - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, "get-caller-file@2.0.5": { "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, @@ -3813,8 +3188,8 @@ "hono@4.11.3": { "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==" }, - "hookable@5.5.3": { - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" + "hookable@6.0.1": { + "integrity": "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==" }, "html-void-elements@3.0.0": { "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==" @@ -3863,8 +3238,8 @@ "safer-buffer" ] }, - "iconv-lite@0.7.1": { - "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "iconv-lite@0.7.2": { + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dependencies": [ "safer-buffer" ] @@ -3888,6 +3263,9 @@ "resolve-from" ] }, + "import-without-cache@0.2.5": { + "integrity": "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==" + }, "imurmurhash@0.1.4": { "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" }, @@ -3916,8 +3294,8 @@ "@types/node@22.19.3" ] }, - "ioredis@5.8.2": { - "integrity": "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==", + "ioredis@5.9.1": { + "integrity": "sha512-BXNqFQ66oOsR82g9ajFFsR8ZKrjVvYCLyeML9IvSMAsP56XH2VXBdZjmI11p65nXXJxTEt1hie3J2QeFJVgrtQ==", "dependencies": [ "@ioredis/commands", "cluster-key-slot", @@ -4036,16 +3414,9 @@ "@jimp/utils@1.6.0" ] }, - "jiti@2.6.1": { - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "bin": true - }, "jpeg-js@0.4.4": { "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, - "js-tokens@4.0.0": { - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, "js-tokens@9.0.1": { "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==" }, @@ -4090,16 +3461,12 @@ "json-stable-stringify-without-jsonify@1.0.1": { "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, - "json5@2.2.3": { - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": true - }, "jsonld@9.0.0": { "integrity": "sha512-pjMIdkXfC1T2wrX9B9i2uXhGdyCmgec3qgMht+TDj+S0qX3bjWMQUfL7NeqEhuRTi8G5ESzmL9uGlST7nzSEWg==", "dependencies": [ "@digitalbazaar/http-client", "canonicalize", - "lru-cache@6.0.0", + "lru-cache", "rdf-canonize" ] }, @@ -4209,16 +3576,10 @@ "loupe@3.2.1": { "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==" }, - "lru-cache@5.1.1": { - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": [ - "yallist@3.1.1" - ] - }, "lru-cache@6.0.0": { "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": [ - "yallist@4.0.0" + "yallist" ] }, "magic-string@0.30.21": { @@ -4383,15 +3744,15 @@ "node-mock-http@1.0.4": { "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==" }, - "node-releases@2.0.27": { - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==" - }, "object-assign@4.1.1": { "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect@1.13.4": { "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, + "obug@2.1.1": { + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==" + }, "ohash@2.0.11": { "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==" }, @@ -4525,9 +3886,6 @@ "picocolors@1.1.1": { "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, - "picomatch@2.3.1": { - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, "picomatch@4.0.3": { "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" }, @@ -4599,8 +3957,8 @@ "source-map-js" ] }, - "postgres@3.4.7": { - "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==" + "postgres@3.4.8": { + "integrity": "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==" }, "preact-render-to-string@6.6.5_preact@10.19.6": { "integrity": "sha512-O6MHzYNIKYaiSX3bOw0gGZfEbOmlIDtDfWwN1JJdc/T3ihzRT6tGGSEWE088dWrEDGa1u7101q+6fzQnO9XCPA==", @@ -4611,8 +3969,8 @@ "preact@10.19.6": { "integrity": "sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==" }, - "preact@10.28.1": { - "integrity": "sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==" + "preact@10.28.2": { + "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==" }, "prelude-ls@1.2.1": { "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" @@ -4703,9 +4061,6 @@ "readable-stream" ] }, - "readdirp@4.1.2": { - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==" - }, "real-require@0.2.0": { "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" }, @@ -4774,45 +4129,68 @@ "rfdc@1.4.1": { "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, - "rolldown-plugin-dts@0.13.14_rolldown@1.0.0-beta.58": { - "integrity": "sha512-wjNhHZz9dlN6PTIXyizB6u/mAg1wEFMW9yw7imEVe3CxHSRnNHVyycIX0yDEOVJfDNISLPbkCIPEpFpizy5+PQ==", + "rolldown-plugin-dts@0.20.0_rolldown@1.0.0-beta.57": { + "integrity": "sha512-cLAY1kN2ilTYMfZcFlGWbXnu6Nb+8uwUBsi+Mjbh4uIx7IN8uMOmJ7RxrrRgPsO4H7eSz3E+JwGoL1gyugiyUA==", "dependencies": [ "@babel/generator", "@babel/parser", "@babel/types", "ast-kit", - "birpc@2.9.0", - "debug@4.4.3", + "birpc@4.0.0", "dts-resolver", "get-tsconfig", - "rolldown" + "obug", + "rolldown@1.0.0-beta.57" ] }, - "rolldown@1.0.0-beta.58": { - "integrity": "sha512-v1FCjMZCan7f+xGAHBi+mqiE4MlH7I+SXEHSQSJoMOGNNB2UYtvMiejsq9YuUOiZjNeUeV/a21nSFbrUR+4ZCQ==", + "rolldown@1.0.0-beta.57": { + "integrity": "sha512-lMMxcNN71GMsSko8RyeTaFoATHkCh4IWU7pYF73ziMYjhHZWfVesC6GQ+iaJCvZmVjvgSks9Ks1aaqEkBd8udg==", "dependencies": [ - "@oxc-project/types", - "@rolldown/pluginutils" + "@oxc-project/types@0.103.0", + "@rolldown/pluginutils@1.0.0-beta.57" ], "optionalDependencies": [ - "@rolldown/binding-android-arm64", - "@rolldown/binding-darwin-arm64", - "@rolldown/binding-darwin-x64", - "@rolldown/binding-freebsd-x64", - "@rolldown/binding-linux-arm-gnueabihf", - "@rolldown/binding-linux-arm64-gnu", - "@rolldown/binding-linux-arm64-musl", - "@rolldown/binding-linux-x64-gnu", - "@rolldown/binding-linux-x64-musl", - "@rolldown/binding-openharmony-arm64", - "@rolldown/binding-wasm32-wasi", - "@rolldown/binding-win32-arm64-msvc", - "@rolldown/binding-win32-x64-msvc" + "@rolldown/binding-android-arm64@1.0.0-beta.57", + "@rolldown/binding-darwin-arm64@1.0.0-beta.57", + "@rolldown/binding-darwin-x64@1.0.0-beta.57", + "@rolldown/binding-freebsd-x64@1.0.0-beta.57", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.57", + "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.57", + "@rolldown/binding-linux-arm64-musl@1.0.0-beta.57", + "@rolldown/binding-linux-x64-gnu@1.0.0-beta.57", + "@rolldown/binding-linux-x64-musl@1.0.0-beta.57", + "@rolldown/binding-openharmony-arm64@1.0.0-beta.57", + "@rolldown/binding-wasm32-wasi@1.0.0-beta.57", + "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.57", + "@rolldown/binding-win32-x64-msvc@1.0.0-beta.57" ], "bin": true }, - "rollup@4.54.0": { - "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==", + "rolldown@1.0.0-beta.59": { + "integrity": "sha512-Slm000Gd8/AO9z4Kxl4r8mp/iakrbAuJ1L+7ddpkNxgQ+Vf37WPvY63l3oeyZcfuPD1DRrUYBsRPIXSOhvOsmw==", + "dependencies": [ + "@oxc-project/types@0.107.0", + "@rolldown/pluginutils@1.0.0-beta.59" + ], + "optionalDependencies": [ + "@rolldown/binding-android-arm64@1.0.0-beta.59", + "@rolldown/binding-darwin-arm64@1.0.0-beta.59", + "@rolldown/binding-darwin-x64@1.0.0-beta.59", + "@rolldown/binding-freebsd-x64@1.0.0-beta.59", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59", + "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59", + "@rolldown/binding-linux-arm64-musl@1.0.0-beta.59", + "@rolldown/binding-linux-x64-gnu@1.0.0-beta.59", + "@rolldown/binding-linux-x64-musl@1.0.0-beta.59", + "@rolldown/binding-openharmony-arm64@1.0.0-beta.59", + "@rolldown/binding-wasm32-wasi@1.0.0-beta.59", + "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59", + "@rolldown/binding-win32-x64-msvc@1.0.0-beta.59" + ], + "bin": true + }, + "rollup@4.55.1": { + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "dependencies": [ "@types/estree" ], @@ -4828,12 +4206,15 @@ "@rollup/rollup-linux-arm64-gnu", "@rollup/rollup-linux-arm64-musl", "@rollup/rollup-linux-loong64-gnu", + "@rollup/rollup-linux-loong64-musl", "@rollup/rollup-linux-ppc64-gnu", + "@rollup/rollup-linux-ppc64-musl", "@rollup/rollup-linux-riscv64-gnu", "@rollup/rollup-linux-riscv64-musl", "@rollup/rollup-linux-s390x-gnu", "@rollup/rollup-linux-x64-gnu", "@rollup/rollup-linux-x64-musl", + "@rollup/rollup-openbsd-x64", "@rollup/rollup-openharmony-arm64", "@rollup/rollup-win32-arm64-msvc", "@rollup/rollup-win32-ia32-msvc", @@ -4881,16 +4262,12 @@ "safer-buffer@2.1.2": { "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sax@1.4.3": { - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==" + "sax@1.4.4": { + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==" }, "secure-json-parse@4.1.0": { "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==" }, - "semver@6.3.1": { - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": true - }, "semver@7.7.3": { "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "bin": true @@ -4936,7 +4313,7 @@ "dependencies": [ "color", "detect-libc", - "semver@7.7.3" + "semver" ], "optionalDependencies": [ "@img/sharp-darwin-arm64", @@ -5129,7 +4506,7 @@ "strip-literal@3.1.0": { "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", "dependencies": [ - "js-tokens@9.0.1" + "js-tokens" ] }, "strtok3@10.3.4": { @@ -5218,7 +4595,7 @@ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dependencies": [ "fdir", - "picomatch@4.0.3" + "picomatch" ] }, "tinypool@1.1.1": { @@ -5263,6 +4640,10 @@ "tr46@0.0.3": { "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "tree-kill@1.2.2": { + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": true + }, "trim-lines@3.0.1": { "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" }, @@ -5272,22 +4653,25 @@ "typescript" ] }, - "tsdown@0.12.9_rolldown@1.0.0-beta.58": { - "integrity": "sha512-MfrXm9PIlT3saovtWKf/gCJJ/NQCdE0SiREkdNC+9Qy6UHhdeDPxnkFaBD7xttVUmgp0yUHtGirpoLB+OVLuLA==", + "tsdown@0.18.4_rolldown@1.0.0-beta.57": { + "integrity": "sha512-J/tRS6hsZTkvqmt4+xdELUCkQYDuUCXgBv0fw3ImV09WPGbEKfsPD65E+WUjSu3E7Z6tji9XZ1iWs8rbGqB/ZA==", "dependencies": [ "ansis", "cac", - "chokidar", - "debug@4.4.3", - "diff", + "defu", "empathic", "hookable", - "rolldown", + "import-without-cache", + "obug", + "picomatch", + "rolldown@1.0.0-beta.57", "rolldown-plugin-dts", - "semver@7.7.3", + "semver", "tinyexec@1.0.2", "tinyglobby", - "unconfig" + "tree-kill", + "unconfig-core", + "unrun" ], "bin": true }, @@ -5328,8 +4712,8 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "bin": true }, - "ufo@1.6.1": { - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==" + "ufo@1.6.2": { + "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==" }, "uid@2.0.2": { "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", @@ -5353,16 +4737,6 @@ "quansync" ] }, - "unconfig@7.4.2": { - "integrity": "sha512-nrMlWRQ1xdTjSnSUqvYqJzbTBFugoqHobQj58B2bc8qxHKBBHMNNsWQFP3Cd3/JZK907voM2geYPWqD4VK3MPQ==", - "dependencies": [ - "@quansync/fs", - "defu", - "jiti", - "quansync", - "unconfig-core" - ] - }, "uncrypto@0.1.3": { "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" }, @@ -5372,8 +4746,8 @@ "undici-types@7.16.0": { "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==" }, - "undici@6.22.0": { - "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==" + "undici@6.23.0": { + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==" }, "undici@7.14.0": { "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==" @@ -5424,12 +4798,10 @@ "unpipe@1.0.0": { "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, - "update-browserslist-db@1.2.3_browserslist@4.28.1": { - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "unrun@0.2.24": { + "integrity": "sha512-xa4/O5q2jmI6EqxweJ+sOy5cyORZWcsgmi8pmABVSUyg24Fh44qJrneUHavZEMsbJbghHYWKSraFy5hDCb/m4w==", "dependencies": [ - "browserslist", - "escalade", - "picocolors" + "rolldown@1.0.0-beta.59" ], "bin": true }, @@ -5452,9 +4824,6 @@ "url-template@3.1.1": { "integrity": "sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA==" }, - "urlpattern-polyfill@10.1.0": { - "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==" - }, "utif2@4.1.0": { "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", "dependencies": [ @@ -5495,13 +4864,13 @@ ], "bin": true }, - "vite@7.3.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3": { - "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", + "vite@7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3": { + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dependencies": [ "@types/node@22.19.3", "esbuild@0.27.2", "fdir", - "picomatch@4.0.3", + "picomatch", "postcss", "rollup", "tinyglobby", @@ -5518,7 +4887,7 @@ ], "bin": true }, - "vitefu@1.1.1_vite@7.3.0__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "vitefu@1.1.1_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", "dependencies": [ "vite" @@ -5527,7 +4896,7 @@ "vite" ] }, - "vitest@3.2.4_@types+node@22.19.3_vite@7.3.0__@types+node@22.19.3__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@22.19.3_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dependencies": [ "@types/chai", @@ -5544,7 +4913,7 @@ "expect-type", "magic-string", "pathe", - "picomatch@4.0.3", + "picomatch", "std-env", "tinybench", "tinyexec@0.3.2", @@ -5606,7 +4975,7 @@ "scripts": true, "bin": true }, - "wrangler@4.35.0_@cloudflare+workers-types@4.20260103.0_unenv@2.0.0-rc.21_workerd@1.20250906.0": { + "wrangler@4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0": { "integrity": "sha512-HbyXtbrh4Fi3mU8ussY85tVdQ74qpVS1vctUgaPc+bPrXBTqfDLkZ6VRtHAVF/eBhz4SFmhJtCQpN1caY2Ak8A==", "dependencies": [ "@cloudflare/kv-asset-handler", @@ -5662,9 +5031,6 @@ "y18n@5.0.8": { "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, - "yallist@3.1.1": { - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, "yallist@4.0.0": { "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, @@ -5754,7 +5120,7 @@ "npm:json-preserve-indent@^1.1.3", "npm:postgres@^3.4.7", "npm:preact@10.19.6", - "npm:tsdown@~0.12.9" + "npm:tsdown@~0.18.4" ], "members": { "examples/fresh": { @@ -5877,21 +5243,16 @@ "packageJson": { "dependencies": [ "npm:@js-temporal/polyfill@~0.5.1", - "npm:@multiformats/base-x@^4.0.1", "npm:@opentelemetry/semantic-conventions@^1.27.0", "npm:@types/node@^24.2.1", - "npm:asn1js@^3.0.7", - "npm:fast-check@^3.22.0", "npm:json-canon@^1.0.1", "npm:jsonld@9", "npm:miniflare@^4.20250523.0", "npm:multicodec@^3.2.1", - "npm:pkijs@^3.3.3", "npm:structured-field-values@^2.0.4", "npm:tsx@^4.19.4", "npm:uri-template-router@1", "npm:url-template@^3.1.1", - "npm:urlpattern-polyfill@^10.1.0", "npm:wrangler@^4.17.0" ] } @@ -5944,6 +5305,20 @@ "npm:@sveltejs/kit@2" ] }, + "packages/vocab": { + "dependencies": [ + "npm:@opentelemetry/api@^1.9.0", + "npm:fast-check@^3.22.0", + "npm:fetch-mock@^12.5.2", + "npm:jsonld@9" + ], + "packageJson": { + "dependencies": [ + "npm:jsonld@9", + "npm:multicodec@^3.2.1" + ] + } + }, "packages/vocab-runtime": { "dependencies": [ "npm:@multiformats/base-x@^4.0.1", @@ -5955,11 +5330,8 @@ ], "packageJson": { "dependencies": [ - "npm:@multiformats/base-x@^4.0.1", "npm:@types/node@^24.2.1", - "npm:asn1js@^3.0.6", - "npm:multicodec@^3.2.1", - "npm:pkijs@^3.2.5" + "npm:multicodec@^3.2.1" ] } }, @@ -5975,6 +5347,17 @@ "npm:yaml@^2.8.1" ] } + }, + "packages/webfinger": { + "dependencies": [ + "npm:es-toolkit@^1.42.0", + "npm:fetch-mock@^12.5.4" + ], + "packageJson": { + "dependencies": [ + "npm:@types/node@^24.2.1" + ] + } } } } diff --git a/docs/manual/access-control.md b/docs/manual/access-control.md index 147d11628..c89c11479 100644 --- a/docs/manual/access-control.md +++ b/docs/manual/access-control.md @@ -35,7 +35,8 @@ authorized fetch for the actor dispatcher: ~~~~ typescript{9-11} twoslash // @noErrors: 2307 2345 -import type { Actor, Federation } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Actor } from "@fedify/vocab"; /** * A hypothetical `Federation` instance. */ @@ -68,7 +69,8 @@ The equivalent method is available for collections as well: ~~~~ typescript{9-11} twoslash // @noErrors: 2307 2345 -import type { Actor, Federation } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Actor } from "@fedify/vocab"; /** * A hypothetical `Federation` instance. */ @@ -116,7 +118,8 @@ actor). The below pseudo code shows how to filter out private posts: ~~~~ typescript{7} twoslash // @noErrors: 2307 -import type { Actor, Create, Federation } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Actor, Create } from "@fedify/vocab"; const federation = null as unknown as Federation; interface Post { /** @@ -177,7 +180,8 @@ domain name, such as `example.com@example.com`. Here is an example of how to implement an instance actor: ~~~~ typescript{3-11,20-27} twoslash -import { type Actor, Application, type Federation, Person } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { type Actor, Application, Person } from "@fedify/vocab"; /** * A hypothetical `Federation` instance. */ diff --git a/docs/manual/actor.md b/docs/manual/actor.md index 8c99a42b1..30c15e7a5 100644 --- a/docs/manual/actor.md +++ b/docs/manual/actor.md @@ -32,7 +32,8 @@ const federation = null as unknown as Federation; interface User { } const user = null as User | null; // ---cut-before--- -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ // Omitted for brevity; see the related section for details. @@ -196,7 +197,8 @@ the URIs of the actor's endpoints. The most important endpoint is the `sharedIn to generate the URI of the actor's shared inbox: ~~~~ typescript twoslash -import { Endpoints, Context } from "@fedify/fedify"; +import { Context } from "@fedify/fedify"; +import { Endpoints } from "@fedify/vocab"; const ctx = null as unknown as Context; // ---cut-before--- new Endpoints({ sharedInbox: ctx.getInboxUri() }) @@ -245,7 +247,8 @@ the `~ActorCallbackSetters.setKeyPairsDispatcher()` method so that Fedify can dispatch appropriate key pairs by the actor's identifier: ~~~~ typescript{4-6,10-14,17-26} twoslash -import { type Federation, Person } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; interface User {} const user = null as User | null; @@ -514,7 +517,8 @@ If you want to provide links with other `rel` than `url` property: ~~~~ typescript{8-16} twoslash -import { type Federation, Person, Link } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Link, Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation diff --git a/docs/manual/collections.md b/docs/manual/collections.md index 4d8f6c1e9..8503ad693 100644 --- a/docs/manual/collections.md +++ b/docs/manual/collections.md @@ -85,7 +85,7 @@ interface Post { */ function getPostsByUserId(userId: string): Post[] { return []; } // ---cut-before--- -import { Article, Create } from "@fedify/fedify"; +import { Article, Create } from "@fedify/vocab"; federation .setOutboxDispatcher("/users/{identifier}/outbox", async (ctx, identifier) => { @@ -178,7 +178,8 @@ Here's an example of how to implement collection pages for the outbox collection with assuming that the database system supports cursor-based pagination: ~~~~ typescript twoslash -import { Article, Create, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article, Create } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents a post. @@ -290,7 +291,8 @@ The value for the first cursor is determined by `~CollectionCallbackSetters.setFirstCursor()` method: ~~~~ typescript twoslash -import { Article, Create, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article, Create } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents a post. @@ -447,7 +449,8 @@ So, the below example assumes that the database system supports offset-based pagination, which is easy to implement backward pagination: ~~~~ typescript twoslash -import { Article, Create, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article, Create } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents a post. @@ -610,7 +613,7 @@ async function countInboxByUserId(userId: string): Promise { return 0; } // ---cut-before--- -import { Activity } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; federation .setInboxDispatcher("/users/{identifier}/inbox", async (ctx, identifier) => { @@ -790,7 +793,8 @@ has to consist of `Recipient` objects that represent the actors. The below example shows how to construct a followers collection: ~~~~ typescript twoslash -import type { Federation, Recipient } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents an actor in the database. @@ -904,7 +908,8 @@ the `Context.sendActivity()` method, you should return the entire followers collection when the `cursor` parameter is `null`: ~~~~ typescript{5-17} twoslash -import type { Federation, Recipient } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents an actor in the database. @@ -1031,7 +1036,8 @@ The following example shows how to filter the followers collection by the server: ~~~~ typescript{8-11} twoslash -import type { Federation, Recipient } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents an actor in the database. @@ -1146,7 +1152,7 @@ async function getLikedByUserId(userId: string): Promise { return []; } // ---cut-before--- -import type { Object } from "@fedify/fedify"; +import type { Object } from "@fedify/vocab"; federation .setLikedDispatcher("/users/{identifier}/liked", async (ctx, identifier, cursor) => { @@ -1171,7 +1177,7 @@ async function getLikedByUserId(userId: string): Promise { return []; } // ---cut-before--- -import type { Object } from "@fedify/fedify"; +import type { Object } from "@fedify/vocab"; federation .setLikedDispatcher("/users/{identifier}/liked", async (ctx, identifier, cursor) => { @@ -1238,7 +1244,8 @@ as the outbox collection, so we don't repeat the explanation here. The below example shows how to construct a featured collection: ~~~~ typescript twoslash -import type { Object, Federation } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Object } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical function that returns the objects that an actor has featured. @@ -1312,7 +1319,8 @@ way as the outbox collection, so we don't repeat the explanation here. The below example shows how to construct a featured tags collection: ~~~~ typescript twoslash -import { Hashtag, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Hashtag } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical function that returns the tags that an actor has featured. @@ -1401,7 +1409,8 @@ collections. Both methods work similarly to the built-in collection dispatchers. Here's an example of creating a custom collection of bookmarked posts: ~~~~ typescript twoslash -import { Article, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents a bookmarked post. @@ -1476,7 +1485,8 @@ federation For ordered collections, simply use `setOrderedCollectionDispatcher()` instead: ~~~~ typescript twoslash -import { Article, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical type that represents a bookmarked post. @@ -1560,7 +1570,8 @@ Custom collections support the same callback methods as built-in collections: Custom collections can have multiple parameters in their URI patterns: ~~~~ typescript twoslash -import { Note, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical function that returns posts by category. @@ -1628,7 +1639,8 @@ ctx.getCollectionUri("category-posts", { You can restrict access to custom collections using the `.authorize()` method: ~~~~ typescript twoslash -import { Article, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Article } from "@fedify/vocab"; const federation = null as unknown as Federation; /** * A hypothetical function that checks if a user can access another user's bookmarks. diff --git a/docs/manual/context.md b/docs/manual/context.md index 7f28fb097..5d84fcc5e 100644 --- a/docs/manual/context.md +++ b/docs/manual/context.md @@ -110,7 +110,8 @@ Here's an example of using the `~Context.getActorUri()` method in the actor dispatcher: ~~~~ typescript twoslash -import { type Federation, Person } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; interface User { } const user: User | null = true ? { } : null; @@ -142,7 +143,7 @@ example in an [inbox listener](./inbox.md): import { type Federation } from "@fedify/fedify"; const federation = null as unknown as Federation; // ---cut-before--- -import { Accept, Follow } from "@fedify/fedify"; +import { Accept, Follow } from "@fedify/vocab"; federation .setInboxListeners("/users/{identifier}/inbox", "/inbox") @@ -193,7 +194,8 @@ object from the URL arguments. The following shows an example of using the `RequestContext.getActor()` method: ~~~~ typescript twoslash -import { type Federation, Update } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Update } from "@fedify/vocab"; const federation = null as unknown as Federation; const request = new Request(""); const identifier: string = ""; @@ -218,7 +220,8 @@ In the same way, you can use the `RequestContext.getObject()` method to dispatch an object from the URL arguments. The following shows an example: ~~~~ typescript twoslash -import { type Federation, Note } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = null as unknown as Federation; const request = new Request(""); const identifier: string = ""; @@ -248,7 +251,8 @@ compatible with `Context`. So you can just pass a `Context` object to those methods: ~~~~ typescript twoslash -import { type Context, Object } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Object } from "@fedify/vocab"; const ctx = null as unknown as Context; const jsonLd: unknown = {}; // ---cut-before--- @@ -268,7 +272,8 @@ In such cases, you can use the `Context.getDocumentLoader()` method to get an authenticated `DocumentLoader` object. The following shows an example: ~~~~ typescript twoslash -import { type Actor, type Context, Person } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { type Actor, Person } from "@fedify/vocab"; const ctx = null as unknown as Context; const actor = new Person({}) as Actor; // ---cut-before--- @@ -325,7 +330,7 @@ Looking up remote objects > For example, you can get the `object` from an `Activity` object directly: > > ~~~~ typescript twoslash -> import { Activity } from "@fedify/fedify"; +> import { Activity } from "@fedify/vocab"; > const activity = new Activity({}); > // ---cut-before--- > const object = await activity.getObject(); @@ -334,7 +339,8 @@ Looking up remote objects > … instead of: > > ~~~~ typescript twoslash -> import { Activity, type Context } from "@fedify/fedify"; +> import { type Context } from "@fedify/fedify"; +> import { Activity } from "@fedify/vocab"; > const ctx = null as unknown as Context; > const activity = new Activity({}); > // ---cut-before--- @@ -507,7 +513,8 @@ and so on. The `Context.traverseCollection()` method plays a role in such cases. The following shows an example of traversing an actor's outbox: ~~~~ typescript twoslash -import { type Context, isActor } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { isActor } from "@fedify/vocab"; const ctx = null as unknown as Context; // ---cut-before--- const actor = await ctx.lookupObject("@hongminhee@fosstodon.org"); diff --git a/docs/manual/deploy.md b/docs/manual/deploy.md index bfe6d2d8a..808c93cec 100644 --- a/docs/manual/deploy.md +++ b/docs/manual/deploy.md @@ -228,7 +228,7 @@ type Env = { KV_NAMESPACE: KVNamespace; QUEUE: Queue; }; -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- import { createFederationBuilder } from "@fedify/fedify"; import { WorkersKvStore, WorkersMessageQueue } from "@fedify/cfworkers"; @@ -265,7 +265,8 @@ must manually connect queue handlers: ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederationBuilder, Person, type Message } from "@fedify/fedify"; +import { createFederationBuilder, type Message } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import { WorkersKvStore, WorkersMessageQueue } from "@fedify/cfworkers"; type Env = { diff --git a/docs/manual/federation.md b/docs/manual/federation.md index e14984482..27422e9ab 100644 --- a/docs/manual/federation.md +++ b/docs/manual/federation.md @@ -468,7 +468,8 @@ and is available in the `Context` object passed to the dispatchers and listeners. For example, you can access the `Federation` object like this: ~~~~ typescript twoslash -import { type FederationBuilder, Person } from "@fedify/fedify"; +import { type FederationBuilder } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const builder = null as unknown as FederationBuilder; // ---cut-before--- builder.setActorDispatcher( diff --git a/docs/manual/inbox.md b/docs/manual/inbox.md index c25704fb8..a81bb3922 100644 --- a/docs/manual/inbox.md +++ b/docs/manual/inbox.md @@ -51,7 +51,8 @@ a time. The following shows how to register an inbox listener: ~~~~ typescript{7-20} twoslash // @noErrors: 2345 -import { createFederation, Accept, Follow } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Accept, Follow } from "@fedify/vocab"; const federation = createFederation({ // Omitted for brevity; see the related section for details. @@ -116,7 +117,8 @@ the `to`, `cc`, `bto`, or `bcc` field of the activity. The following shows how to determine the recipient of a `Create` activity: ~~~~ typescript twoslash -import { Create, type InboxListenerSetters } from "@fedify/fedify"; +import { type InboxListenerSetters } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; (0 as unknown as InboxListenerSetters) // ---cut-before--- .on(Create, async (ctx, create) => { @@ -132,7 +134,8 @@ The `to`, `cc`, `bto`, and `bcc` fields can contain multiple recipients, so you may need to iterate over them to determine the recipient of the activity: ~~~~ typescript twoslash -import { Create, type InboxListenerSetters } from "@fedify/fedify"; +import { type InboxListenerSetters } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; (0 as unknown as InboxListenerSetters) // ---cut-before--- .on(Create, async (ctx, create) => { @@ -150,12 +153,8 @@ collection objects. In such cases, you may need to recursively resolve the collection objects to determine the recipients of the activity: ~~~~ typescript twoslash -import { - Collection, - Create, - type InboxListenerSetters, - isActor, -} from "@fedify/fedify"; +import { type InboxListenerSetters } from "@fedify/fedify"; +import { Collection, Create, isActor } from "@fedify/vocab"; (0 as unknown as InboxListenerSetters) // ---cut-before--- .on(Create, async (ctx, create) => { @@ -190,7 +189,8 @@ the `InboxContext.recipient` property. The below example shows how to determine the recipient of a `Follow` activity: ~~~~ typescript twoslash -import { Follow, type InboxListenerSetters } from "@fedify/fedify"; +import { type InboxListenerSetters } from "@fedify/fedify"; +import { Follow } from "@fedify/vocab"; (0 as unknown as InboxListenerSetters) // ---cut-before--- .on(Follow, async (ctx, follow) => { @@ -243,7 +243,7 @@ pattern: import type { Federation } from "@fedify/fedify"; const federation = null as unknown as Federation; // ---cut-before--- -import { Application, Person } from "@fedify/fedify"; +import { Application, Person } from "@fedify/vocab"; federation .setInboxListeners("/users/{identifier}/inbox", "/inbox") @@ -427,7 +427,8 @@ You can configure the idempotency strategy using the `~InboxListenerSetters.withIdempotency()` method: ~~~~ typescript twoslash -import { type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -446,7 +447,8 @@ the inbox context and the activity, and should return a unique cache key for the activity, or `null` to skip idempotency checking for that activity: ~~~~ typescript twoslash -import { type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -485,7 +487,8 @@ function that takes a `Context` object and an error object. The following shows an example of handling errors: ~~~~ typescript{6-8} twoslash -import { type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -529,7 +532,8 @@ modification, so the signature made by the original sender is preserved The following shows an example of forwarding `Create` activities to followers: ~~~~ typescript twoslash -import { Create, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const federation: Federation = null as unknown as Federation; federation.setInboxListeners("/{identifier}/inbox", "/inbox") // ---cut-before--- @@ -626,7 +630,8 @@ The following code shows how to route an `Activity` object enclosed in top-level `Announce` object to the corresponding inbox listener: ~~~~ typescript twoslash -import { Activity, Announce, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Activity, Announce } from "@fedify/vocab"; const federation = null as unknown as Federation; @@ -647,7 +652,8 @@ As another example, the following code shows how to invoke the corresponding inbox listeners for a remote actor's activities: ~~~~ typescript twoslash -import { Activity, type Context, isActor } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity, isActor } from "@fedify/vocab"; async function main(context: Context) { // ---cut-before--- diff --git a/docs/manual/lint.md b/docs/manual/lint.md index 569cb1637..62cea4f2d 100644 --- a/docs/manual/lint.md +++ b/docs/manual/lint.md @@ -275,7 +275,8 @@ and to receive activities from other servers. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing id property @@ -308,7 +309,8 @@ won't be able to properly verify the actor's identity or send activities to it. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using hardcoded URL @@ -351,7 +353,8 @@ are legitimate. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing publicKey when setKeyPairsDispatcher is configured @@ -401,7 +404,8 @@ Signatures. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing assertionMethod when setKeyPairsDispatcher is configured @@ -454,7 +458,8 @@ activities. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing inbox when setInboxListeners is configured @@ -493,7 +498,8 @@ a different URI will cause incoming activities to fail. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using hardcoded URL @@ -527,7 +533,8 @@ activities. It's part of the standard ActivityPub actor profile. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing outbox when setOutboxDispatcher is configured @@ -565,7 +572,8 @@ The outbox URI must match the path configured in `setOutboxDispatcher()`. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -600,7 +608,8 @@ which is important for activity delivery and social graph discovery. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing followers when setFollowersDispatcher is configured @@ -639,7 +648,8 @@ The followers URI must match the path configured in `setFollowersDispatcher()`. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -673,7 +683,8 @@ The following URL allows other servers to discover who this actor follows. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing following when setFollowingDispatcher is configured @@ -712,7 +723,8 @@ The following URI must match the path configured in `setFollowingDispatcher()`. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -746,7 +758,8 @@ liked. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing liked when setLikedDispatcher is configured @@ -783,7 +796,8 @@ The liked URI must match the path configured in `setLikedDispatcher()`. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -818,7 +832,8 @@ highlighted content (commonly shown at the top of a profile). ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing featured when setFeaturedDispatcher is configured @@ -857,7 +872,8 @@ The featured URI must match the path configured in `setFeaturedDispatcher()`. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -893,7 +909,8 @@ hashtags (commonly used for profile discovery). ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing featuredTags when setFeaturedTagsDispatcher is configured @@ -933,7 +950,8 @@ The featuredTags URI must match the path configured in ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using wrong context method @@ -969,7 +987,8 @@ on your server with a single request, improving federation efficiency. ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Endpoints, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Missing sharedInbox when setInboxListeners has shared inbox path @@ -1010,7 +1029,8 @@ The shared inbox URI must match the shared inbox path configured in ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Endpoints, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Bad: Using getInboxUri with identifier for shared inbox @@ -1088,7 +1108,8 @@ Here's an example of code that would trigger lint errors: ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ❌ Wrong: Using relative URL for actor ID @@ -1107,7 +1128,8 @@ Corrected version: ~~~~ typescript twoslash // @noErrors: 2345 -import { createFederation, Person } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: null as any }); // ---cut-before--- // ✅ Correct: Using Context.getActorUri() for actor ID diff --git a/docs/manual/object.md b/docs/manual/object.md index dd0e8cdef..49e071f10 100644 --- a/docs/manual/object.md +++ b/docs/manual/object.md @@ -27,7 +27,8 @@ The below example shows how to register an object dispatcher: // @noErrors: 2345 const note: { id: string; content: string } = { id: "", content: "" }; // ---cut-before--- -import { createFederation, Note } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = createFederation({ // Omitted for brevity; see the related section for details. @@ -74,7 +75,8 @@ of the object. The below example shows how to construct an object URI: ~~~~ typescript twoslash -import { type Context, Note } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const ctx = null as unknown as Context; // ---cut-before--- ctx.getObjectUri(Note, { diff --git a/docs/manual/pragmatics.md b/docs/manual/pragmatics.md index 6bb8cf8f4..c5b9da747 100644 --- a/docs/manual/pragmatics.md +++ b/docs/manual/pragmatics.md @@ -55,7 +55,7 @@ If an actor is represented as an `Application` or `Service` object, it is considered an automated actor by Mastodon and a bot actor by Misskey. ~~~~ typescript twoslash -import { Application } from "@fedify/fedify"; +import { Application } from "@fedify/vocab"; // ---cut-before--- new Application({ // [!code highlight] name: "Fedify Demo", @@ -76,7 +76,7 @@ If an actor is represented as a `Group` object, it is considered a group actor by Mastodon. ~~~~ typescript twoslash -import { Group } from "@fedify/fedify"; +import { Group } from "@fedify/vocab"; // ---cut-before--- new Group({ // [!code highlight] name: "Fedify Demo", @@ -106,7 +106,7 @@ a nickname of a person, or a title of a group or an organization. It is displayed in the profile page of an actor and the timeline. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", // [!code highlight] @@ -131,7 +131,7 @@ implementations. The bio is displayed in the profile page of the actor. > entities if it contains characters like `<`, `>`, and `&`. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -157,7 +157,7 @@ The date joined is displayed in the profile page of the actor. > implementations that display the date and time. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import { Temporal } from "@js-temporal/polyfill"; // ---cut-before--- new Person({ @@ -181,7 +181,7 @@ ActivityPub implementations. The avatar image is displayed next to the name of the actor in the profile page and the timeline. ~~~~ typescript{5-8} twoslash -import { Image, Person } from "@fedify/fedify"; +import { Image, Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -206,7 +206,7 @@ The `image` property is used as a header image in Mastodon and Misskey. The header image is displayed on the top of the profile page. ~~~~ typescript{5-8} twoslash -import { Image, Person } from "@fedify/fedify"; +import { Image, Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -231,7 +231,7 @@ The `attachments` property is used as custom fields in Mastodon and Misskey. The custom fields are displayed as a table in the profile page. ~~~~ typescript{5-18} twoslash -import { Person, PropertyValue } from "@fedify/fedify"; +import { Person, PropertyValue } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -280,7 +280,7 @@ a locked account if the `manuallyApprovesFollowers` property is `true`. > account. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -303,7 +303,7 @@ If the `suspended` property is `true`, the profile page of the actor is displayed as suspended. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -326,7 +326,7 @@ If the `memorial` property is `true`, the profile page of the actor is displayed as memorialized. ~~~~ typescript twoslash -import { Person } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; // ---cut-before--- new Person({ name: "Fedify Demo", @@ -387,7 +387,8 @@ is displayed in the profile page of the actor. Each item in the collection is a `Recipient` or an `Actor` that follows the actor. ~~~~ typescript twoslash -import type { Federation, Recipient } from "@fedify/fedify"; +import type { Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation diff --git a/docs/manual/send.md b/docs/manual/send.md index 3edbcf6c1..2b54f25f5 100644 --- a/docs/manual/send.md +++ b/docs/manual/send.md @@ -33,7 +33,8 @@ To send an activity to another actor, you can use the `Context.sendActivity()` method. The following shows how to send a `Follow` activity to another actor: ~~~~ typescript{8-15} twoslash -import { type Context, Follow, type Recipient } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Follow, type Recipient } from "@fedify/vocab"; async function sendFollow( ctx: Context, @@ -71,7 +72,8 @@ the actor with the given identifier. The identifier is used to find the actor's key pairs to sign the activity: ~~~~ typescript twoslash -import { Activity, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); // ---cut-before--- @@ -89,7 +91,8 @@ the actor with the given WebFinger username. The username is used to find the actor's key pairs to sign the activity: ~~~~ typescript twoslash -import { Activity, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); // ---cut-before--- @@ -110,12 +113,8 @@ If you specify a `SenderKeyPair` object or an array of `SenderKeyPair` objects, the sender is the set of the given key pairs: ~~~~ typescript twoslash -import { - Activity, - type Actor, - type Context, - SenderKeyPair, -} from "@fedify/fedify"; +import { type Context, SenderKeyPair } from "@fedify/fedify"; +import { Activity, type Actor } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); const recipients: Actor[] = []; @@ -147,7 +146,8 @@ inboxes (or shared inboxes if some actors support it and you turn on the `preferSharedInbox` option): ~~~~ typescript twoslash -import { Activity, type Actor, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity, type Actor } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); const actor = {} as Actor; @@ -162,7 +162,8 @@ await ctx.sendActivity( Or you can specify multiple actors: ~~~~ typescript twoslash -import { Activity, type Actor, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity, type Actor } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); const actor = {} as Actor; @@ -197,7 +198,8 @@ export interface Recipient { Here's an example of specifying a `Recipient` object: ~~~~ typescript{3-6} twoslash -import { Activity, type Context, Recipient } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); // ---cut-before--- @@ -214,7 +216,8 @@ await ctx.sendActivity( Or you can provide its shared inbox endpoint as well: ~~~~ typescript{6-8} twoslash -import { Activity, type Context, Recipient } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); // ---cut-before--- @@ -246,7 +249,8 @@ followers of the sender. It is a special value that represents the followers of the sender: ~~~~ typescript twoslash -import { Activity, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = new Activity({}); // ---cut-before--- @@ -331,9 +335,8 @@ and you can set them to `Actor` objects, `Collection` objects, or `URL` objects. To wrap up, the following is an example of sending a `Create` activity: ~~~~ typescript twoslash -import { - type Context, Create, Note, type Actor, PUBLIC_COLLECTION, -} from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { type Actor, Create, Note, PUBLIC_COLLECTION } from "@fedify/vocab"; const ctx = null as unknown as Context; const senderId: string = ""; const noteId: string = ""; @@ -446,7 +449,8 @@ You can control this behavior using the `fanout` option in the `~Context.sendActivity()` method: ~~~~ typescript twoslash -import type { Activity, Context, Recipient } from "@fedify/fedify"; +import type { Context } from "@fedify/fedify"; +import type { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = {} as Activity; const recipients: Recipient[] = []; @@ -480,7 +484,8 @@ The `fanout` option accepts the following values: Use the default `"auto"` for most cases: ~~~~ typescript twoslash -import type { Activity, Context, Recipient } from "@fedify/fedify"; +import type { Context } from "@fedify/fedify"; +import type { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = {} as Activity; const recipients: Recipient[] = []; @@ -491,7 +496,8 @@ await ctx.sendActivity({ identifier: "alice" }, recipients, activity); Use `"skip"` when you need different content for each recipient: ~~~~ typescript twoslash -import type { Activity, Context, Recipient } from "@fedify/fedify"; +import type { Context } from "@fedify/fedify"; +import type { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = {} as Activity; const recipients: Recipient[] = []; @@ -507,7 +513,8 @@ await ctx.sendActivity( Use `"force"` to ensure fan-out behavior even with few recipients (rarely needed): ~~~~ typescript twoslash -import type { Activity, Context, Recipient } from "@fedify/fedify"; +import type { Context } from "@fedify/fedify"; +import type { Activity, Recipient } from "@fedify/vocab"; const ctx = null as unknown as Context; const activity = {} as Activity; const recipients: Recipient[] = []; @@ -530,7 +537,8 @@ You can do this by calling the `~Context.sendActivity()` method with the ~~~~ typescript twoslash -import { type Context, Follow, type Recipient } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Follow, type Recipient } from "@fedify/vocab"; async function sendFollow( ctx: Context, @@ -561,13 +569,8 @@ recipient's personal inbox. To deliver an activity to the shared inbox, you can pass the `preferSharedInbox` option: ~~~~ typescript twoslash -import { - type Context, - Create, - Note, - type Recipient, - PUBLIC_COLLECTION, -} from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Create, Note, type Recipient, PUBLIC_COLLECTION } from "@fedify/vocab"; async function sendNote( ctx: Context, @@ -633,7 +636,8 @@ the `"followers"` string and turning on the `~SendActivityOptionsForCollection.syncCollection` option: ~~~~ typescript twoslash -import { type Context, Create, Note } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Create, Note } from "@fedify/vocab"; const ctx = null as unknown as Context; const senderId : string = ""; // ---cut-before--- @@ -694,7 +698,8 @@ To exclude same-server recipients, you can pass the `excludeBaseUris` option to the `~Context.sendActivity()` method: ~~~~ typescript twoslash -import { Activity, type Context } from "@fedify/fedify"; +import { type Context } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; const ctx = null as unknown as Context; const senderId: string = ""; const activity = new Activity({}); @@ -937,7 +942,7 @@ property contains the full actor object inlined. For example, the following activity: ~~~~ typescript{3-7} twoslash -import { Follow, Person } from "@fedify/fedify"; +import { Follow, Person } from "@fedify/vocab"; // ---cut-before--- new Follow({ id: new URL("http://example.com/activities/1"), @@ -957,7 +962,7 @@ new Follow({ is transformed into: ~~~~ typescript twoslash -import { Follow, Person } from "@fedify/fedify"; +import { Follow, Person } from "@fedify/vocab"; // ---cut-before--- new Follow({ id: new URL("http://example.com/activities/1"), diff --git a/docs/manual/test.md b/docs/manual/test.md index f9fde2175..51a069f34 100644 --- a/docs/manual/test.md +++ b/docs/manual/test.md @@ -201,7 +201,7 @@ Here's a basic example of using `createFederation()`: ~~~~ typescript twoslash import { createFederation } from "@fedify/testing"; -import { Create, Note } from "@fedify/fedify/vocab"; +import { Create, Note } from "@fedify/vocab"; // Create a mock federation with context data const federation = createFederation<{ userId: string }>({ @@ -240,7 +240,7 @@ sent activities and provides mock implementations of URI generation methods: ~~~~ typescript twoslash import { createFederation } from "@fedify/testing"; -import { Create, Note, Person } from "@fedify/fedify/vocab"; +import { Create, Note, Person } from "@fedify/vocab"; // Create a mock federation and context const federation = createFederation<{ userId: string }>(); @@ -281,7 +281,7 @@ configured in your test federation: ~~~~ typescript twoslash import { createFederation } from "@fedify/testing"; -import { Note } from "@fedify/fedify/vocab"; +import { Note } from "@fedify/vocab"; const federation = createFederation(); diff --git a/docs/manual/uri-template.md b/docs/manual/uri-template.md index f121d7e00..b2ba5a543 100644 --- a/docs/manual/uri-template.md +++ b/docs/manual/uri-template.md @@ -47,7 +47,8 @@ characters like `:` and spaces are percent-encoded: Here's how to use it in an actor dispatcher: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( @@ -86,7 +87,8 @@ This prevents double-encoding issues when your identifier is itself a URI: Here's how to use it when your identifiers might contain URIs: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( @@ -148,7 +150,8 @@ If you're using simple usernames or UUIDs as actor identifiers, use simple expansion. This will properly encode any special characters: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( @@ -169,7 +172,8 @@ a proxy layer on top of existing ActivityPub servers), use reserved expansion to avoid double-encoding: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( @@ -191,7 +195,8 @@ The same principle applies to collections. Use simple expansion when your identifiers are basic strings: ~~~~ typescript twoslash -import { type Federation, type Recipient } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setFollowersDispatcher( @@ -207,7 +212,8 @@ federation.setFollowersDispatcher( And use reserved expansion when identifiers might contain URIs: ~~~~ typescript twoslash -import { type Federation, type Recipient } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setFollowersDispatcher( @@ -228,7 +234,8 @@ Here are some additional examples: Inbox listeners use the same pattern as other dispatchers: ~~~~ typescript twoslash -import { type Federation, Create } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -241,7 +248,8 @@ federation Object dispatchers allow you to serve ActivityPub objects at custom URIs: ~~~~ typescript twoslash -import { Note, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setObjectDispatcher( @@ -305,7 +313,8 @@ To prevent this, add validation in your dispatcher to reject identifiers containing unexpected characters: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( @@ -383,7 +392,8 @@ expand the templates according to the pattern you specified. For example, to verify the expansion: ~~~~ typescript twoslash -import { Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher( diff --git a/docs/manual/vocab.md b/docs/manual/vocab.md index c64302ab3..17ad6817d 100644 --- a/docs/manual/vocab.md +++ b/docs/manual/vocab.md @@ -36,20 +36,53 @@ list of the objects, please refer to the [API reference]. > class as `ASObject` as follows: > > ~~~~ typescript twoslash -> import { Object as ASObject } from "@fedify/fedify"; +> import { Object as ASObject } from "@fedify/vocab"; > ~~~~ > > Or, you can import the classes from the Activity Vocabulary with a prefix as > follows: > > ~~~~ typescript -> import * as vocab from "@fedify/fedify/vocab"; +> import * as vocab from "@fedify/vocab"; > ~~~~ -[API reference]: https://jsr.io/@fedify/fedify/doc/vocab/~ +[API reference]: https://jsr.io/@fedify/vocab/doc/~ [`Object`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object +Installation +------------ + +The `@fedify/vocab` package is available on [JSR] and [npm]. You can install +it using the following command: + +[JSR]: https://jsr.io/@fedify/vocab +[npm]: https://www.npmjs.com/package/@fedify/vocab + +::: code-group + +~~~~ bash [Deno] +deno add jsr:@fedify/vocab +~~~~ + +~~~~ bash [npm] +npm add @fedify/vocab +~~~~ + +~~~~ bash [pnpm] +pnpm add @fedify/vocab +~~~~ + +~~~~ bash [Yarn] +yarn add @fedify/vocab +~~~~ + +~~~~ bash [Bun] +bun add @fedify/vocab +~~~~ + +::: + Instantiation ------------- @@ -60,7 +93,7 @@ instantiating a `Create` object: ~~~~ typescript twoslash import { Temporal } from "@js-temporal/polyfill"; // ---cut-before--- -import { Create, Note } from "@fedify/fedify"; +import { Create, Note } from "@fedify/vocab"; const create = new Create({ id: new URL("https://example.com/activities/123"), @@ -164,7 +197,7 @@ For example, the following two objects are equivalent (where dereferencing URI *https://example.com/notes/456* returns the `Note` object): ~~~~ typescript twoslash -import { Create, Note } from "@fedify/fedify"; +import { Create, Note } from "@fedify/vocab"; import { Temporal } from "@js-temporal/polyfill"; // ---cut-before--- const a = new Create({ @@ -222,7 +255,7 @@ For example, the following code hydrates the `object` property of the `Create` object: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; // ---cut-before--- const create = new Create({ object: new URL( @@ -245,7 +278,7 @@ the JSON-LD representation of the `Create` object has the `object` property with the URI of the object: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; // ---cut-before--- const create = new Create({ object: new URL( @@ -272,7 +305,7 @@ However, if the property is once hydrated, the JSON-LD representation of the object has the `object` property with the full object: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const create = new Create({ }); // ---cut-before--- // Hydrates the `object` property: @@ -321,7 +354,7 @@ property of a `Note` object: ~~~~ typescript{8-10} twoslash import { Temporal } from "@js-temporal/polyfill"; // ---cut-before--- -import { Note } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; import { LanguageString } from "@fedify/vocab-runtime"; const noteInEnglish = new Note({ @@ -380,7 +413,7 @@ If you want to instantiate an object from a JSON-LD document, you can use the instantiating a `Create` object from the JSON-LD document: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const create = await Create.fromJsonLd({ "@context": "https://www.w3.org/ns/activitystreams", @@ -401,7 +434,7 @@ since `Create` is a subtype of `Activity`, the `Activity.fromJsonLd()` method can parse a `Create` object as well: ~~~~ typescript twoslash -import { Activity } from "@fedify/fedify"; +import { Activity } from "@fedify/vocab"; const create = await Activity.fromJsonLd({ "@context": "https://www.w3.org/ns/activitystreams", @@ -421,7 +454,7 @@ On the other way around, you can use the `toJsonLd()` method to get the JSON-LD representation of the object: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const create = new Create({}); // ---cut-before--- const jsonLd = await create.toJsonLd(); @@ -437,7 +470,7 @@ In this case, the `toJsonLd()` method returns the compacted JSON-LD document which is processed by the proper JSON-LD processor: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const create = new Create({}); // ---cut-before--- const jsonLd = await create.toJsonLd({ @@ -545,7 +578,7 @@ You can control this behavior using the `crossOrigin` option when calling property accessors: ~~~~ typescript twoslash -import { Create } from "@fedify/fedify"; +import { Create } from "@fedify/vocab"; const create = {} as unknown as Create; // ---cut-before--- // Default behavior: ignore untrusted embedded objects (recommended) @@ -610,15 +643,15 @@ unconditionally if any of the following conditions are met: community ([Discord], [Matrix], [GitHub Discussions], etc.) If you want to contribute to Fedify's vocabulary API, the process is -straightforward. The _\*.yaml_ files located in the *fedify/vocab/* directory -of the Fedify repository serve as the source data for code generation. To add -a new type, you simply need to add a new *.yaml* file, and to add a new +straightforward. The _\*.yaml_ files located in the *packages/vocab/src/* +directory of the Fedify repository serve as the source data for code generation. + To add a new type, you simply need to add a new *.yaml* file, and to add a new property, you need to define the new property in the `properties` section of an existing *.yaml* file. For detailed information on how to contribute to the vocabulary API, please refer to the [*Contributing guide*](../contribute.md) and the existing YAML -files in the *fedify/vocab/* directory for examples. +files in the *packages/vocab/src/* directory for examples. [FEP]: https://w3id.org/fep/ [Discord]: https://discord.gg/bhtwpzURwd diff --git a/docs/manual/webfinger.md b/docs/manual/webfinger.md index 19a358e65..794890467 100644 --- a/docs/manual/webfinger.md +++ b/docs/manual/webfinger.md @@ -248,3 +248,130 @@ if (activityPubActorLink?.href) { > which automatically performs WebFinger lookups when given a handle. > Use `~Context.lookupWebFinger()` when you need the raw WebFinger data or > want more direct control over the lookup process. + + +Using WebFinger client +---------------------- + +The `@fedify/webfinger` package provides a standalone WebFinger client that can +be used independently of the main Fedify framework. This is useful when you +only need WebFinger lookup functionality without the full ActivityPub +federation capabilities. + + +### Installation + +The `@fedify/webfinger` package is available on [JSR] and [npm]. You can +install it using the following command: + +[JSR]: https://jsr.io/@fedify/webfinger +[npm]: https://www.npmjs.com/package/@fedify/webfinger + +::: code-group + +~~~~ bash [Deno] +deno add jsr:@fedify/webfinger +~~~~ + +~~~~ bash [npm] +npm add @fedify/webfinger +~~~~ + +~~~~ bash [pnpm] +pnpm add @fedify/webfinger +~~~~ + +~~~~ bash [Yarn] +yarn add @fedify/webfinger +~~~~ + +~~~~ bash [Bun] +bun add @fedify/webfinger +~~~~ + +::: + + +### Looking up a WebFinger resource + +You can look up a WebFinger resource using the `lookupWebFinger()` function: + +~~~~ typescript twoslash +import { lookupWebFinger } from "@fedify/webfinger"; + +// Look up by acct: URI +const result = await lookupWebFinger("acct:alice@example.com"); + +// Look up by URL +const result2 = await lookupWebFinger("https://example.com/users/alice"); +~~~~ + + +### Working with the result + +The result is a `ResourceDescriptor` object containing the subject, aliases, +properties, and links: + +~~~~ typescript twoslash +import { lookupWebFinger } from "@fedify/webfinger"; + +const result = await lookupWebFinger("acct:alice@example.com"); +if (result != null) { + console.log("Subject:", result.subject); + console.log("Aliases:", result.aliases); + + // Find the ActivityPub actor URL + const actorLink = result.links?.find( + (link) => link.rel === "self" && link.type === "application/activity+json", + ); + if (actorLink?.href != null) { + console.log("Actor URL:", actorLink.href); + } +} +~~~~ + + +### Configuration options + +The `lookupWebFinger()` function accepts various options: + +~~~~ typescript twoslash +import { lookupWebFinger } from "@fedify/webfinger"; + +const result = await lookupWebFinger("acct:alice@example.com", { + // Custom User-Agent header + userAgent: "MyApp/1.0", + + // Maximum redirects to follow (default: 5) + maxRedirection: 3, + + // AbortSignal for cancellation + signal: AbortSignal.timeout(5000), +}); +~~~~ + +The available options are: + +`userAgent` +: The `User-Agent` header value to use when making requests. Can be a string + or an object with options for generating the header. + +`allowPrivateAddress` +: Whether to allow private IP addresses in the URL. Mostly useful for + testing purposes. *Do not use this in production.* Turned off by default. + +`maxRedirection` +: The maximum number of redirections to follow. Defaults to `5`. + +`tracerProvider` +: The OpenTelemetry tracer provider. If omitted, the global tracer provider + is used. + +`signal` +: An `AbortSignal` for cancelling the request. + +> [!TIP] +> Use `@fedify/webfinger` when you need a lightweight WebFinger client without +> the full Fedify framework. If you're already using Fedify, prefer +> `~Context.lookupWebFinger()` instead as it integrates with the federation +> context. \ No newline at end of file diff --git a/docs/package.json b/docs/package.json index 364bc4dd9..7aca93653 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,6 +19,7 @@ "@fedify/sqlite": "workspace:", "@fedify/sveltekit": "workspace:", "@fedify/testing": "workspace:", + "@fedify/vocab": "workspace:", "@fedify/vocab-runtime": "workspace:", "@fedify/relay": "workspace:", "@hono/node-server": "^1.13.7", @@ -62,8 +63,8 @@ "x-forwarded-fetch": "^0.2.0" }, "scripts": { - "dev": "cd ../ && pnpm run --filter '!{docs}' --filter='!./examples/**' -r build && cd docs/ && vitepress dev --host", - "build": "cd ../ && pnpm run --filter '!{docs}' --filter '!./examples/**' -r build && cd docs/ && NODE_OPTIONS='--max-old-space-size=8192' vitepress build", - "preview": "cd ../ && pnpm run --filter '!{docs}' --filter '!./examples/**' -r build && cd docs/ && vitepress preview" + "dev": "cd ../ && pnpm run --filter '@fedify/*' -r build && cd docs/ && vitepress dev --host", + "build": "cd ../ && pnpm run --filter '@fedify/*' -r build && cd docs/ && NODE_OPTIONS='--max-old-space-size=8192' vitepress build", + "preview": "cd ../ && pnpm run --filter '@fedify/*' -r build && cd docs/ && vitepress preview" } } diff --git a/docs/tutorial/basics.md b/docs/tutorial/basics.md index ced599ee8..ae8b094c1 100644 --- a/docs/tutorial/basics.md +++ b/docs/tutorial/basics.md @@ -381,7 +381,8 @@ Let's create an actor dispatcher for our server: ::: code-group ~~~~ typescript{7-16} twoslash [Deno] -import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: new MemoryKvStore(), @@ -406,7 +407,8 @@ Deno.serve( ~~~~ typescript{7-16} twoslash [Bun] import "@types/bun"; // ---cut-before--- -import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = createFederation({ kv: new MemoryKvStore(), @@ -432,7 +434,8 @@ Bun.serve({ ~~~~ ~~~~ typescript{8-17} twoslash [Node.js] -import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import { serve } from "@hono/node-server"; const federation = createFederation({ @@ -728,18 +731,15 @@ represents the `Follow` activity. We will use the `Follow` class to handle incoming follow requests: ~~~~ typescript twoslash [server.ts] -import { - createFederation, - Follow, // [!code highlight] - Person, - MemoryKvStore, -} from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Follow, Person } from "@fedify/vocab"; // [!code highlight] ~~~~ Then, we register an inbox listener for the `Follow` activity: ~~~~ typescript{3-11} twoslash [server.ts] -import { type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -765,7 +765,8 @@ URI in the actor object. Let's modify the actor dispatcher to include the inbox URI: ~~~~ typescript twoslash [server.ts] -import { type Federation, Person } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setActorDispatcher("/users/{identifier}", async (ctx, identifier) => { @@ -823,10 +824,9 @@ import { exportJwk, generateCryptoKeyPair, importJwk, - Follow, - Person, MemoryKvStore, } from "@fedify/fedify"; +import { Follow, Person } from "@fedify/vocab"; ~~~~ By the way, when should we generate a key pair? In general, you should generate @@ -848,8 +848,8 @@ import { generateCryptoKeyPair, importJwk, type Federation, - Person, } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- const kv = await Deno.openKv(); // Open the key–value store @@ -904,8 +904,8 @@ import { generateCryptoKeyPair, importJwk, type Federation, - Person, } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- import { serialize as encodeV8, deserialize as decodeV8 } from "node:v8"; @@ -963,8 +963,8 @@ import { generateCryptoKeyPair, importJwk, type Federation, - Person, } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- import { openKv } from "@deno/kv"; @@ -1087,17 +1087,20 @@ import { exportJwk, generateCryptoKeyPair, importJwk, +} from "@fedify/fedify"; +import { Accept, // [!code highlight] Follow, Person, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ Then, we modify the inbox listener to send an `Accept` activity back to the follower when we receive a follow request: ~~~~ typescript{10-17} twoslash [server.ts] -import { Accept, type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Accept, Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -1138,7 +1141,8 @@ we need to store the followers in the key–value store. We will store each `Follow` activity's ID as the key and the follower's actor ID as the value: ~~~~ typescript{16-17} twoslash [server.ts] -import { Accept, type Federation, Follow } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Accept, Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; const kv = await Deno.openKv(); // ---cut-before--- diff --git a/docs/tutorial/microblog.md b/docs/tutorial/microblog.md index c67840fda..6a2ff07ad 100644 --- a/docs/tutorial/microblog.md +++ b/docs/tutorial/microblog.md @@ -950,8 +950,8 @@ First, let's take a look at the current implementation. Open the *src/federation.ts* file: ~~~~ typescript{12-18} twoslash [src/federation.ts] -import { Person, createFederation } from "@fedify/fedify"; -import { InProcessMessageQueue, MemoryKvStore } from "@fedify/fedify"; +import { createFederation, InProcessMessageQueue, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; const logger = getLogger("microblog"); @@ -1284,7 +1284,8 @@ Now that we've created the `actors` table and filled in a record, let's modify ~~~~ typescript twoslash [src/federation.ts] // @noErrors: 2307 -import { Endpoints, Person, createFederation } from "@fedify/fedify"; +import { createFederation } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; import db from "./db.ts"; import type { Actor, User } from "./schema.ts"; ~~~~ @@ -1293,7 +1294,8 @@ Now that we've `import`ed what we need, let's modify the `~Federatable.setActorDispatcher()` method: ~~~~ typescript{2-11,16-21} twoslash [src/federation.ts] -import { Endpoints, Person, type Federation } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; import Database from "better-sqlite3"; const db = new Database(""); interface User {} @@ -1488,13 +1490,12 @@ the `Key` type we defined earlier: ~~~~ typescript{5-7,9} twoslash [src/federation.ts] // @noErrors: 2307 import { - Endpoints, - Person, createFederation, exportJwk, generateCryptoKeyPair, importJwk, } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; import type { Actor, Key, User } from "./schema.ts"; ~~~~ @@ -1502,13 +1503,12 @@ Now let's modify the actor dispatcher part as follows: ~~~~ typescript twoslash [src/federation.ts] import { - Endpoints, type Federation, - Person, exportJwk, generateCryptoKeyPair, importJwk, } from "@fedify/fedify"; +import { Endpoints, Person } from "@fedify/vocab"; const federation = null as unknown as Federation; import { type Logger } from "@logtape/logtape"; const logger = null as unknown as Logger; @@ -1633,7 +1633,7 @@ Each element of the array is an object representing the key pair in various formats, which looks like this: ~~~~ typescript twoslash -import type { CryptographicKey, Multikey } from "@fedify/fedify"; +import type { CryptographicKey, Multikey } from "@fedify/vocab"; // ---cut-before--- interface ActorKeyPair { privateKey: CryptoKey; // Private key @@ -1868,16 +1868,18 @@ and the `getActorHandle()` function provided by Fedify: ~~~~ typescript{2,4,9} twoslash [src/federation.ts] import { - Accept, - Endpoints, - Follow, - Person, createFederation, exportJwk, generateCryptoKeyPair, - getActorHandle, importJwk, } from "@fedify/fedify"; +import { + Accept, + Endpoints, + Follow, + Person, + getActorHandle, +} from "@fedify/vocab"; ~~~~ Now let's modify the code calling the `~Federatable.setInboxListeners()` method @@ -1885,16 +1887,18 @@ as follows: ~~~~ typescript twoslash [src/federation.ts] import { - Accept, - Endpoints, type Federation, - Follow, - Person, exportJwk, generateCryptoKeyPair, - getActorHandle, importJwk, } from "@fedify/fedify"; +import { + Accept, + Endpoints, + Follow, + Person, + getActorHandle, +} from "@fedify/vocab"; const federation = null as unknown as Federation; import type { Logger } from "@logtape/logtape"; const logger = null as unknown as Logger; @@ -2117,25 +2121,28 @@ To implement unfollow, open the *src/federation.ts* file and `import` the `Undo` class provided by Fedify: ~~~~ typescript twoslash [src/federation.ts] +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Endpoints, Follow, Person, Undo, // [!code highlight] - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ Then add `on(Undo, ...)` in succession after `on(Follow, ...)`: ~~~~ typescript{6-23} twoslash [src/federation.ts] // @errors: 1160 -import { type Federation, Follow, Undo } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow, Undo } from "@fedify/vocab"; const federation = null as unknown as Federation; import Database from "better-sqlite3"; const db = new Database(""); @@ -2459,25 +2466,28 @@ Open the *src/federation.ts* file and `import` the `Recipient` type provided by Fedify: ~~~~ typescript twoslash [src/federation.ts] +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Endpoints, Follow, Person, Undo, - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, type Recipient, // [!code highlight] -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ Then add a followers collection dispatcher at the bottom: ~~~~ typescript twoslash [src/federation.ts] -import { type Federation, type Recipient } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import type { Recipient } from "@fedify/vocab"; const federation = null as unknown as Federation; import Database from "better-sqlite3"; const db = new Database(""); @@ -2579,7 +2589,8 @@ servers know where the followers collection is. So we need to link to the followers collection in the actor dispatcher: ~~~~ typescript twoslash [src/federation.ts] -import { type Federation, Person } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation @@ -2801,6 +2812,12 @@ First, open the *src/federation.ts* file and `import` the `Note` class provided by Fedify: ~~~~ typescript twoslash [src/federation.ts] +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Endpoints, @@ -2808,19 +2825,16 @@ import { Note, // [!code highlight] Person, Undo, - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, type Recipient, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ Add the following code: ~~~~ typescript twoslash [src/federation.ts] -import { type Federation, Note } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setObjectDispatcher( @@ -2855,14 +2869,15 @@ Also `import` the `Post` type and the `Note` class provided by Fedify: ~~~~ typescript twoslash [src/app.tsx] // @noErrors: 2307 import type { Actor, Post, User } from "./schema.ts"; -import { Note } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; ~~~~ And implement the `POST /users/{username}/posts` request handler: ~~~~ typescript twoslash [src/app.tsx] import { stringifyEntities } from "stringify-entities"; -import { type Federation, Note } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const fedi = null as unknown as Federation; import { Hono } from "hono"; const app = new Hono(); @@ -3133,6 +3148,12 @@ Fedify: ~~~~ typescript twoslash [src/federation.ts] // @noErrors: 2307 +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Endpoints, @@ -3141,13 +3162,9 @@ import { PUBLIC_COLLECTION, // [!code highlight] Person, Undo, - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, type Recipient, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import type { Actor, Key, @@ -3161,7 +3178,8 @@ ActivityPub. We've already created an empty implementation of the object dispatcher for the `Note` class: ~~~~ typescript twoslash [src/federation.ts] -import { type Federation, Note } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note } from "@fedify/vocab"; const federation = null as unknown as Federation; // ---cut-before--- federation.setObjectDispatcher( @@ -3177,7 +3195,8 @@ Let's modify this as follows: ~~~~ typescript twoslash [src/federation.ts] import { Temporal } from "@js-temporal/polyfill"; -import { type Federation, Note, PUBLIC_COLLECTION } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Note, PUBLIC_COLLECTION } from "@fedify/vocab"; const federation = null as unknown as Federation; import Database from "better-sqlite3"; const db = new Database(""); @@ -3248,14 +3267,15 @@ Let's modify the code to send a `Create(Note)` activity when creating a post. Open the *src/app.tsx* file and `import` the `Create` class provided by Fedify: ~~~~ typescript twoslash [src/app.tsx] -import { Create, Note } from "@fedify/fedify"; +import { Create, Note } from "@fedify/vocab"; ~~~~ Then modify the `POST /users/{username}/posts` request handler as follows: ~~~~ typescript{4,24,26-40} twoslash [src/app.tsx] import { stringifyEntities } from "stringify-entities"; -import { Create, type Federation, Note } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Create, Note } from "@fedify/vocab"; const fedi = null as unknown as Federation; import { Hono } from "hono"; const app = new Hono(); @@ -3507,13 +3527,14 @@ import { Follow, // [!code highlight] isActor, // [!code highlight] Note, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ Then add a `POST /users/{username}/following` request handler: ~~~~ typescript twoslash [src/app.tsx] -import { type Federation, Follow, isActor } from "@fedify/fedify"; +import { type Federation } from "@fedify/fedify"; +import { Follow, isActor } from "@fedify/vocab"; const fedi = null as unknown as Federation; import { Hono } from "hono"; const app = new Hono(); @@ -3598,6 +3619,12 @@ Open the *src/federation.ts* file and `import` the `isActor()` function and `Actor` type provided by Fedify: ~~~~ typescript twoslash [src/federation.ts] +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Endpoints, @@ -3606,15 +3633,11 @@ import { PUBLIC_COLLECTION, Person, Undo, - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, isActor, // [!code highlight] type Actor as APActor, // [!code highlight] type Recipient, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ We've given the alias `APActor` to the `Actor` type because @@ -3625,7 +3648,7 @@ the `actors` table when first encountered to make it reusable. Add the following function: ~~~~ typescript twoslash [src/federation.ts] -import { getActorHandle, isActor, type Actor as APActor } from "@fedify/fedify"; +import { getActorHandle, isActor, type Actor as APActor } from "@fedify/vocab"; import type { Logger } from "@logtape/logtape"; const logger = {} as unknown as Logger; import Database from "better-sqlite3"; @@ -3675,12 +3698,8 @@ Change the code doing the same role in the `on(Follow, ...)` part of the inbox to use the `persistActor()` function: ~~~~ typescript twoslash [src/federation.ts] -import { - type Actor as APActor, - type Federation, - Follow, - type ParseUriResult, -} from "@fedify/fedify"; +import { type Federation, type ParseUriResult } from "@fedify/fedify"; +import { type Actor as APActor, Follow } from "@fedify/vocab"; const federation = null as unknown as Federation; import type { Logger } from "@logtape/logtape"; const logger = {} as unknown as Logger; @@ -3716,13 +3735,13 @@ Now that we've finished refactoring, let's implement the behavior when receiving an `Accept(Follow)` activity in the inbox: ~~~~ typescript twoslash [src/federation.ts] +import { type Federation } from "@fedify/fedify"; import { Accept, type Actor as APActor, - type Federation, Follow, isActor, -} from "@fedify/fedify"; +} from "@fedify/vocab"; const federation = null as unknown as Federation; import Database from "better-sqlite3"; const db = new Database(""); @@ -4116,6 +4135,12 @@ Open the *src/federation.ts* file and `import` the `Create` class provided by Fedify: ~~~~ typescript twoslash [src/federation.ts] +import { + createFederation, + exportJwk, + generateCryptoKeyPair, + importJwk, +} from "@fedify/fedify"; import { Accept, Create, // [!code highlight] @@ -4125,27 +4150,23 @@ import { PUBLIC_COLLECTION, Person, Undo, - createFederation, - exportJwk, - generateCryptoKeyPair, getActorHandle, - importJwk, isActor, type Actor as APActor, type Recipient, -} from "@fedify/fedify"; +} from "@fedify/vocab"; ~~~~ And add `on(Create, ...)` to the inbox code: ~~~~ typescript twoslash [src/federation.ts] +import { type Federation } from "@fedify/fedify"; import { type Actor as APActor, - type Federation, Create, Note, isActor, -} from "@fedify/fedify"; +} from "@fedify/vocab"; const federation = null as unknown as Federation; import Database from "better-sqlite3"; const db = new Database(""); diff --git a/examples/actor-lookup-cli/main.ts b/examples/actor-lookup-cli/main.ts index f9c9f0e17..ab5686af4 100644 --- a/examples/actor-lookup-cli/main.ts +++ b/examples/actor-lookup-cli/main.ts @@ -5,7 +5,7 @@ import { isActor, lookupObject, PropertyValue, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; import { convert } from "npm:html-to-text@^9.0.5"; export interface Actor { diff --git a/examples/cloudflare-workers/package.json b/examples/cloudflare-workers/package.json index 63da22f34..3e0297c12 100644 --- a/examples/cloudflare-workers/package.json +++ b/examples/cloudflare-workers/package.json @@ -14,6 +14,7 @@ "wrangler": "^4.18.0" }, "dependencies": { - "@fedify/fedify": "workspace:" + "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:" } } diff --git a/examples/cloudflare-workers/src/index.ts b/examples/cloudflare-workers/src/index.ts index a27abfed4..1660a77c7 100644 --- a/examples/cloudflare-workers/src/index.ts +++ b/examples/cloudflare-workers/src/index.ts @@ -17,7 +17,7 @@ import { Object, Person, Undo, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; interface ContextData { kv: KVNamespace; diff --git a/examples/elysia/app.ts b/examples/elysia/app.ts index bab3c3d5b..7b36589cf 100644 --- a/examples/elysia/app.ts +++ b/examples/elysia/app.ts @@ -1,5 +1,6 @@ import { fedify } from "@fedify/elysia"; -import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import { Elysia, redirect } from "elysia"; const federation = createFederation({ diff --git a/examples/elysia/package.json b/examples/elysia/package.json index 4919d14d3..99f747c85 100644 --- a/examples/elysia/package.json +++ b/examples/elysia/package.json @@ -32,6 +32,7 @@ "dependencies": { "@fedify/elysia": "workspace:*", "@fedify/fedify": "workspace:*", + "@fedify/vocab": "workspace:", "elysia": "catalog:" } } diff --git a/examples/express/app.ts b/examples/express/app.ts index f8e668b35..23c84d82f 100644 --- a/examples/express/app.ts +++ b/examples/express/app.ts @@ -1,16 +1,12 @@ -import express from "express"; import { integrateFederation } from "@fedify/express"; import { - Accept, createFederation, - Endpoints, - Follow, generateCryptoKeyPair, MemoryKvStore, - Person, - Undo, } from "@fedify/fedify"; +import { Accept, Endpoints, Follow, Person, Undo } from "@fedify/vocab"; import { configure, getConsoleSink } from "@logtape/logtape"; +import express from "express"; import process from "node:process"; const keyPairsStore = new Map>(); diff --git a/examples/express/federation.ts b/examples/express/federation.ts index 8a581fa34..adecd0360 100644 --- a/examples/express/federation.ts +++ b/examples/express/federation.ts @@ -1,4 +1,5 @@ -import { createFederation, MemoryKvStore, Note, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Note, Person } from "@fedify/vocab"; export const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/express/package.json b/examples/express/package.json index 7b22f85ab..12a6751a6 100644 --- a/examples/express/package.json +++ b/examples/express/package.json @@ -32,6 +32,7 @@ "dependencies": { "@fedify/express": "workspace:", "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:", "@logtape/logtape": "catalog:", "express": "catalog:" } diff --git a/examples/fastify/index.ts b/examples/fastify/index.ts index 110797ff3..fdea0772b 100644 --- a/examples/fastify/index.ts +++ b/examples/fastify/index.ts @@ -1,4 +1,5 @@ -import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import Fastify from "fastify"; import fedifyPlugin from "../../packages/fastify/src/index.ts"; diff --git a/examples/fastify/package.json b/examples/fastify/package.json index 256751bd3..a52d0d6a2 100644 --- a/examples/fastify/package.json +++ b/examples/fastify/package.json @@ -10,6 +10,7 @@ "dependencies": { "@fedify/fastify": "workspace:", "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:", "fastify": "catalog:" }, "devDependencies": { diff --git a/examples/h3/federation.ts b/examples/h3/federation.ts index 8a581fa34..adecd0360 100644 --- a/examples/h3/federation.ts +++ b/examples/h3/federation.ts @@ -1,4 +1,5 @@ -import { createFederation, MemoryKvStore, Note, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Note, Person } from "@fedify/vocab"; export const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/hono-sample/deno.json b/examples/hono-sample/deno.json index d2ce7a546..2481e438f 100644 --- a/examples/hono-sample/deno.json +++ b/examples/hono-sample/deno.json @@ -3,7 +3,7 @@ "hono": "jsr:@hono/hono@^4.7.1" }, "tasks": { - "codegen": "deno task -f @fedify/fedify codegen", + "codegen": "deno task -f @fedify/vocab compile", "check": { "command": "deno fmt --check && deno lint && deno check **/*.ts", "dependencies": [ diff --git a/examples/hono-sample/main.ts b/examples/hono-sample/main.ts index 70c66a215..629f19fd9 100644 --- a/examples/hono-sample/main.ts +++ b/examples/hono-sample/main.ts @@ -1,6 +1,6 @@ import { createFederation, MemoryKvStore } from "@fedify/fedify/federation"; -import { Person } from "@fedify/fedify/vocab"; import { federation } from "@fedify/hono"; +import { Person } from "@fedify/vocab"; import { Hono } from "hono"; const fedi = createFederation({ diff --git a/examples/koa/federation.ts b/examples/koa/federation.ts index 8a581fa34..adecd0360 100644 --- a/examples/koa/federation.ts +++ b/examples/koa/federation.ts @@ -1,4 +1,5 @@ -import { createFederation, MemoryKvStore, Note, Person } from "@fedify/fedify"; +import { createFederation, MemoryKvStore } from "@fedify/fedify"; +import { Note, Person } from "@fedify/vocab"; export const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/koa/package.json b/examples/koa/package.json index bef1111c3..35729ee82 100644 --- a/examples/koa/package.json +++ b/examples/koa/package.json @@ -32,6 +32,7 @@ "dependencies": { "@fedify/koa": "workspace:", "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:", "@logtape/logtape": "catalog:", "koa": "catalog:" } diff --git a/examples/next-integration/federation/index.ts b/examples/next-integration/federation/index.ts index 71f4395c8..c9aefa1c5 100644 --- a/examples/next-integration/federation/index.ts +++ b/examples/next-integration/federation/index.ts @@ -1,15 +1,11 @@ +import { keyPairsStore, relationStore } from "@/data/store"; import { - Accept, createFederation, - Endpoints, - Follow, generateCryptoKeyPair, MemoryKvStore, - Person, - Undo, } from "@fedify/fedify"; +import { Accept, Endpoints, Follow, Person, Undo } from "@fedify/vocab"; import { revalidatePath } from "next/cache"; -import { keyPairsStore, relationStore } from "@/data/store"; const federation = createFederation({ kv: new MemoryKvStore(), diff --git a/examples/next-integration/package.json b/examples/next-integration/package.json index 3ca913409..21e22fd76 100644 --- a/examples/next-integration/package.json +++ b/examples/next-integration/package.json @@ -11,6 +11,7 @@ "dependencies": { "@fedify/fedify": "workspace:", "@fedify/next": "workspace:", + "@fedify/vocab": "workspace:", "next": "15.5.0", "react": "19.1.0", "react-dom": "19.1.0", diff --git a/examples/next14-app-router/app/[fedify]/[[...catchAll]]/route.ts b/examples/next14-app-router/app/[fedify]/[[...catchAll]]/route.ts index 146b46679..34122c227 100644 --- a/examples/next14-app-router/app/[fedify]/[[...catchAll]]/route.ts +++ b/examples/next14-app-router/app/[fedify]/[[...catchAll]]/route.ts @@ -1,13 +1,9 @@ import { - Accept, createFederation, - Endpoints, - Follow, generateCryptoKeyPair, MemoryKvStore, - Person, - Undo, } from "@fedify/fedify"; +import { Accept, Endpoints, Follow, Person, Undo } from "@fedify/vocab"; import { keyPairsStore, relationStore } from "~/data/store"; import { integrateFederation } from "~/shared/integrate-fedify"; diff --git a/examples/next14-app-router/package.json b/examples/next14-app-router/package.json index 6e5527afb..d0ea3a385 100644 --- a/examples/next14-app-router/package.json +++ b/examples/next14-app-router/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:", "@logtape/logtape": "catalog:", "next": "^14.0.0", "react": "19.0.0-rc-7771d3a7-20240827", diff --git a/examples/next15-app-router/package.json b/examples/next15-app-router/package.json index 76194086c..7e21dd352 100644 --- a/examples/next15-app-router/package.json +++ b/examples/next15-app-router/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@fedify/fedify": "workspace:", + "@fedify/vocab": "workspace:", "next": "15.3.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/next15-app-router/shared/integrate-fedify.ts b/examples/next15-app-router/shared/integrate-fedify.ts index 634e33b77..59038f38e 100644 --- a/examples/next15-app-router/shared/integrate-fedify.ts +++ b/examples/next15-app-router/shared/integrate-fedify.ts @@ -1,16 +1,12 @@ -import { getXForwardedRequest } from "x-forwarded-fetch"; import { - Accept, createFederation, - Endpoints, - Follow, generateCryptoKeyPair, MemoryKvStore, - Person, - Undo, } from "@fedify/fedify"; -import { keyPairsStore, relationStore } from "~/data/store"; +import { Accept, Endpoints, Follow, Person, Undo } from "@fedify/vocab"; import { revalidatePath } from "next/cache"; +import { getXForwardedRequest } from "x-forwarded-fetch"; +import { keyPairsStore, relationStore } from "~/data/store"; export const fedifyRequestHandler = integrateFederation(() => {}); diff --git a/examples/sveltekit-sample/package.json b/examples/sveltekit-sample/package.json index 0f59ff6a9..fbe56d236 100644 --- a/examples/sveltekit-sample/package.json +++ b/examples/sveltekit-sample/package.json @@ -22,6 +22,7 @@ "dependencies": { "@fedify/fedify": "workspace:", "@fedify/sveltekit": "workspace:", + "@fedify/vocab": "workspace:", "x-forwarded-fetch": "^0.2.0" }, "devDependencies": { diff --git a/examples/sveltekit-sample/src/lib/federation.ts b/examples/sveltekit-sample/src/lib/federation.ts index 5886be8bd..81e3c6899 100644 --- a/examples/sveltekit-sample/src/lib/federation.ts +++ b/examples/sveltekit-sample/src/lib/federation.ts @@ -1,17 +1,19 @@ import { - Accept, createFederation, + generateCryptoKeyPair, + MemoryKvStore, + PUBLIC_COLLECTION, +} from "@fedify/fedify"; +import { + Accept, Endpoints, Follow, - generateCryptoKeyPair, Image, - MemoryKvStore, Note, Person, - PUBLIC_COLLECTION, type Recipient, Undo, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import { keyPairsStore, postStore, relationStore } from "./store"; const federation = createFederation({ diff --git a/mise.toml b/mise.toml index a0ba38390..f5a5c4d67 100644 --- a/mise.toml +++ b/mise.toml @@ -16,7 +16,8 @@ run = "deno task codegen" [tasks.prepare] description = "Prepare the development environment (codegen, install, build fixtures)" env = { CI = "true" } # Prevent pnpm from prompting for confirmation -run = "deno task install && deno task pnpm:build-fixture" +depends = ["install"] +run = "pnpm --filter '@fedify/*' --recursive --parallel build" # Code quality [tasks.check] diff --git a/packages/cli/deno.json b/packages/cli/deno.json index 06c50b9cf..ed028dad5 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -33,9 +33,9 @@ "exclude": ["**/*.test.ts"] }, "tasks": { - "codegen": "deno task -f @fedify/fedify codegen", + "codegen": "deno task -f @fedify/vocab compile", "check": { - "command": "deno task codegen && deno fmt --check && deno lint && deno check src/**/*.ts", + "command": "deno fmt --check && deno lint && deno check src/**/*.ts", "dependencies": [ "codegen" ] diff --git a/packages/cli/package.json b/packages/cli/package.json index c9c77d6da..4d439d53e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -47,6 +47,7 @@ "@fedify/fedify": "workspace:*", "@fedify/relay": "workspace:*", "@fedify/sqlite": "workspace:*", + "@fedify/vocab": "workspace:*", "@fedify/vocab-runtime": "workspace:*", "@fedify/vocab-tools": "workspace:*", "@fxts/core": "catalog:", @@ -90,10 +91,10 @@ "prepublish": "pnpm run build", "test": "pnpm build && node --test --experimental-transform-types 'src/**/*.test.ts' '!src/init/test/**'", "test-init": "deno task test-init", - "test:bun": "pnpm build && bun test", - "run": "pnpm build && node dist/mod.js", + "test:bun": "tsdown && bun test", + "run": "tsdown && node dist/mod.js", "runi": "tsdown && node dist/mod.js", - "run:bun": "pnpm build && bun dist/mod.js", + "run:bun": "tsdown && bun dist/mod.js", "runi:bun": "tsdown && bun dist/mod.js" } } diff --git a/packages/cli/src/inbox.tsx b/packages/cli/src/inbox.tsx index c34d3039d..261c65d5c 100644 --- a/packages/cli/src/inbox.tsx +++ b/packages/cli/src/inbox.tsx @@ -1,23 +1,25 @@ /** @jsx react-jsx */ /** @jsxImportSource hono/jsx */ +import { + type Context, + createFederation, + generateCryptoKeyPair, + MemoryKvStore, +} from "@fedify/fedify"; import { Accept, Activity, type Actor, Application, - type Context, - createFederation, Delete, Endpoints, Follow, - generateCryptoKeyPair, Image, isActor, lookupObject, - MemoryKvStore, PUBLIC_COLLECTION, type Recipient, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { command, diff --git a/packages/cli/src/inbox/entry.ts b/packages/cli/src/inbox/entry.ts index 466891926..ea6ea6e34 100644 --- a/packages/cli/src/inbox/entry.ts +++ b/packages/cli/src/inbox/entry.ts @@ -1,4 +1,4 @@ -import type { Activity } from "@fedify/fedify"; +import type { Activity } from "@fedify/vocab"; import type { LogRecord } from "@logtape/logtape"; export interface ActivityEntry { diff --git a/packages/cli/src/inbox/rendercode.ts b/packages/cli/src/inbox/rendercode.ts index 09146529c..52e01ec53 100644 --- a/packages/cli/src/inbox/rendercode.ts +++ b/packages/cli/src/inbox/rendercode.ts @@ -1,4 +1,4 @@ -import type { Activity } from "@fedify/fedify"; +import type { Activity } from "@fedify/vocab"; import { getStatusText } from "@poppanator/http-constants"; import { getContextLoader } from "../docloader.ts"; diff --git a/packages/cli/src/lookup.test.ts b/packages/cli/src/lookup.test.ts index 943964d15..b04e37dba 100644 --- a/packages/cli/src/lookup.test.ts +++ b/packages/cli/src/lookup.test.ts @@ -1,7 +1,7 @@ -import { Activity, Note } from "@fedify/fedify"; +import { Activity, Note } from "@fedify/vocab"; import assert from "node:assert/strict"; -import test from "node:test"; import { mkdir, readFile, rm } from "node:fs/promises"; +import test from "node:test"; import { getContextLoader } from "./docloader.ts"; import { clearTimeoutSignal, diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 76e12a5d1..e93b53602 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -1,17 +1,19 @@ +import { + generateCryptoKeyPair, + getAuthenticatedDocumentLoader, + respondWithObject, +} from "@fedify/fedify"; import { Application, Collection, CryptographicKey, - generateCryptoKeyPair, - getAuthenticatedDocumentLoader, type Link, lookupObject, Object as APObject, - type ResourceDescriptor, - respondWithObject, traverseCollection, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import type { DocumentLoader } from "@fedify/vocab-runtime"; +import type { ResourceDescriptor } from "@fedify/webfinger"; import { getLogger } from "@logtape/logtape"; import { argument, diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index b975e22e0..355eddd6c 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -1,3 +1,4 @@ +import { type Actor, getActorHandle } from "@fedify/vocab"; import { isObject } from "@fxts/core"; import { message } from "@optique/core"; import { print, printError } from "@optique/run"; @@ -8,7 +9,6 @@ import { spawn } from "node:child_process"; import { writeFile } from "node:fs/promises"; import process from "node:process"; import util from "node:util"; -import { type Actor, getActorHandle } from "@fedify/fedify"; export const colorEnabled: boolean = process.stdout.isTTY && !("NO_COLOR" in process.env && process.env.NO_COLOR !== ""); diff --git a/packages/cli/src/webfinger/action.ts b/packages/cli/src/webfinger/action.ts index 5a425a48c..8a4d98aa0 100644 --- a/packages/cli/src/webfinger/action.ts +++ b/packages/cli/src/webfinger/action.ts @@ -1,8 +1,8 @@ -import type { ResourceDescriptor } from "@fedify/fedify"; +import type { ResourceDescriptor } from "@fedify/webfinger"; import { lookupWebFinger, type LookupWebFingerOptions, -} from "@fedify/fedify/webfinger"; +} from "@fedify/webfinger"; import { formatMessage, message } from "@optique/core/message"; import { print } from "@optique/run"; import ora from "ora"; diff --git a/packages/cli/src/webfinger/lib.ts b/packages/cli/src/webfinger/lib.ts index 30f22e3a6..e11bd53f8 100644 --- a/packages/cli/src/webfinger/lib.ts +++ b/packages/cli/src/webfinger/lib.ts @@ -1,4 +1,4 @@ -import { toAcctUrl } from "@fedify/fedify"; +import { toAcctUrl } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { InvalidHandleError } from "./error.ts"; diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts index c351793b1..461378f04 100644 --- a/packages/cli/tsdown.config.ts +++ b/packages/cli/tsdown.config.ts @@ -11,6 +11,7 @@ export default defineConfig({ ], platform: "node", unbundle: true, + external: [/^node:/], inputOptions: { onwarn(warning, defaultHandler) { if ( diff --git a/packages/fastify/package.json b/packages/fastify/package.json index 00640a074..d50cfc17f 100644 --- a/packages/fastify/package.json +++ b/packages/fastify/package.json @@ -59,6 +59,6 @@ "build": "tsdown", "prepack": "tsdown", "prepublish": "tsdown", - "test": "tsdown && node --experimental-transform-types --test" + "test": "node --experimental-transform-types --test" } } diff --git a/packages/fastify/src/index.test.ts b/packages/fastify/src/index.test.ts index 784a24748..3c58cc24e 100644 --- a/packages/fastify/src/index.test.ts +++ b/packages/fastify/src/index.test.ts @@ -2,9 +2,9 @@ import { fedifyPlugin } from "@fedify/fastify"; import { createFederation, MemoryKvStore, - Person, type RequestContext, } from "@fedify/fedify"; +import { Person } from "@fedify/vocab"; import Fastify from "fastify"; import { strict as assert } from "node:assert"; import { test } from "node:test"; diff --git a/packages/fastify/src/index.ts b/packages/fastify/src/index.ts index 40569211f..0d922a0cc 100644 --- a/packages/fastify/src/index.ts +++ b/packages/fastify/src/index.ts @@ -39,7 +39,8 @@ export interface FedifyPluginOptions * * @example * ```typescript - * import { createFederation, MemoryKvStore, Person } from "@fedify/fedify"; + * import { createFederation, MemoryKvStore } from "@fedify/fedify"; + * import { Person } from "@fedify/vocab"; * import fedifyPlugin from "@fedify/fastify"; * import Fastify from "fastify"; * diff --git a/packages/fedify/README.md b/packages/fedify/README.md index 8fbc169bd..529d1d521 100644 --- a/packages/fedify/README.md +++ b/packages/fedify/README.md @@ -113,8 +113,10 @@ Here is the list of packages: | [@fedify/sqlite](/packages/sqlite/) | [JSR][jsr:@fedify/sqlite] | [npm][npm:@fedify/sqlite] | SQLite driver | | [@fedify/sveltekit](/packages/sveltekit/) | [JSR][jsr:@fedify/sveltekit] | [npm][npm:@fedify/sveltekit] | SvelteKit integration | | [@fedify/testing](/packages/testing/) | [JSR][jsr:@fedify/testing] | [npm][npm:@fedify/testing] | Testing utilities | +| [@fedify/vocab](/packages/vocab/) | [JSR][jsr:@fedify/vocab] | [npm][npm:@fedify/vocab] | Activity Vocabulary library | | [@fedify/vocab-runtime](/packages/vocab-runtime/) | [JSR][jsr:@fedify/vocab-runtime] | [npm][npm:@fedify/vocab-runtime] | Runtime library for code-generated vocab | | [@fedify/vocab-tools](/packages/vocab-tools/) | [JSR][jsr:@fedify/vocab-tools] | [npm][npm:@fedify/vocab-tools] | Code generation tools for Activity Vocab | +| [@fedify/webfinger](/packages/webfinger/) | [JSR][jsr:@fedify/webfinger] | [npm][npm:@fedify/webfinger] | WebFinger client library for ActivityPub | [jsr:@fedify/cli]: https://jsr.io/@fedify/cli [npm:@fedify/cli]: https://www.npmjs.com/package/@fedify/cli diff --git a/packages/fedify/deno.json b/packages/fedify/deno.json index 91795532e..49cc8c9fa 100644 --- a/packages/fedify/deno.json +++ b/packages/fedify/deno.json @@ -9,9 +9,7 @@ "./nodeinfo": "./src/nodeinfo/mod.ts", "./otel": "./src/otel/mod.ts", "./sig": "./src/sig/mod.ts", - "./vocab": "./src/vocab/mod.ts", - "./utils": "./src/utils/mod.ts", - "./webfinger": "./src/webfinger/mod.ts" + "./utils": "./src/utils/mod.ts" }, "imports": { "@multiformats/base-x": "npm:@multiformats/base-x@^4.0.1", @@ -31,9 +29,6 @@ "uri-template-router": "npm:uri-template-router@^1.0.0", "url-template": "npm:url-template@^3.1.1" }, - "include": [ - "src/vocab/vocab.ts" - ], "exclude": [ ".test-report.xml", "apidoc/", @@ -47,15 +42,16 @@ "src/cfworkers/README.md", "src/cfworkers/server.ts", "src/cfworkers/server.js", - "src/cfworkers/server.js.map", - "src/vocab/*.yaml", - "!src/vocab/vocab.ts" + "src/cfworkers/server.js.map" ], "publish": { - "exclude": ["**/*.test.ts", "src/testing/"] + "exclude": [ + "**/*.test.ts", + "src/testing/" + ] }, "tasks": { - "codegen": "deno run --allow-read --allow-write --allow-env --check scripts/codegen.ts && deno fmt src/vocab/vocab.ts && deno cache src/vocab/vocab.ts && deno check src/vocab/vocab.ts", + "codegen": "deno task -f @fedify/vocab compile", "cache": { "command": "deno cache src/mod.ts", "dependencies": [ @@ -97,22 +93,7 @@ "pnpm:build": { "command": "pnpm exec tsdown", "dependencies": [ - "codegen", - "pnpm:install", - "pnpm:build-vocab", - "pnpm:build-fixture" - ] - }, - "pnpm:build-vocab-runtime": { - "command": "cd ../vocab-runtime && pnpm build" - }, - "pnpm:build-vocab-tools": { - "command": "cd ../vocab-tools && pnpm build" - }, - "pnpm:build-vocab": { - "dependencies": [ - "pnpm:build-vocab-runtime", - "pnpm:build-vocab-tools" + "pnpm:build-vocab" ] }, "test:node": { diff --git a/packages/fedify/package.json b/packages/fedify/package.json index 83f59d057..1ef26a847 100644 --- a/packages/fedify/package.json +++ b/packages/fedify/package.json @@ -107,48 +107,27 @@ "import": "./dist/utils/mod.js", "require": "./dist/utils/mod.cjs", "default": "./dist/utils/mod.js" - }, - "./vocab": { - "types": { - "import": "./dist/vocab/mod.d.ts", - "require": "./dist/vocab/mod.d.cts", - "default": "./dist/vocab/mod.d.ts" - }, - "import": "./dist/vocab/mod.js", - "require": "./dist/vocab/mod.cjs", - "default": "./dist/vocab/mod.js" - }, - "./webfinger": { - "types": { - "import": "./dist/webfinger/mod.d.ts", - "require": "./dist/webfinger/mod.d.cts", - "default": "./dist/webfinger/mod.d.ts" - }, - "import": "./dist/webfinger/mod.js", - "require": "./dist/webfinger/mod.cjs", - "default": "./dist/webfinger/mod.js" } }, "dependencies": { + "@fedify/vocab": "workspace:*", "@fedify/vocab-runtime": "workspace:*", + "@fedify/webfinger": "workspace:*", "@js-temporal/polyfill": "^0.5.1", "@logtape/logtape": "catalog:", - "@multiformats/base-x": "^4.0.1", "@opentelemetry/api": "catalog:", "@opentelemetry/core": "catalog:", "@opentelemetry/sdk-trace-base": "catalog:", "@opentelemetry/semantic-conventions": "^1.27.0", - "asn1js": "^3.0.7", "byte-encodings": "catalog:", "es-toolkit": "catalog:", "json-canon": "^1.0.1", "jsonld": "^9.0.0", "multicodec": "^3.2.1", - "pkijs": "^3.3.3", "structured-field-values": "^2.0.4", "uri-template-router": "^1.0.0", "url-template": "^3.1.1", - "urlpattern-polyfill": "^10.1.0" + "urlpattern-polyfill": "catalog:" }, "devDependencies": { "@fedify/fixture": "workspace:*", @@ -156,7 +135,6 @@ "@std/assert": "jsr:^0.226.0", "@std/path": "catalog:", "@types/node": "^24.2.1", - "fast-check": "^3.22.0", "fetch-mock": "catalog:", "miniflare": "^4.20250523.0", "tsdown": "catalog:", @@ -165,11 +143,11 @@ "wrangler": "^4.17.0" }, "scripts": { - "build": "deno task codegen && pnpm run --filter vocab-runtime build && pnpm run --filter vocab-tools build && pnpm run --filter fixture build && tsdown", - "prepack": "pnpm run build", - "prepublish": "pnpm run build", - "test": "deno task codegen && tsdown && cd dist/ && node --test", - "test:bun": "deno task pnpm:build && cd dist/ && bun test --timeout 60000", + "build": "tsdown", + "prepack": "tsdown", + "prepublish": "tsdown", + "test": "tsdown && cd dist/ && node --test", + "test:bun": "tsdown && cd dist/ && bun test --timeout 60000", "test:cfworkers": "deno task codegen && wrangler deploy --dry-run --outdir src/cfworkers && node --import=tsx src/cfworkers/client.ts" } } diff --git a/packages/fedify/src/compat/transformers.test.ts b/packages/fedify/src/compat/transformers.test.ts index 50ea41782..06363376f 100644 --- a/packages/fedify/src/compat/transformers.test.ts +++ b/packages/fedify/src/compat/transformers.test.ts @@ -1,10 +1,10 @@ import { test } from "@fedify/fixture"; +import { Follow, Person } from "@fedify/vocab"; import { assert } from "@std/assert/assert"; import { assertEquals } from "@std/assert/assert-equals"; import { assertInstanceOf } from "@std/assert/assert-instance-of"; import { MemoryKvStore } from "../federation/kv.ts"; import { FederationImpl } from "../federation/middleware.ts"; -import { Follow, Person } from "../vocab/vocab.ts"; import { actorDehydrator, autoIdAssigner } from "./transformers.ts"; const federation = new FederationImpl({ diff --git a/packages/fedify/src/compat/transformers.ts b/packages/fedify/src/compat/transformers.ts index 90017840c..c649935ec 100644 --- a/packages/fedify/src/compat/transformers.ts +++ b/packages/fedify/src/compat/transformers.ts @@ -1,6 +1,6 @@ +import type { Activity } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import type { Context } from "../federation/context.ts"; -import type { Activity } from "../vocab/vocab.ts"; import type { ActivityTransformer } from "./types.ts"; const logger = getLogger(["fedify", "compat", "transformers"]); @@ -47,7 +47,7 @@ export function autoIdAssigner( * activity like this: * * ```typescript - * import { Follow, Person } from "@fedify/fedify/vocab"; + * import { Follow, Person } from "@fedify/vocab"; * const input = new Follow({ * id: new URL("http://example.com/activities/1"), * actor: new Person({ @@ -66,7 +66,7 @@ export function autoIdAssigner( * The result of applying this transformer would be: * * ```typescript - * import { Follow, Person } from "@fedify/fedify/vocab"; + * import { Follow, Person } from "@fedify/vocab"; * const output = new Follow({ * id: new URL("http://example.com/activities/1"), * actor: new URL("http://example.com/actors/1"), diff --git a/packages/fedify/src/compat/types.ts b/packages/fedify/src/compat/types.ts index 191beaba3..37faeef2f 100644 --- a/packages/fedify/src/compat/types.ts +++ b/packages/fedify/src/compat/types.ts @@ -1,5 +1,5 @@ +import type { Activity } from "@fedify/vocab"; import type { Context } from "../federation/context.ts"; -import type { Activity } from "../vocab/vocab.ts"; /** * A function that transforms an activity object. diff --git a/packages/fedify/src/federation/builder.test.ts b/packages/fedify/src/federation/builder.test.ts index afd35dc8e..6be1353c8 100644 --- a/packages/fedify/src/federation/builder.test.ts +++ b/packages/fedify/src/federation/builder.test.ts @@ -1,7 +1,7 @@ import { test } from "@fedify/fixture"; +import { Activity, Note, Person } from "@fedify/vocab"; import { assertEquals, assertExists, assertThrows } from "@std/assert"; import type { Protocol } from "../nodeinfo/types.ts"; -import { Activity, Note, Person } from "../vocab/vocab.ts"; import { createFederationBuilder } from "./builder.ts"; import type { ActorDispatcher, diff --git a/packages/fedify/src/federation/builder.ts b/packages/fedify/src/federation/builder.ts index 77dd63862..843d6f2d9 100644 --- a/packages/fedify/src/federation/builder.ts +++ b/packages/fedify/src/federation/builder.ts @@ -1,9 +1,15 @@ +import type { + Activity, + Actor, + Hashtag, + Like, + Object, + Recipient, +} from "@fedify/vocab"; +import { getTypeId } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api"; import metadata from "../../deno.json" with { type: "json" }; -import type { Actor, Recipient } from "../vocab/actor.ts"; -import { getTypeId } from "../vocab/type.ts"; -import type { Activity, Hashtag, Like, Object } from "../vocab/vocab.ts"; import type { ActorAliasMapper, ActorDispatcher, diff --git a/packages/fedify/src/federation/callback.ts b/packages/fedify/src/federation/callback.ts index 0fd4a9703..6bf5a6c27 100644 --- a/packages/fedify/src/federation/callback.ts +++ b/packages/fedify/src/federation/callback.ts @@ -1,8 +1,6 @@ +import type { Activity, Actor, CryptographicKey, Object } from "@fedify/vocab"; +import type { Link } from "@fedify/webfinger"; import type { NodeInfo } from "../nodeinfo/types.ts"; -import type { Actor } from "../vocab/actor.ts"; -import type { Activity, CryptographicKey } from "../vocab/mod.ts"; -import type { Object } from "../vocab/vocab.ts"; -import type { Link } from "../webfinger/mod.ts"; import type { PageItems } from "./collection.ts"; import type { Context, InboxContext, RequestContext } from "./context.ts"; import type { SenderKeyPair } from "./send.ts"; diff --git a/packages/fedify/src/federation/context.ts b/packages/fedify/src/federation/context.ts index 518bb9774..b541c744c 100644 --- a/packages/fedify/src/federation/context.ts +++ b/packages/fedify/src/federation/context.ts @@ -1,23 +1,24 @@ -import type { DocumentLoader } from "@fedify/vocab-runtime"; -import type { TracerProvider } from "@opentelemetry/api"; -import type { GetNodeInfoOptions } from "../nodeinfo/client.ts"; -import type { JsonValue, NodeInfo } from "../nodeinfo/types.ts"; -import type { GetKeyOwnerOptions } from "../sig/owner.ts"; -import type { Actor, Recipient } from "../vocab/actor.ts"; -import type { - LookupObjectOptions, - TraverseCollectionOptions, -} from "../vocab/lookup.ts"; import type { Activity, + Actor, Collection, CryptographicKey, Link, + LookupObjectOptions, Multikey, Object, -} from "../vocab/vocab.ts"; -import type { ResourceDescriptor } from "../webfinger/jrd.ts"; -import type { LookupWebFingerOptions } from "../webfinger/lookup.ts"; + Recipient, + TraverseCollectionOptions, +} from "@fedify/vocab"; +import type { DocumentLoader } from "@fedify/vocab-runtime"; +import type { + LookupWebFingerOptions, + ResourceDescriptor, +} from "@fedify/webfinger"; +import type { TracerProvider } from "@opentelemetry/api"; +import type { GetNodeInfoOptions } from "../nodeinfo/client.ts"; +import type { JsonValue, NodeInfo } from "../nodeinfo/types.ts"; +import type { GetKeyOwnerOptions } from "../sig/owner.ts"; import type { ConstructorWithTypeId, Federation } from "./federation.ts"; import type { SenderKeyPair } from "./send.ts"; diff --git a/packages/fedify/src/federation/federation.ts b/packages/fedify/src/federation/federation.ts index d3a2b7a9b..be5075635 100644 --- a/packages/fedify/src/federation/federation.ts +++ b/packages/fedify/src/federation/federation.ts @@ -1,3 +1,10 @@ +import type { + Activity, + Actor, + Hashtag, + Object, + Recipient, +} from "@fedify/vocab"; import type { AuthenticatedDocumentLoaderFactory, DocumentLoaderFactory, @@ -6,8 +13,6 @@ import type { import type { TracerProvider } from "@opentelemetry/api"; import type { ActivityTransformer } from "../compat/types.ts"; import type { HttpMessageSignaturesSpec } from "../sig/http.ts"; -import type { Actor, Recipient } from "../vocab/actor.ts"; -import type { Activity, Hashtag, Object } from "../vocab/vocab.ts"; import type { ActorAliasMapper, ActorDispatcher, diff --git a/packages/fedify/src/federation/handler.test.ts b/packages/fedify/src/federation/handler.test.ts index 544f0fb9c..37a37cd14 100644 --- a/packages/fedify/src/federation/handler.test.ts +++ b/packages/fedify/src/federation/handler.test.ts @@ -3,6 +3,13 @@ import { mockDocumentLoader, test, } from "@fedify/fixture"; +import { + type Activity, + Create, + Note, + type Object, + Person, +} from "@fedify/vocab"; import { assert, assertEquals } from "@std/assert"; import { signRequest } from "../sig/http.ts"; import { @@ -14,13 +21,6 @@ import { rsaPublicKey2, rsaPublicKey3, } from "../testing/keys.ts"; -import { - type Activity, - Create, - Note, - type Object, - Person, -} from "../vocab/vocab.ts"; import type { ActorDispatcher, CollectionCounter, diff --git a/packages/fedify/src/federation/handler.ts b/packages/fedify/src/federation/handler.ts index eb905005e..7e975697e 100644 --- a/packages/fedify/src/federation/handler.ts +++ b/packages/fedify/src/federation/handler.ts @@ -1,3 +1,15 @@ +import type { Recipient } from "@fedify/vocab"; +import { + Activity, + Collection, + CollectionPage, + type CryptographicKey, + getTypeId, + Link, + Object, + OrderedCollection, + OrderedCollectionPage, +} from "@fedify/vocab"; import type { DocumentLoader } from "@fedify/vocab-runtime"; import { getLogger } from "@logtape/logtape"; import type { @@ -12,18 +24,6 @@ import { verifyRequest } from "../sig/http.ts"; import { detachSignature, verifyJsonLd } from "../sig/ld.ts"; import { doesActorOwnKey } from "../sig/owner.ts"; import { verifyObject } from "../sig/proof.ts"; -import type { Recipient } from "../vocab/actor.ts"; -import { getTypeId } from "../vocab/type.ts"; -import { - Activity, - Collection, - CollectionPage, - type CryptographicKey, - Link, - Object, - OrderedCollection, - OrderedCollectionPage, -} from "../vocab/vocab.ts"; import type { ActorDispatcher, AuthorizePredicate, diff --git a/packages/fedify/src/federation/idempotency.test.ts b/packages/fedify/src/federation/idempotency.test.ts index d8b715e87..9bf70d1a9 100644 --- a/packages/fedify/src/federation/idempotency.test.ts +++ b/packages/fedify/src/federation/idempotency.test.ts @@ -1,4 +1,5 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import { type Activity, Create, Follow, Person } from "@fedify/vocab"; import { assertEquals } from "@std/assert"; import { signObject } from "../sig/proof.ts"; import { @@ -6,7 +7,6 @@ import { ed25519PrivateKey, ed25519PublicKey, } from "../testing/keys.ts"; -import { type Activity, Create, Follow, Person } from "../vocab/vocab.ts"; import type { Federation, FederationOptions } from "./federation.ts"; import { MemoryKvStore } from "./kv.ts"; import { createFederation } from "./middleware.ts"; diff --git a/packages/fedify/src/federation/inbox.test.ts b/packages/fedify/src/federation/inbox.test.ts index 5454778db..09a27ceb9 100644 --- a/packages/fedify/src/federation/inbox.test.ts +++ b/packages/fedify/src/federation/inbox.test.ts @@ -1,7 +1,7 @@ import { test } from "@fedify/fixture"; +import { Activity, Create, Invite, Offer, Update } from "@fedify/vocab"; import { assertEquals } from "@std/assert/assert-equals"; import { assertThrows } from "@std/assert/assert-throws"; -import { Activity, Create, Invite, Offer, Update } from "../vocab/vocab.ts"; import { InboxListenerSet } from "./inbox.ts"; test("InboxListenerSet", () => { diff --git a/packages/fedify/src/federation/inbox.ts b/packages/fedify/src/federation/inbox.ts index 1181fa32a..c0a69b9e7 100644 --- a/packages/fedify/src/federation/inbox.ts +++ b/packages/fedify/src/federation/inbox.ts @@ -1,3 +1,4 @@ +import { Activity, getTypeId } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { context, @@ -9,8 +10,6 @@ import { type TracerProvider, } from "@opentelemetry/api"; import metadata from "../../deno.json" with { type: "json" }; -import { getTypeId } from "../vocab/type.ts"; -import { Activity } from "../vocab/vocab.ts"; import type { InboxErrorHandler, InboxListener } from "./callback.ts"; import type { Context, InboxContext } from "./context.ts"; import type { diff --git a/packages/fedify/src/federation/keycache.test.ts b/packages/fedify/src/federation/keycache.test.ts index 0d1764f39..501fe946e 100644 --- a/packages/fedify/src/federation/keycache.test.ts +++ b/packages/fedify/src/federation/keycache.test.ts @@ -1,8 +1,8 @@ import { test } from "@fedify/fixture"; +import { CryptographicKey, Multikey } from "@fedify/vocab"; import { assert } from "@std/assert/assert"; import { assertEquals } from "@std/assert/assert-equals"; import { assertInstanceOf } from "@std/assert/assert-instance-of"; -import { CryptographicKey, Multikey } from "../vocab/vocab.ts"; import { KvKeyCache } from "./keycache.ts"; import { MemoryKvStore } from "./kv.ts"; diff --git a/packages/fedify/src/federation/keycache.ts b/packages/fedify/src/federation/keycache.ts index 19e507d04..2ddd46715 100644 --- a/packages/fedify/src/federation/keycache.ts +++ b/packages/fedify/src/federation/keycache.ts @@ -1,6 +1,6 @@ +import { CryptographicKey, Multikey } from "@fedify/vocab"; import type { DocumentLoader } from "@fedify/vocab-runtime"; import type { KeyCache } from "../sig/key.ts"; -import { CryptographicKey, Multikey } from "../vocab/vocab.ts"; import type { KvKey, KvStore } from "./kv.ts"; export interface KvKeyCacheOptions { diff --git a/packages/fedify/src/federation/middleware.test.ts b/packages/fedify/src/federation/middleware.test.ts index ebd2fbea1..688d0cdbd 100644 --- a/packages/fedify/src/federation/middleware.test.ts +++ b/packages/fedify/src/federation/middleware.test.ts @@ -1,4 +1,6 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import * as vocab from "@fedify/vocab"; +import { getTypeId, lookupObject } from "@fedify/vocab"; import { assert, assertEquals, @@ -37,9 +39,6 @@ import { fetchDocumentLoader, getAuthenticatedDocumentLoader, } from "../utils/docloader.ts"; -import { lookupObject } from "../vocab/lookup.ts"; -import { getTypeId } from "../vocab/type.ts"; -import * as vocab from "../vocab/vocab.ts"; import type { Context } from "./context.ts"; import { MemoryKvStore } from "./kv.ts"; import { diff --git a/packages/fedify/src/federation/middleware.ts b/packages/fedify/src/federation/middleware.ts index a94539429..7659bec0f 100644 --- a/packages/fedify/src/federation/middleware.ts +++ b/packages/fedify/src/federation/middleware.ts @@ -1,11 +1,33 @@ -import type { GetUserAgentOptions } from "@fedify/vocab-runtime"; +import type { + Actor, + Collection, + Link, + LookupObjectOptions, + Object, + Recipient, + TraverseCollectionOptions, +} from "@fedify/vocab"; import { - type AuthenticatedDocumentLoaderFactory, - type DocumentLoader, - type DocumentLoaderFactory, - type DocumentLoaderFactoryOptions, - getDocumentLoader, + Activity, + CryptographicKey, + getTypeId, + lookupObject, + Multikey, + traverseCollection, +} from "@fedify/vocab"; +import type { + AuthenticatedDocumentLoaderFactory, + DocumentLoader, + DocumentLoaderFactory, + DocumentLoaderFactoryOptions, + GetUserAgentOptions, } from "@fedify/vocab-runtime"; +import { getDocumentLoader } from "@fedify/vocab-runtime"; +import type { + LookupWebFingerOptions, + ResourceDescriptor, +} from "@fedify/webfinger"; +import { lookupWebFinger } from "@fedify/webfinger"; import { getLogger, withContext } from "@logtape/logtape"; import { context, @@ -41,28 +63,6 @@ import { getKeyOwner, type GetKeyOwnerOptions } from "../sig/owner.ts"; import { signObject, verifyObject } from "../sig/proof.ts"; import { getAuthenticatedDocumentLoader } from "../utils/docloader.ts"; import { kvCache } from "../utils/kv-cache.ts"; -import type { Actor, Recipient } from "../vocab/actor.ts"; -import { - lookupObject, - type LookupObjectOptions, - traverseCollection, - type TraverseCollectionOptions, -} from "../vocab/lookup.ts"; -import { getTypeId } from "../vocab/type.ts"; -import { - Activity, - type Collection, - CryptographicKey, - type Link, - Multikey, - type Object, -} from "../vocab/vocab.ts"; -import { handleWebFinger } from "../webfinger/handler.ts"; -import type { ResourceDescriptor } from "../webfinger/jrd.ts"; -import { - lookupWebFinger, - type LookupWebFingerOptions, -} from "../webfinger/lookup.ts"; import { FederationBuilderImpl } from "./builder.ts"; import type { OutboxErrorHandler } from "./callback.ts"; import { buildCollectionSynchronizationHeader } from "./collection.ts"; @@ -107,6 +107,7 @@ import type { import { createExponentialBackoffPolicy, type RetryPolicy } from "./retry.ts"; import { RouterError } from "./router.ts"; import { extractInboxes, sendActivity, type SenderKeyPair } from "./send.ts"; +import { handleWebFinger } from "./webfinger.ts"; /** * Options for {@link createFederation} function. diff --git a/packages/fedify/src/federation/mod.ts b/packages/fedify/src/federation/mod.ts index 7affa82e4..161eeb0c5 100644 --- a/packages/fedify/src/federation/mod.ts +++ b/packages/fedify/src/federation/mod.ts @@ -26,3 +26,7 @@ export type { Message } from "./queue.ts"; export * from "./retry.ts"; export * from "./router.ts"; export { type SenderKeyPair } from "./send.ts"; +export { + handleWebFinger, + type WebFingerHandlerParameters, +} from "./webfinger.ts"; diff --git a/packages/fedify/src/federation/send.test.ts b/packages/fedify/src/federation/send.test.ts index 8c9753abb..e5a31bc4e 100644 --- a/packages/fedify/src/federation/send.test.ts +++ b/packages/fedify/src/federation/send.test.ts @@ -3,6 +3,15 @@ import { mockDocumentLoader, test, } from "@fedify/fixture"; +import type { Actor } from "@fedify/vocab"; +import { + Activity, + Application, + Endpoints, + Group, + Person, + Service, +} from "@fedify/vocab"; import { assert, assertEquals, @@ -19,15 +28,7 @@ import { rsaPrivateKey2, rsaPublicKey2, } from "../testing/keys.ts"; -import type { Actor } from "../vocab/actor.ts"; -import { - Activity, - Application, - Endpoints, - Group, - Person, - Service, -} from "../vocab/vocab.ts"; + import { extractInboxes, sendActivity } from "./send.ts"; test("extractInboxes()", () => { diff --git a/packages/fedify/src/federation/send.ts b/packages/fedify/src/federation/send.ts index 6cb05bb31..866c9bb2e 100644 --- a/packages/fedify/src/federation/send.ts +++ b/packages/fedify/src/federation/send.ts @@ -1,3 +1,4 @@ +import type { Recipient } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { type Span, @@ -11,7 +12,6 @@ import { doubleKnock, type HttpMessageSignaturesSpecDeterminer, } from "../sig/http.ts"; -import type { Recipient } from "../vocab/actor.ts"; /** * Parameters for {@link extractInboxes}. diff --git a/packages/fedify/src/webfinger/handler.test.ts b/packages/fedify/src/federation/webfinger.test.ts similarity index 99% rename from packages/fedify/src/webfinger/handler.test.ts rename to packages/fedify/src/federation/webfinger.test.ts index 01219f887..0ee8c7109 100644 --- a/packages/fedify/src/webfinger/handler.test.ts +++ b/packages/fedify/src/federation/webfinger.test.ts @@ -1,4 +1,6 @@ import { test } from "@fedify/fixture"; +import type { Actor } from "@fedify/vocab"; +import { Image, Link, Person } from "@fedify/vocab"; import { assertEquals } from "@std/assert"; import type { ActorAliasMapper, @@ -10,9 +12,7 @@ import type { RequestContext } from "../federation/context.ts"; import { MemoryKvStore } from "../federation/kv.ts"; import { createFederation } from "../federation/middleware.ts"; import { createRequestContext } from "../testing/context.ts"; -import type { Actor } from "../vocab/actor.ts"; -import { Image, Link, Person } from "../vocab/vocab.ts"; -import { handleWebFinger } from "./handler.ts"; +import { handleWebFinger } from "./webfinger.ts"; test("handleWebFinger()", async (t) => { const url = new URL("https://example.com/.well-known/webfinger"); diff --git a/packages/fedify/src/webfinger/handler.ts b/packages/fedify/src/federation/webfinger.ts similarity index 97% rename from packages/fedify/src/webfinger/handler.ts rename to packages/fedify/src/federation/webfinger.ts index 1aa5e0017..34a035571 100644 --- a/packages/fedify/src/webfinger/handler.ts +++ b/packages/fedify/src/federation/webfinger.ts @@ -1,3 +1,5 @@ +import { Link as LinkObject } from "@fedify/vocab"; +import type { Link, ResourceDescriptor } from "@fedify/webfinger"; import { getLogger } from "@logtape/logtape"; import type { Span, Tracer } from "@opentelemetry/api"; import { SpanKind, SpanStatusCode } from "@opentelemetry/api"; @@ -7,10 +9,8 @@ import type { ActorDispatcher, ActorHandleMapper, WebFingerLinksDispatcher, -} from "../federation/callback.ts"; -import type { RequestContext } from "../federation/context.ts"; -import { Link as LinkObject } from "../vocab/mod.ts"; -import type { Link, ResourceDescriptor } from "./jrd.ts"; +} from "./callback.ts"; +import type { RequestContext } from "./context.ts"; const logger = getLogger(["fedify", "webfinger", "server"]); diff --git a/packages/fedify/src/mod.ts b/packages/fedify/src/mod.ts index 1e17977d2..d8fe5b4bf 100644 --- a/packages/fedify/src/mod.ts +++ b/packages/fedify/src/mod.ts @@ -47,5 +47,3 @@ export * from "./federation/mod.ts"; export * from "./nodeinfo/mod.ts"; export * from "./sig/mod.ts"; export * from "./utils/mod.ts"; -export * from "./vocab/mod.ts"; -export { lookupWebFinger, type ResourceDescriptor } from "./webfinger/mod.ts"; diff --git a/packages/fedify/src/nodeinfo/client.ts b/packages/fedify/src/nodeinfo/client.ts index f07d1c967..32b76c3b5 100644 --- a/packages/fedify/src/nodeinfo/client.ts +++ b/packages/fedify/src/nodeinfo/client.ts @@ -1,6 +1,6 @@ import { getUserAgent, type GetUserAgentOptions } from "@fedify/vocab-runtime"; +import type { ResourceDescriptor } from "@fedify/webfinger"; import { getLogger } from "@logtape/logtape"; -import type { ResourceDescriptor } from "../webfinger/jrd.ts"; import type { InboundService, JsonValue, diff --git a/packages/fedify/src/nodeinfo/handler.ts b/packages/fedify/src/nodeinfo/handler.ts index efb30cc46..89d4e068d 100644 --- a/packages/fedify/src/nodeinfo/handler.ts +++ b/packages/fedify/src/nodeinfo/handler.ts @@ -1,7 +1,7 @@ +import type { Link, ResourceDescriptor } from "@fedify/webfinger"; import type { NodeInfoDispatcher } from "../federation/callback.ts"; import type { RequestContext } from "../federation/context.ts"; import { RouterError } from "../federation/router.ts"; -import type { Link, ResourceDescriptor } from "../webfinger/jrd.ts"; import { nodeInfoToJson } from "./types.ts"; /** diff --git a/packages/fedify/src/sig/http.test.ts b/packages/fedify/src/sig/http.test.ts index 7d352831f..9a68efc5c 100644 --- a/packages/fedify/src/sig/http.test.ts +++ b/packages/fedify/src/sig/http.test.ts @@ -1,4 +1,5 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import type { CryptographicKey, Multikey } from "@fedify/vocab"; import { exportSpki } from "@fedify/vocab-runtime"; import { assert, @@ -17,7 +18,6 @@ import { rsaPublicKey2, rsaPublicKey5, } from "../testing/keys.ts"; -import type { CryptographicKey, Multikey } from "../vocab/vocab.ts"; import { createRfc9421SignatureBase, doubleKnock, diff --git a/packages/fedify/src/sig/http.ts b/packages/fedify/src/sig/http.ts index 6b9a6dad5..4fd962ea8 100644 --- a/packages/fedify/src/sig/http.ts +++ b/packages/fedify/src/sig/http.ts @@ -1,3 +1,4 @@ +import { CryptographicKey } from "@fedify/vocab"; import type { DocumentLoader } from "@fedify/vocab-runtime"; import { getLogger } from "@logtape/logtape"; import { @@ -20,7 +21,6 @@ import { Item, } from "structured-field-values"; import metadata from "../../deno.json" with { type: "json" }; -import { CryptographicKey } from "../vocab/vocab.ts"; import { fetchKey, type KeyCache, validateCryptoKey } from "./key.ts"; /** diff --git a/packages/fedify/src/sig/key.test.ts b/packages/fedify/src/sig/key.test.ts index 536d36a3a..6f52f8d0a 100644 --- a/packages/fedify/src/sig/key.test.ts +++ b/packages/fedify/src/sig/key.test.ts @@ -1,4 +1,5 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import { CryptographicKey, Multikey } from "@fedify/vocab"; import { assertEquals, assertRejects, assertThrows } from "@std/assert"; import { ed25519Multikey, @@ -7,7 +8,6 @@ import { rsaPublicKey2, rsaPublicKey3, } from "../testing/keys.ts"; -import { CryptographicKey, Multikey } from "../vocab/vocab.ts"; import { exportJwk, fetchKey, diff --git a/packages/fedify/src/sig/key.ts b/packages/fedify/src/sig/key.ts index 0c7936919..016703743 100644 --- a/packages/fedify/src/sig/key.ts +++ b/packages/fedify/src/sig/key.ts @@ -1,3 +1,9 @@ +import { + CryptographicKey, + isActor, + type Multikey, + Object, +} from "@fedify/vocab"; import { type DocumentLoader, getDocumentLoader } from "@fedify/vocab-runtime"; import { getLogger } from "@logtape/logtape"; import { @@ -7,8 +13,6 @@ import { type TracerProvider, } from "@opentelemetry/api"; import metadata from "../../deno.json" with { type: "json" }; -import { isActor } from "../vocab/actor.ts"; -import { CryptographicKey, type Multikey, Object } from "../vocab/vocab.ts"; /** * Checks if the given key is valid and supported. No-op if the key is valid, diff --git a/packages/fedify/src/sig/ld.test.ts b/packages/fedify/src/sig/ld.test.ts index d4efecd06..c7f4db9a6 100644 --- a/packages/fedify/src/sig/ld.test.ts +++ b/packages/fedify/src/sig/ld.test.ts @@ -1,4 +1,5 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import { CryptographicKey } from "@fedify/vocab"; import { assert } from "@std/assert/assert"; import { assertEquals } from "@std/assert/assert-equals"; import { assertFalse } from "@std/assert/assert-false"; @@ -13,7 +14,6 @@ import { rsaPublicKey2, rsaPublicKey3, } from "../testing/keys.ts"; -import { CryptographicKey } from "../vocab/vocab.ts"; import { generateCryptoKeyPair } from "./key.ts"; import { attachSignature, diff --git a/packages/fedify/src/sig/ld.ts b/packages/fedify/src/sig/ld.ts index 41b4742eb..120bb6f09 100644 --- a/packages/fedify/src/sig/ld.ts +++ b/packages/fedify/src/sig/ld.ts @@ -1,3 +1,4 @@ +import { Activity, CryptographicKey, getTypeId, Object } from "@fedify/vocab"; import { type DocumentLoader, getDocumentLoader } from "@fedify/vocab-runtime"; import { getLogger } from "@logtape/logtape"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; @@ -5,8 +6,6 @@ import { decodeBase64, encodeBase64 } from "byte-encodings/base64"; import { encodeHex } from "byte-encodings/hex"; import jsonld from "jsonld"; import metadata from "../../deno.json" with { type: "json" }; -import { getTypeId } from "../vocab/type.ts"; -import { Activity, CryptographicKey, Object } from "../vocab/vocab.ts"; import { fetchKey, type KeyCache, validateCryptoKey } from "./key.ts"; const logger = getLogger(["fedify", "sig", "ld"]); diff --git a/packages/fedify/src/sig/owner.test.ts b/packages/fedify/src/sig/owner.test.ts index 7d13d433c..29990ab54 100644 --- a/packages/fedify/src/sig/owner.test.ts +++ b/packages/fedify/src/sig/owner.test.ts @@ -3,10 +3,9 @@ import { mockDocumentLoader, test, } from "@fedify/fixture"; +import { Create, CryptographicKey, lookupObject } from "@fedify/vocab"; import { assert, assertEquals, assertFalse } from "@std/assert"; import { rsaPublicKey1, rsaPublicKey2 } from "../testing/keys.ts"; -import { lookupObject } from "../vocab/lookup.ts"; -import { Create, CryptographicKey } from "../vocab/vocab.ts"; import { doesActorOwnKey, getKeyOwner } from "./owner.ts"; test("doesActorOwnKey()", async () => { diff --git a/packages/fedify/src/sig/owner.ts b/packages/fedify/src/sig/owner.ts index 4da8433f1..796b73b36 100644 --- a/packages/fedify/src/sig/owner.ts +++ b/packages/fedify/src/sig/owner.ts @@ -1,3 +1,10 @@ +import { + type Activity, + type Actor, + CryptographicKey, + isActor, + Object as ASObject, +} from "@fedify/vocab"; import { type DocumentLoader, getDocumentLoader } from "@fedify/vocab-runtime"; import { SpanKind, @@ -6,12 +13,6 @@ import { type TracerProvider, } from "@opentelemetry/api"; import metadata from "../../deno.json" with { type: "json" }; -import { type Actor, isActor } from "../vocab/actor.ts"; -import { - type Activity, - CryptographicKey, - Object as ASObject, -} from "../vocab/vocab.ts"; export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.ts"; /** diff --git a/packages/fedify/src/sig/proof.test.ts b/packages/fedify/src/sig/proof.test.ts index d79610873..f78a40092 100644 --- a/packages/fedify/src/sig/proof.test.ts +++ b/packages/fedify/src/sig/proof.test.ts @@ -1,4 +1,12 @@ import { mockDocumentLoader, test } from "@fedify/fixture"; +import { + Create, + type CryptographicKey, + DataIntegrityProof, + Multikey, + Note, + Place, +} from "@fedify/vocab"; import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime"; import { assertEquals, assertInstanceOf, assertRejects } from "@std/assert"; import { decodeHex, encodeHex } from "byte-encodings/hex"; @@ -9,14 +17,6 @@ import { rsaPrivateKey2, rsaPublicKey2, } from "../testing/keys.ts"; -import { - Create, - type CryptographicKey, - DataIntegrityProof, - Multikey, - Note, - Place, -} from "../vocab/vocab.ts"; import type { KeyCache } from "./key.ts"; import { createProof, diff --git a/packages/fedify/src/sig/proof.ts b/packages/fedify/src/sig/proof.ts index a0c6f4474..fe00938b5 100644 --- a/packages/fedify/src/sig/proof.ts +++ b/packages/fedify/src/sig/proof.ts @@ -1,16 +1,16 @@ +import { + Activity, + DataIntegrityProof, + getTypeId, + Multikey, + type Object, +} from "@fedify/vocab"; import type { DocumentLoader } from "@fedify/vocab-runtime"; import { getLogger } from "@logtape/logtape"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; import { encodeHex } from "byte-encodings/hex"; import serialize from "json-canon"; import metadata from "../../deno.json" with { type: "json" }; -import { getTypeId } from "../vocab/type.ts"; -import { - Activity, - DataIntegrityProof, - Multikey, - type Object, -} from "../vocab/vocab.ts"; import { fetchKey, type FetchKeyResult, diff --git a/packages/fedify/src/testing/context.ts b/packages/fedify/src/testing/context.ts index 81e3e5a9b..ddcc06a26 100644 --- a/packages/fedify/src/testing/context.ts +++ b/packages/fedify/src/testing/context.ts @@ -1,4 +1,9 @@ import { mockDocumentLoader } from "@fedify/fixture"; +import { + lookupObject as globalLookupObject, + traverseCollection as globalTraverseCollection, +} from "@fedify/vocab"; +import { lookupWebFinger as globalLookupWebFinger } from "@fedify/webfinger"; import { trace } from "@opentelemetry/api"; import type { Context, @@ -7,11 +12,6 @@ import type { } from "../federation/context.ts"; import type { Federation } from "../federation/federation.ts"; import { RouterError } from "../federation/router.ts"; -import { - lookupObject as globalLookupObject, - traverseCollection as globalTraverseCollection, -} from "../vocab/lookup.ts"; -import { lookupWebFinger as globalLookupWebFinger } from "../webfinger/lookup.ts"; export function createContext( values: Partial> & { diff --git a/packages/fedify/src/testing/keys.ts b/packages/fedify/src/testing/keys.ts index 4a0815cdf..fb187c4f6 100644 --- a/packages/fedify/src/testing/keys.ts +++ b/packages/fedify/src/testing/keys.ts @@ -1,5 +1,5 @@ +import { CryptographicKey, Multikey } from "@fedify/vocab"; import { importSpki } from "@fedify/vocab-runtime"; -import { CryptographicKey, Multikey } from "../vocab/vocab.ts"; export const rsaPublicKey1 = new CryptographicKey({ id: new URL("https://example.com/key"), diff --git a/packages/fedify/src/testing/mod.ts b/packages/fedify/src/testing/mod.ts index 3ae7a6198..91d655a70 100644 --- a/packages/fedify/src/testing/mod.ts +++ b/packages/fedify/src/testing/mod.ts @@ -1,2 +1,3 @@ -export * from "@fedify/fixture"; export { createInboxContext, createRequestContext } from "./context.ts"; +// without bellows, `test:cfworkers` makes error +export { testDefinitions } from "@fedify/fixture"; diff --git a/packages/fedify/tsdown.config.ts b/packages/fedify/tsdown.config.ts index d4d759aac..89c6eb410 100644 --- a/packages/fedify/tsdown.config.ts +++ b/packages/fedify/tsdown.config.ts @@ -12,8 +12,6 @@ export default [ "./src/otel/mod.ts", "./src/utils/mod.ts", "./src/sig/mod.ts", - "./src/vocab/mod.ts", - "./src/webfinger/mod.ts", ], dts: true, format: ["esm", "cjs"], @@ -45,12 +43,6 @@ export default [ inputOptions: { onwarn(warning, defaultHandler) { if ( - warning.code === "UNRESOLVED_IMPORT" && - warning.id?.endsWith(join("vocab", "vocab.test.ts")) && - warning.exporter === "@std/testing/snapshot" - ) { - return; - } else if ( warning.code === "UNRESOLVED_IMPORT" && warning.id?.endsWith(join("testing", "mod.ts")) && warning.exporter === "bun:test" diff --git a/packages/fixture/package.json b/packages/fixture/package.json index 4a6038e4f..d80a2b3e3 100644 --- a/packages/fixture/package.json +++ b/packages/fixture/package.json @@ -15,6 +15,11 @@ "types": "./dist/mod.d.ts", "exports": { ".": { + "types": { + "import": "./dist/mod.d.ts", + "require": "./dist/mod.d.cts", + "default": "./dist/mod.d.ts" + }, "import": "./dist/mod.js", "require": "./dist/mod.cjs", "default": "./dist/mod.js" @@ -26,21 +31,23 @@ "dist/", "package.json" ], - "peerDependencies": { + "dependencies": { "@fedify/vocab-runtime": "workspace:^", "@logtape/logtape": "catalog:", "@opentelemetry/core": "catalog:", "@opentelemetry/sdk-trace-base": "catalog:" }, "devDependencies": { + "@js-temporal/polyfill": "catalog:", "tsdown": "catalog:", - "typescript": "catalog:" + "typescript": "catalog:", + "urlpattern-polyfill": "catalog:" }, "scripts": { "build": "tsdown", "prepack": "tsdown", "prepublish": "tsdown", - "test": "deno task codegen && tsdown && cd dist/ && node --test" + "test": "tsdown && cd dist/ && node --test" }, "private": true } diff --git a/packages/fixture/src/docloader.test.ts b/packages/fixture/src/docloader.test.ts index 6e419aea4..3a046e5af 100644 --- a/packages/fixture/src/docloader.test.ts +++ b/packages/fixture/src/docloader.test.ts @@ -1,4 +1,4 @@ -import { deepStrictEqual } from "node:assert"; +import { deepStrictEqual } from "node:assert/strict"; import { mockDocumentLoader } from "./docloader.ts"; import { test } from "./test.ts"; diff --git a/packages/fixture/tsdown.config.ts b/packages/fixture/tsdown.config.ts index a7d03d068..89b694d01 100644 --- a/packages/fixture/tsdown.config.ts +++ b/packages/fixture/tsdown.config.ts @@ -2,44 +2,35 @@ import { cp, glob } from "node:fs/promises"; import { join, sep } from "node:path"; import { defineConfig } from "tsdown"; -export default defineConfig({ - entry: [ - "src/mod.ts", - ...(await Array.fromAsync(glob(`src/**/*.test.ts`))) - .map((f) => f.replace(sep, "/")), - ], - dts: true, - format: ["esm"], - platform: "neutral", - external: [/^node:/], - inputOptions: { - onwarn(warning, defaultHandler) { - if ( - warning.code === "UNRESOLVED_IMPORT" && - warning.id?.endsWith(join("mod.ts")) && - warning.exporter === "bun:test" - ) { - return; - } - defaultHandler(warning); - }, - }, - outputOptions: { - intro: ` - import { Temporal } from "@js-temporal/polyfill"; - import { URLPattern } from "urlpattern-polyfill"; - globalThis.addEventListener = () => {}; - `, - }, - hooks: { - "build:done": async (ctx) => { - await cp( - join("src", "fixtures"), - join(ctx.options.outDir, "fixtures"), - { recursive: true }, - ); +export default [ + defineConfig({ + entry: ["src/mod.ts"], + dts: true, + format: ["esm", "cjs"], + platform: "neutral", + external: [/^node:/], + hooks: { + "build:done": async (ctx) => { + for await (const file of glob("src/fixtures/**/*.json")) { + await cp( + file, + join(ctx.options.outDir, file.replace(`src${sep}`, "")), + { force: true }, + ); + } + }, }, - }, -}); + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + format: ["esm", "cjs"], + platform: "node", + external: [ + /^node:/, + "@fedify/vocab-runtime", + ], + }), +]; // cSpell: ignore onwarn diff --git a/packages/hono/package.json b/packages/hono/package.json index 88ccd1872..2def0ec77 100644 --- a/packages/hono/package.json +++ b/packages/hono/package.json @@ -60,6 +60,6 @@ "build": "tsdown", "prepack": "tsdown", "prepublish": "tsdown", - "test": "deno task codegen && tsdown && cd dist/ && node --test" + "test": "node --experimental-transform-types --test" } } diff --git a/packages/postgres/src/mq.test.ts b/packages/postgres/src/mq.test.ts index 40ce48d51..715b1b983 100644 --- a/packages/postgres/src/mq.test.ts +++ b/packages/postgres/src/mq.test.ts @@ -1,8 +1,8 @@ import { PostgresMessageQueue } from "@fedify/postgres/mq"; import * as temporal from "@js-temporal/polyfill"; import { delay } from "@std/async/delay"; -import process from "node:process"; import assert from "node:assert/strict"; +import process from "node:process"; import { test } from "node:test"; import postgres from "postgres"; diff --git a/packages/relay/deno.json b/packages/relay/deno.json index d1d98e39b..fe602ecb4 100644 --- a/packages/relay/deno.json +++ b/packages/relay/deno.json @@ -2,7 +2,6 @@ "name": "@fedify/relay", "version": "2.0.0", "license": "MIT", - "exports": {}, "imports": { "@std/assert": "jsr:@std/assert@^1.0.13" }, @@ -17,9 +16,9 @@ "exclude": ["**/*.test.ts"] }, "tasks": { - "codegen": "deno task -f @fedify/fedify codegen", + "codegen": "deno task -f @fedify/vocab compile", "check": { - "command": "deno task codegen && deno fmt --check && deno lint && deno check src/**/*.ts", + "command": "deno fmt --check && deno lint && deno check src/**/*.ts", "dependencies": [ "codegen" ] diff --git a/packages/relay/package.json b/packages/relay/package.json index 610690a13..b763ec76c 100644 --- a/packages/relay/package.json +++ b/packages/relay/package.json @@ -48,23 +48,22 @@ "package.json" ], "dependencies": { + "@fedify/fedify": "workspace:^", + "@fedify/vocab": "workspace:*", "@js-temporal/polyfill": "catalog:", "@logtape/logtape": "catalog:" }, - "peerDependencies": { - "@fedify/fedify": "workspace:^" - }, "devDependencies": { - "@fedify/testing": "workspace:^", "@fedify/vocab-runtime": "workspace:^", "tsdown": "catalog:", - "typescript": "catalog:" + "typescript": "catalog:", + "urlpattern-polyfill": "catalog:" }, "scripts": { - "build": "deno task codegen && tsdown", - "prepack": "deno task codegen && tsdown", - "prepublish": "deno task codegen && tsdown", - "test": "deno task codegen && tsdown && node --test", - "test:bun": "deno task codegen && tsdown && bun test --timeout 60000" + "build": "tsdown", + "prepack": "tsdown", + "prepublish": "tsdown", + "test": "tsdown && cd dist/ && node --test", + "test:bun": "tsdown && cd dist/ && bun test --timeout 60000" } } diff --git a/packages/relay/src/base.ts b/packages/relay/src/base.ts index c7309457f..d7a18e075 100644 --- a/packages/relay/src/base.ts +++ b/packages/relay/src/base.ts @@ -1,5 +1,5 @@ import type { Context, Federation, FederationBuilder } from "@fedify/fedify"; -import { isActor, Object as APObject } from "@fedify/fedify/vocab"; +import { isActor, Object as APObject } from "@fedify/vocab"; import { isRelayFollowerData, type Relay, diff --git a/packages/relay/src/builder.ts b/packages/relay/src/builder.ts index 15ea7688f..7bd40aa3f 100644 --- a/packages/relay/src/builder.ts +++ b/packages/relay/src/builder.ts @@ -6,8 +6,8 @@ import { generateCryptoKeyPair, importJwk, } from "@fedify/fedify"; -import { Application, isActor, Object } from "@fedify/fedify/vocab"; -import type { Actor } from "@fedify/fedify/vocab"; +import type { Actor } from "@fedify/vocab"; +import { Application, isActor, Object } from "@fedify/vocab"; import { isRelayFollowerData, RELAY_SERVER_ACTOR, diff --git a/packages/relay/src/follow.ts b/packages/relay/src/follow.ts index 5094df656..aa4f830fa 100644 --- a/packages/relay/src/follow.ts +++ b/packages/relay/src/follow.ts @@ -1,11 +1,5 @@ -import { - Accept, - type Context, - Follow, - Reject, - type Undo, -} from "@fedify/fedify"; -import type { Actor } from "@fedify/fedify/vocab"; +import type { Context } from "@fedify/fedify"; +import { Accept, type Actor, Follow, Reject, type Undo } from "@fedify/vocab"; import type { getLogger } from "@logtape/logtape"; import { RELAY_SERVER_ACTOR, type RelayOptions } from "./types.ts"; diff --git a/packages/relay/src/litepub.test.ts b/packages/relay/src/litepub.test.ts index 9afd0ee43..899bf6d8b 100644 --- a/packages/relay/src/litepub.test.ts +++ b/packages/relay/src/litepub.test.ts @@ -1,5 +1,6 @@ // deno-lint-ignore-file no-explicit-any import { MemoryKvStore, signRequest } from "@fedify/fedify"; +import { createRelay, type RelayOptions } from "@fedify/relay"; import { Accept, Announce, @@ -11,7 +12,7 @@ import { Person, Undo, Update, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; import { exportSpki, getDocumentLoader, @@ -19,7 +20,6 @@ import { } from "@fedify/vocab-runtime"; import { ok, strictEqual } from "node:assert"; import test, { describe } from "node:test"; -import { createRelay, type RelayOptions } from "@fedify/relay"; import { isRelayFollowerData } from "./types.ts"; // Simple mock document loader that returns a minimal context diff --git a/packages/relay/src/litepub.ts b/packages/relay/src/litepub.ts index 0b0fff5b3..8114e0f50 100644 --- a/packages/relay/src/litepub.ts +++ b/packages/relay/src/litepub.ts @@ -1,16 +1,16 @@ +import type { InboxContext } from "@fedify/fedify"; import { Accept, Announce, Create, Delete, Follow, - type InboxContext, isActor, Move, PUBLIC_COLLECTION, Undo, Update, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { BaseRelay } from "./base.ts"; import { diff --git a/packages/relay/src/mastodon.test.ts b/packages/relay/src/mastodon.test.ts index e43bd3803..d5a73b503 100644 --- a/packages/relay/src/mastodon.test.ts +++ b/packages/relay/src/mastodon.test.ts @@ -1,5 +1,6 @@ // deno-lint-ignore-file no-explicit-any import { MemoryKvStore, signRequest } from "@fedify/fedify"; +import { createRelay, type RelayOptions } from "@fedify/relay"; import { Create, Delete, @@ -9,7 +10,7 @@ import { Person, Undo, Update, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; import { exportSpki, getDocumentLoader, @@ -17,7 +18,6 @@ import { } from "@fedify/vocab-runtime"; import { ok, strictEqual } from "node:assert"; import test, { describe } from "node:test"; -import { createRelay, type RelayOptions } from "@fedify/relay"; import { isRelayFollowerData } from "./types.ts"; // Simple mock document loader that returns a minimal context diff --git a/packages/relay/src/mastodon.ts b/packages/relay/src/mastodon.ts index 6af28ab47..a1136be6a 100644 --- a/packages/relay/src/mastodon.ts +++ b/packages/relay/src/mastodon.ts @@ -1,13 +1,13 @@ +import type { InboxContext } from "@fedify/fedify"; import { Announce, Create, Delete, Follow, - type InboxContext, Move, Undo, Update, -} from "@fedify/fedify"; +} from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; import { BaseRelay } from "./base.ts"; import { diff --git a/packages/relay/src/types.ts b/packages/relay/src/types.ts index 65f35e42f..fd906bed7 100644 --- a/packages/relay/src/types.ts +++ b/packages/relay/src/types.ts @@ -1,5 +1,5 @@ import type { Context, KvStore, MessageQueue } from "@fedify/fedify"; -import type { Actor } from "@fedify/fedify/vocab"; +import type { Actor } from "@fedify/vocab"; import type { AuthenticatedDocumentLoaderFactory, DocumentLoaderFactory, diff --git a/packages/relay/tsdown.config.ts b/packages/relay/tsdown.config.ts index a89df939d..6fb051e1c 100644 --- a/packages/relay/tsdown.config.ts +++ b/packages/relay/tsdown.config.ts @@ -1,20 +1,37 @@ +import { glob } from "node:fs/promises"; +import { sep } from "node:path"; import { defineConfig } from "tsdown"; -export default defineConfig({ - entry: ["src/mod.ts"], - dts: true, - format: ["esm", "cjs"], - platform: "node", - outputOptions(outputOptions, format) { - if (format === "cjs") { - outputOptions.intro = ` +export default [ + defineConfig({ + entry: ["src/mod.ts"], + dts: true, + format: ["esm", "cjs"], + platform: "node", + outputOptions(outputOptions, format) { + if (format === "cjs") { + outputOptions.intro = ` const { Temporal } = require("@js-temporal/polyfill"); `; - } else { - outputOptions.intro = ` + } else { + outputOptions.intro = ` import { Temporal } from "@js-temporal/polyfill"; `; - } - return outputOptions; - }, -}); + } + return outputOptions; + }, + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + dts: true, + external: [/^node:/], + outputOptions: { + intro: ` + import { Temporal } from "@js-temporal/polyfill"; + import { URLPattern } from "urlpattern-polyfill"; + globalThis.addEventListener = () => {}; + `, + }, + }), +]; diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index 6c03c6bf9..1234a779a 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -62,6 +62,6 @@ "prepack": "tsdown", "prepublish": "tsdown", "dev": "tsdown --watch", - "test": "deno task codegen && tsdown && cd dist/ && node --test" + "test": "node --experimental-transform-types --test" } } diff --git a/packages/testing/README.md b/packages/testing/README.md index ce66e8500..e80ba578e 100644 --- a/packages/testing/README.md +++ b/packages/testing/README.md @@ -40,7 +40,7 @@ interface for unit testing: ~~~~ typescript import { MockFederation } from "@fedify/testing"; -import { Create } from "@fedify/fedify/vocab"; +import { Create } from "@fedify/vocab"; // Create a mock federation const federation = new MockFederation<{ userId: string }>(); diff --git a/packages/testing/src/context.ts b/packages/testing/src/context.ts index 98753f670..7ae82d9a9 100644 --- a/packages/testing/src/context.ts +++ b/packages/testing/src/context.ts @@ -9,7 +9,7 @@ import { RouterError } from "@fedify/fedify/federation"; import { lookupObject as globalLookupObject, traverseCollection as globalTraverseCollection, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; import { mockDocumentLoader } from "./docloader.ts"; // Create a no-op tracer provider. diff --git a/packages/testing/src/mock.test.ts b/packages/testing/src/mock.test.ts index ff0c564cb..cded9d85d 100644 --- a/packages/testing/src/mock.test.ts +++ b/packages/testing/src/mock.test.ts @@ -1,7 +1,7 @@ import type { InboxContext } from "@fedify/fedify/federation"; -import { Create, Note, Person } from "@fedify/fedify/vocab"; +import { test } from "@fedify/fixture"; +import { Create, Note, Person } from "@fedify/vocab"; import { assertEquals, assertRejects } from "@std/assert"; -import { test } from "../../fedify/src/testing/mod.ts"; import { createFederation } from "./mock.ts"; test("getSentActivities returns sent activities", async () => { diff --git a/packages/testing/src/mock.ts b/packages/testing/src/mock.ts index 05aff0a9b..17497d430 100644 --- a/packages/testing/src/mock.ts +++ b/packages/testing/src/mock.ts @@ -10,14 +10,14 @@ import type { RequestContext, RouteActivityOptions, } from "@fedify/fedify/federation"; -import type { DocumentLoader } from "@fedify/vocab-runtime"; import type { Activity, Collection, LookupObjectOptions, Object, TraverseCollectionOptions, -} from "@fedify/fedify/vocab"; +} from "@fedify/vocab"; +import type { DocumentLoader } from "@fedify/vocab-runtime"; import { createContext, createInboxContext, @@ -141,7 +141,7 @@ interface TestFederation * * @example * ```typescript - * import { Create } from "@fedify/fedify/vocab"; + * import { Create } from "@fedify/vocab"; * import { createFederation } from "@fedify/testing"; * * // Create a mock federation with contextData @@ -495,7 +495,7 @@ class MockFederation implements Federation { * * @example * ```typescript - * import { Create } from "@fedify/fedify/vocab"; + * import { Create } from "@fedify/vocab"; * import { createFederation } from "@fedify/testing"; * * // Create a mock federation with contextData @@ -544,7 +544,7 @@ export function createFederation( * * @example * ```typescript - * import { Person, Create } from "@fedify/fedify/vocab"; + * import { Person, Create } from "@fedify/vocab"; * import { createFederation } from "@fedify/testing"; * * // Create a mock federation and context diff --git a/packages/testing/tsdown.config.ts b/packages/testing/tsdown.config.ts index 655d7db35..516eb89d6 100644 --- a/packages/testing/tsdown.config.ts +++ b/packages/testing/tsdown.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ "@fedify/fedify/federation", "@fedify/fedify/nodeinfo", "@fedify/fedify/utils", - "@fedify/fedify/vocab", + "@fedify/vocab", "@fedify/fedify/webfinger", ], }); diff --git a/packages/vocab-runtime/package.json b/packages/vocab-runtime/package.json index 3d4a2647a..99c01b853 100644 --- a/packages/vocab-runtime/package.json +++ b/packages/vocab-runtime/package.json @@ -62,11 +62,11 @@ }, "dependencies": { "@logtape/logtape": "catalog:", - "@multiformats/base-x": "^4.0.1", + "@multiformats/base-x": "catalog:", "@opentelemetry/api": "catalog:", - "asn1js": "^3.0.6", + "asn1js": "catalog:", "byte-encodings": "catalog:", "multicodec": "^3.2.1", - "pkijs": "^3.2.5" + "pkijs": "catalog:" } } diff --git a/packages/vocab-runtime/tsdown.config.ts b/packages/vocab-runtime/tsdown.config.ts index e3e4bfd52..5fa66a56e 100644 --- a/packages/vocab-runtime/tsdown.config.ts +++ b/packages/vocab-runtime/tsdown.config.ts @@ -1,9 +1,20 @@ +import { glob } from "node:fs/promises"; +import { sep } from "node:path"; import { defineConfig } from "tsdown"; -export default defineConfig({ - entry: ["src/mod.ts"], - dts: true, - format: ["esm", "cjs"], - platform: "node", - external: [/^node:/], -}); +export default [ + defineConfig({ + entry: ["src/mod.ts"], + dts: true, + format: ["esm", "cjs"], + platform: "neutral", + external: [/^node:/], + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + format: ["esm", "cjs"], + platform: "node", + external: [/^node:/], + }), +]; diff --git a/packages/vocab-tools/src/class.test.ts b/packages/vocab-tools/src/class.test.ts index f44dac40b..9f6d8018d 100644 --- a/packages/vocab-tools/src/class.test.ts +++ b/packages/vocab-tools/src/class.test.ts @@ -1,5 +1,5 @@ import { deepStrictEqual } from "node:assert"; -import { basename, dirname, join } from "node:path"; +import { basename, dirname, extname, join } from "node:path"; import { test } from "node:test"; import metadata from "../deno.json" with { type: "json" }; import { generateClasses, sortTopologically } from "./class.ts"; @@ -88,7 +88,7 @@ if ("Deno" in globalThis) { async function getEntireCode() { const packagesDir = dirname(dirname(import.meta.dirname!)); - const schemaDir = join(packagesDir, "fedify", "src", "vocab"); + const schemaDir = join(packagesDir, "vocab", "src"); const types = await loadSchemaFiles(schemaDir); const entireCode = (await Array.fromAsync(generateClasses(types))) .join("") @@ -106,7 +106,7 @@ async function changeNodeSnapshotPath() { return join( dirname(path), "__snapshots__", - basename(path) + ".node.snap", + basename(path.replace(extname(path), ".ts")) + ".node.snap", ); }, ); diff --git a/packages/vocab-tools/tsdown.config.ts b/packages/vocab-tools/tsdown.config.ts index 798016abb..584311ff0 100644 --- a/packages/vocab-tools/tsdown.config.ts +++ b/packages/vocab-tools/tsdown.config.ts @@ -1,20 +1,55 @@ -import { cp } from "node:fs/promises"; -import { join } from "node:path"; +import { cp, glob } from "node:fs/promises"; +import { join, sep } from "node:path"; import { defineConfig } from "tsdown"; -export default defineConfig({ - entry: ["src/mod.ts"], - dts: true, - format: ["esm", "cjs"], - platform: "node", - external: [/^node:/], - hooks: { - "build:done": async (ctx) => { - await cp( - join("src", "schema.yaml"), - join(ctx.options.outDir, "schema.yaml"), - { force: true }, - ); +export default [ + defineConfig({ + entry: ["src/mod.ts"], + dts: true, + format: ["esm", "cjs"], + platform: "neutral", + external: [/^node:/], + hooks: { + "build:done": async (ctx) => { + await cp( + join("src", "schema.yaml"), + join(ctx.options.outDir, "schema.yaml"), + { force: true }, + ); + }, }, - }, -}); + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + format: ["esm"], + platform: "node", + external: [ + /^node:/, + /^bun:/, + ], + inputOptions: { + onwarn(warning, defaultHandler) { + if ( + warning.code === "UNRESOLVED_IMPORT" && + warning.id?.endsWith(".test.ts") && + warning.exporter && + ["bun:test", "@std/testing/snapshot"].includes(warning.exporter) + ) { + return; + } + defaultHandler(warning); + }, + }, + hooks: { + "build:done": async (ctx) => { + await cp( + join("src", "__snapshots__"), + join(ctx.options.outDir, "__snapshots__"), + { recursive: true }, + ); + }, + }, + }), +]; +// cSpell: ignore onwarn diff --git a/packages/vocab/README.md b/packages/vocab/README.md new file mode 100644 index 000000000..353424af4 --- /dev/null +++ b/packages/vocab/README.md @@ -0,0 +1,139 @@ + + +@fedify/vocab: ActivityPub vocabulary for Fedify +================================================ + +[![JSR][JSR badge]][JSR] +[![npm][npm badge]][npm] + +This package provides a collection of type-safe objects that represent the +[Activity Vocabulary] and vendor-specific extensions for the [Fedify] framework. +It is the core vocabulary library that powers ActivityPub object handling in +Fedify applications. + +[JSR]: https://jsr.io/@fedify/vocab +[JSR badge]: https://jsr.io/badges/@fedify/vocab +[npm]: https://www.npmjs.com/package/@fedify/vocab +[npm badge]: https://img.shields.io/npm/v/@fedify/vocab?logo=npm +[Activity Vocabulary]: https://www.w3.org/TR/activitystreams-vocabulary/ +[Fedify]: https://fedify.dev/ + + +Features +-------- + + - Type-safe objects for [Activity Vocabulary] types (`Create`, `Note`, + `Person`, etc.) + - Vendor-specific extensions (Mastodon, Misskey, etc.) + - JSON-LD serialization and deserialization + - Immutable object design with `clone()` method for modifications + - Support for looking up remote objects + - Actor handle resolution via WebFinger + + +Installation +------------ + +~~~~ bash +deno add jsr:@fedify/vocab # Deno +npm add @fedify/vocab # npm +pnpm add @fedify/vocab # pnpm +yarn add @fedify/vocab # Yarn +bun add @fedify/vocab # Bun +~~~~ + + +Usage +----- + +### Instantiation + +You can instantiate an object by calling the constructor with properties: + +~~~~ typescript +import { Create, Note } from "@fedify/vocab"; + +const create = new Create({ + id: new URL("https://example.com/activities/123"), + actor: new URL("https://example.com/users/alice"), + object: new Note({ + id: new URL("https://example.com/notes/456"), + content: "Hello, world!", + }), +}); +~~~~ + +### JSON-LD serialization + +Deserialize from JSON-LD: + +~~~~ typescript +import { Create } from "@fedify/vocab"; + +const create = await Create.fromJsonLd({ + "@context": "https://www.w3.org/ns/activitystreams", + "type": "Create", + "id": "https://example.com/activities/123", + "actor": "https://example.com/users/alice", + "object": { + "type": "Note", + "id": "https://example.com/notes/456", + "content": "Hello, world!", + } +}); +~~~~ + +Serialize to JSON-LD: + +~~~~ typescript +const jsonLd = await create.toJsonLd(); +~~~~ + +### Immutability + +All objects are immutable. Use `clone()` to create modified copies: + +~~~~ typescript +import { Note } from "@fedify/vocab"; +import { LanguageString } from "@fedify/vocab-runtime"; + +const noteInEnglish = new Note({ + id: new URL("https://example.com/notes/123"), + content: new LanguageString("Hello, world!", "en"), +}); + +const noteInChinese = noteInEnglish.clone({ + content: new LanguageString("你好,世界!", "zh"), +}); +~~~~ + +### Looking up remote objects + +~~~~ typescript +import { lookupObject } from "@fedify/vocab"; + +const object = await lookupObject("https://example.com/users/alice"); +~~~~ + + +Documentation +------------- + +For comprehensive documentation, please refer to: + + - [Vocabulary documentation](https://fedify.dev/manual/vocab) + - [API reference](https://jsr.io/@fedify/vocab/doc/~) + + +Related packages +---------------- + + - *@fedify/fedify*: The main Fedify framework + - *@fedify/vocab-runtime*: Runtime utilities for vocabulary objects + - *@fedify/vocab-tools*: Code generation tools for Activity Vocabulary + + +License +------- + +[MIT License](https://github.com/fedify-dev/fedify/blob/main/LICENSE) diff --git a/packages/vocab/deno.json b/packages/vocab/deno.json new file mode 100644 index 000000000..a7afbdb3a --- /dev/null +++ b/packages/vocab/deno.json @@ -0,0 +1,31 @@ +{ + "name": "@fedify/vocab", + "version": "2.0.0", + "license": "MIT", + "exports": { + ".": "./src/mod.ts" + }, + "description": "Vocabularies library for @fedify/fedify", + "author": { + "name": "Hong Minhee", + "email": "hong@minhee.org", + "url": "https://hongminhee.org/" + }, + "imports": { + "@opentelemetry/api": "npm:@opentelemetry/api@^1.9.0", + "fast-check": "npm:fast-check@^3.22.0", + "fetch-mock": "npm:fetch-mock@^12.5.2", + "jsonld": "npm:jsonld@^9.0.0" + }, + "exclude": [ + "dist/", + "node_modules/", + "src/*.yaml", + "!src/vocab.ts" + ], + "tasks": { + "check": "deno fmt --check && deno lint && deno check src/*.ts", + "compile": "deno run --allow-read --allow-write --allow-env --check scripts/codegen.ts && deno fmt src/vocab.ts && deno cache src/vocab.ts && deno check src/vocab.ts", + "test": "deno test --allow-read --allow-write --allow-env --unstable-kv --trace-leaks --parallel" + } +} diff --git a/packages/vocab/package.json b/packages/vocab/package.json new file mode 100644 index 000000000..b357c8b73 --- /dev/null +++ b/packages/vocab/package.json @@ -0,0 +1,80 @@ +{ + "name": "@fedify/vocab", + "version": "2.0.0", + "homepage": "https://fedify.dev/", + "repository": { + "type": "git", + "url": "git+https://github.com/fedify-dev/fedify.git", + "directory": "packages/vocab" + }, + "bugs": { + "url": "https://github.com/fedify-dev/fedify/issues" + }, + "funding": [ + "https://opencollective.com/fedify", + "https://github.com/sponsors/dahlia" + ], + "engines": { + "deno": ">=2.0.0", + "node": ">=22.0.0", + "bun": ">=1.1.0" + }, + "description": "Activity Vocabulary library", + "type": "module", + "main": "./dist/mod.cjs", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", + "exports": { + ".": { + "types": { + "import": "./dist/mod.d.ts", + "require": "./dist/mod.d.cts", + "default": "./dist/mod.d.ts" + }, + "import": "./dist/mod.js", + "require": "./dist/mod.cjs", + "default": "./dist/mod.js" + }, + "./package.json": "./package.json" + }, + "dependencies": { + "@fedify/vocab-tools": "workspace:*", + "@fedify/webfinger": "workspace:*", + "@js-temporal/polyfill": "catalog:", + "@multiformats/base-x": "catalog:", + "@logtape/logtape": "catalog:", + "@opentelemetry/api": "catalog:", + "asn1js": "catalog:", + "es-toolkit": "catalog:", + "jsonld": "^9.0.0", + "multicodec": "^3.2.1", + "pkijs": "catalog:" + }, + "devDependencies": { + "@fedify/fixture": "workspace:*", + "@fedify/vocab-runtime": "workspace:*", + "@types/node": "catalog:", + "fast-check": "catalog:", + "fetch-mock": "catalog:", + "tsdown": "catalog:", + "typescript": "catalog:" + }, + "scripts": { + "build": "tsdown", + "prepack": "pnpm build", + "prepublish": "pnpm build", + "test": "pnpm build && cd dist/ && node --test", + "test:bun": "pnpm build && cd dist/ && bun test --timeout 60000" + }, + "keywords": [ + "Fedify", + "ActivityPub", + "Fediverse" + ], + "author": { + "name": "Hong Minhee", + "email": "hong@minhee.org", + "url": "https://hongminhee.org/" + }, + "license": "MIT" +} diff --git a/packages/fedify/scripts/codegen.ts b/packages/vocab/scripts/codegen.ts similarity index 89% rename from packages/fedify/scripts/codegen.ts rename to packages/vocab/scripts/codegen.ts index 61b740edf..9a178a884 100644 --- a/packages/fedify/scripts/codegen.ts +++ b/packages/vocab/scripts/codegen.ts @@ -7,7 +7,7 @@ async function codegen() { if (!scriptsDir) { throw new Error("Could not determine schema directory"); } - const schemaDir = join(dirname(scriptsDir), "src", "vocab"); + const schemaDir = join(dirname(scriptsDir), "src"); const generatedPath = join(schemaDir, `vocab-${crypto.randomUUID()}.ts`); const realPath = join(schemaDir, "vocab.ts"); diff --git a/packages/fedify/src/vocab/.gitignore b/packages/vocab/src/.gitignore similarity index 100% rename from packages/fedify/src/vocab/.gitignore rename to packages/vocab/src/.gitignore diff --git a/packages/fedify/src/vocab/__snapshots__/vocab.test.ts.snap b/packages/vocab/src/__snapshots__/vocab.test.ts.snap similarity index 100% rename from packages/fedify/src/vocab/__snapshots__/vocab.test.ts.snap rename to packages/vocab/src/__snapshots__/vocab.test.ts.snap diff --git a/packages/fedify/src/vocab/accept.yaml b/packages/vocab/src/accept.yaml similarity index 92% rename from packages/fedify/src/vocab/accept.yaml rename to packages/vocab/src/accept.yaml index 9c574ad73..60ad23cd7 100644 --- a/packages/fedify/src/vocab/accept.yaml +++ b/packages/vocab/src/accept.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Accept compactName: Accept uri: "https://www.w3.org/ns/activitystreams#Accept" diff --git a/packages/fedify/src/vocab/activity.yaml b/packages/vocab/src/activity.yaml similarity index 98% rename from packages/fedify/src/vocab/activity.yaml rename to packages/vocab/src/activity.yaml index 08e4c38da..7a6b46dc0 100644 --- a/packages/fedify/src/vocab/activity.yaml +++ b/packages/vocab/src/activity.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Activity compactName: Activity uri: "https://www.w3.org/ns/activitystreams#Activity" diff --git a/packages/fedify/src/vocab/actor.test.ts b/packages/vocab/src/actor.test.ts similarity index 74% rename from packages/fedify/src/vocab/actor.test.ts rename to packages/vocab/src/actor.test.ts index 1d28c7811..f35e2b6cd 100644 --- a/packages/fedify/src/vocab/actor.test.ts +++ b/packages/vocab/src/actor.test.ts @@ -1,14 +1,13 @@ import { test } from "@fedify/fixture"; -import { - assert, - assertEquals, - assertFalse, - assertRejects, - assertStrictEquals, - assertThrows, -} from "@std/assert"; import * as fc from "fast-check"; import fetchMock from "fetch-mock"; +import { + deepStrictEqual, + ok, + rejects, + strictEqual, + throws, +} from "node:assert/strict"; import { type Actor, getActorClassByTypeName, @@ -52,7 +51,7 @@ function actor(): fc.Arbitrary { } test("isActor()", () => { - fc.assert(fc.property(actor(), (actor) => assert(isActor(actor)))); + fc.assert(fc.property(actor(), (actor) => ok(isActor(actor)))); fc.assert( fc.property( fc.anything({ @@ -66,7 +65,7 @@ test("isActor()", () => { withTypedArray: true, withSparseArray: true, }), - (nonActor) => assertFalse(isActor(nonActor)), + (nonActor) => ok(!isActor(nonActor)), ), ); }); @@ -75,7 +74,8 @@ test("getActorTypeName()", () => { fc.assert( fc.property( actorClassAndInstance(), - ([cls, instance]) => assertEquals(getActorTypeName(instance), cls.name), + ([cls, instance]) => + deepStrictEqual(getActorTypeName(instance), cls.name), ), ); }); @@ -85,7 +85,7 @@ test("getActorClassByTypeName()", () => { fc.property( actorClassAndInstance(), ([cls, instance]) => - assertStrictEquals( + strictEqual( getActorClassByTypeName(getActorTypeName(instance)), cls, ), @@ -114,13 +114,16 @@ test({ }); await t.step("WebFinger subject", async () => { - assertEquals(await getActorHandle(actor), "@johndoe@foo.example.com"); - assertEquals( + deepStrictEqual(await getActorHandle(actor), "@johndoe@foo.example.com"); + deepStrictEqual( await getActorHandle(actor, { trimLeadingAt: true }), "johndoe@foo.example.com", ); - assertEquals(await getActorHandle(actorId), "@johndoe@foo.example.com"); - assertEquals( + deepStrictEqual( + await getActorHandle(actorId), + "@johndoe@foo.example.com", + ); + deepStrictEqual( await getActorHandle(actorId, { trimLeadingAt: true }), "johndoe@foo.example.com", ); @@ -142,13 +145,16 @@ test({ ); await t.step("WebFinger aliases", async () => { - assertEquals(await getActorHandle(actor), "@johndoe@foo.example.com"); - assertEquals( + deepStrictEqual(await getActorHandle(actor), "@johndoe@foo.example.com"); + deepStrictEqual( await getActorHandle(actor, { trimLeadingAt: true }), "johndoe@foo.example.com", ); - assertEquals(await getActorHandle(actorId), "@johndoe@foo.example.com"); - assertEquals( + deepStrictEqual( + await getActorHandle(actorId), + "@johndoe@foo.example.com", + ); + deepStrictEqual( await getActorHandle(actorId, { trimLeadingAt: true }), "johndoe@foo.example.com", ); @@ -168,7 +174,7 @@ test({ ); await t.step("cross-origin WebFinger resources", async () => { - assertEquals(await getActorHandle(actor), "@john@bar.example.com"); + deepStrictEqual(await getActorHandle(actor), "@john@bar.example.com"); }); fetchMock.removeRoutes(); @@ -178,8 +184,8 @@ test({ ); await t.step("no WebFinger", async () => { - assertEquals(await getActorHandle(actor), "@john@foo.example.com"); - assertRejects(() => getActorHandle(actorId), TypeError); + deepStrictEqual(await getActorHandle(actor), "@john@foo.example.com"); + rejects(() => getActorHandle(actorId), TypeError); }); fetchMock.hardReset(); @@ -187,71 +193,71 @@ test({ }); test("normalizeActorHandle()", () => { - assertEquals(normalizeActorHandle("@foo@BAR.COM"), "@foo@bar.com"); - assertEquals(normalizeActorHandle("@BAZ@☃-⌘.com"), "@BAZ@☃-⌘.com"); - assertEquals( + deepStrictEqual(normalizeActorHandle("@foo@BAR.COM"), "@foo@bar.com"); + deepStrictEqual(normalizeActorHandle("@BAZ@☃-⌘.com"), "@BAZ@☃-⌘.com"); + deepStrictEqual( normalizeActorHandle("@qux@xn--maana-pta.com"), "@qux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@XN--MAANA-PTA.COM"), "@quux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@MAÑANA.COM"), "@quux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@foo@BAR.COM", { trimLeadingAt: true }), "foo@bar.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@BAZ@☃-⌘.com", { trimLeadingAt: true }), "BAZ@☃-⌘.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@qux@xn--maana-pta.com", { trimLeadingAt: true }), "qux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@XN--MAANA-PTA.COM", { trimLeadingAt: true }), "quux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@MAÑANA.COM", { trimLeadingAt: true }), "quux@mañana.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@foo@BAR.COM", { punycode: true }), "@foo@bar.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@BAZ@☃-⌘.com", { punycode: true }), "@BAZ@xn----dqo34k.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@qux@xn--maana-pta.com", { punycode: true }), "@qux@xn--maana-pta.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@XN--MAANA-PTA.COM", { punycode: true }), "@quux@xn--maana-pta.com", ); - assertEquals( + deepStrictEqual( normalizeActorHandle("@quux@MAÑANA.COM", { punycode: true }), "@quux@xn--maana-pta.com", ); - assertThrows(() => normalizeActorHandle("")); - assertThrows(() => normalizeActorHandle("@")); - assertThrows(() => normalizeActorHandle("foo")); - assertThrows(() => normalizeActorHandle("@foo")); - assertThrows(() => normalizeActorHandle("@@foo.com")); - assertThrows(() => normalizeActorHandle("@foo@")); - assertThrows(() => normalizeActorHandle("foo@bar.com@baz.com")); - assertThrows(() => normalizeActorHandle("@foo@bar.com@baz.com")); + throws(() => normalizeActorHandle("")); + throws(() => normalizeActorHandle("@")); + throws(() => normalizeActorHandle("foo")); + throws(() => normalizeActorHandle("@foo")); + throws(() => normalizeActorHandle("@@foo.com")); + throws(() => normalizeActorHandle("@foo@")); + throws(() => normalizeActorHandle("foo@bar.com@baz.com")); + throws(() => normalizeActorHandle("@foo@bar.com@baz.com")); }); // cSpell: ignore maana diff --git a/packages/fedify/src/vocab/actor.ts b/packages/vocab/src/actor.ts similarity index 98% rename from packages/fedify/src/vocab/actor.ts rename to packages/vocab/src/actor.ts index cd4de4c83..adf3341f1 100644 --- a/packages/fedify/src/vocab/actor.ts +++ b/packages/vocab/src/actor.ts @@ -1,8 +1,8 @@ import type { GetUserAgentOptions } from "@fedify/vocab-runtime"; +import { lookupWebFinger } from "@fedify/webfinger"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; import { domainToASCII, domainToUnicode } from "node:url"; -import metadata from "../../deno.json" with { type: "json" }; -import { lookupWebFinger } from "../webfinger/lookup.ts"; +import metadata from "../deno.json" with { type: "json" }; import { getTypeId } from "./type.ts"; import { Application, Group, Organization, Person, Service } from "./vocab.ts"; diff --git a/packages/fedify/src/vocab/add.yaml b/packages/vocab/src/add.yaml similarity index 93% rename from packages/fedify/src/vocab/add.yaml rename to packages/vocab/src/add.yaml index ab3a3f06c..62051664e 100644 --- a/packages/fedify/src/vocab/add.yaml +++ b/packages/vocab/src/add.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Add compactName: Add uri: "https://www.w3.org/ns/activitystreams#Add" diff --git a/packages/fedify/src/vocab/announce.yaml b/packages/vocab/src/announce.yaml similarity index 95% rename from packages/fedify/src/vocab/announce.yaml rename to packages/vocab/src/announce.yaml index 8e81f40e5..b36a72e46 100644 --- a/packages/fedify/src/vocab/announce.yaml +++ b/packages/vocab/src/announce.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Announce compactName: Announce uri: "https://www.w3.org/ns/activitystreams#Announce" diff --git a/packages/fedify/src/vocab/application.yaml b/packages/vocab/src/application.yaml similarity index 99% rename from packages/fedify/src/vocab/application.yaml rename to packages/vocab/src/application.yaml index 44d692a47..a82f7e8b3 100644 --- a/packages/fedify/src/vocab/application.yaml +++ b/packages/vocab/src/application.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Application compactName: Application uri: "https://www.w3.org/ns/activitystreams#Application" diff --git a/packages/fedify/src/vocab/arrive.yaml b/packages/vocab/src/arrive.yaml similarity index 93% rename from packages/fedify/src/vocab/arrive.yaml rename to packages/vocab/src/arrive.yaml index 86ed08f91..cf1eb5f65 100644 --- a/packages/fedify/src/vocab/arrive.yaml +++ b/packages/vocab/src/arrive.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Arrive compactName: Arrive uri: "https://www.w3.org/ns/activitystreams#Arrive" diff --git a/packages/fedify/src/vocab/article.yaml b/packages/vocab/src/article.yaml similarity index 97% rename from packages/fedify/src/vocab/article.yaml rename to packages/vocab/src/article.yaml index 92a7bc799..e0f30bd08 100644 --- a/packages/fedify/src/vocab/article.yaml +++ b/packages/vocab/src/article.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Article compactName: Article uri: "https://www.w3.org/ns/activitystreams#Article" diff --git a/packages/fedify/src/vocab/audio.yaml b/packages/vocab/src/audio.yaml similarity index 88% rename from packages/fedify/src/vocab/audio.yaml rename to packages/vocab/src/audio.yaml index b74072f4a..d04fa5572 100644 --- a/packages/fedify/src/vocab/audio.yaml +++ b/packages/vocab/src/audio.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Audio compactName: Audio uri: "https://www.w3.org/ns/activitystreams#Audio" diff --git a/packages/fedify/src/vocab/block.yaml b/packages/vocab/src/block.yaml similarity index 93% rename from packages/fedify/src/vocab/block.yaml rename to packages/vocab/src/block.yaml index 350a1b44a..4fef742ab 100644 --- a/packages/fedify/src/vocab/block.yaml +++ b/packages/vocab/src/block.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Block compactName: Block uri: "https://www.w3.org/ns/activitystreams#Block" diff --git a/packages/fedify/src/vocab/chatmessage.yaml b/packages/vocab/src/chatmessage.yaml similarity index 97% rename from packages/fedify/src/vocab/chatmessage.yaml rename to packages/vocab/src/chatmessage.yaml index 53cb0a407..593b5478c 100644 --- a/packages/fedify/src/vocab/chatmessage.yaml +++ b/packages/vocab/src/chatmessage.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: ChatMessage compactName: ChatMessage uri: "http://litepub.social/ns#ChatMessage" diff --git a/packages/fedify/src/vocab/collection.yaml b/packages/vocab/src/collection.yaml similarity index 99% rename from packages/fedify/src/vocab/collection.yaml rename to packages/vocab/src/collection.yaml index b33172232..11d4db64f 100644 --- a/packages/fedify/src/vocab/collection.yaml +++ b/packages/vocab/src/collection.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Collection compactName: Collection uri: "https://www.w3.org/ns/activitystreams#Collection" diff --git a/packages/fedify/src/vocab/collectionpage.yaml b/packages/vocab/src/collectionpage.yaml similarity index 97% rename from packages/fedify/src/vocab/collectionpage.yaml rename to packages/vocab/src/collectionpage.yaml index dd920e501..396f74521 100644 --- a/packages/fedify/src/vocab/collectionpage.yaml +++ b/packages/vocab/src/collectionpage.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: CollectionPage compactName: CollectionPage uri: "https://www.w3.org/ns/activitystreams#CollectionPage" diff --git a/packages/fedify/src/vocab/constants.ts b/packages/vocab/src/constants.ts similarity index 100% rename from packages/fedify/src/vocab/constants.ts rename to packages/vocab/src/constants.ts diff --git a/packages/fedify/src/vocab/create.yaml b/packages/vocab/src/create.yaml similarity index 95% rename from packages/fedify/src/vocab/create.yaml rename to packages/vocab/src/create.yaml index 28d40a4b5..20d8a4eb2 100644 --- a/packages/fedify/src/vocab/create.yaml +++ b/packages/vocab/src/create.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Create compactName: Create uri: "https://www.w3.org/ns/activitystreams#Create" diff --git a/packages/fedify/src/vocab/dataintegrityproof.yaml b/packages/vocab/src/dataintegrityproof.yaml similarity index 97% rename from packages/fedify/src/vocab/dataintegrityproof.yaml rename to packages/vocab/src/dataintegrityproof.yaml index ad9fd6c07..1cc5ba85b 100644 --- a/packages/fedify/src/vocab/dataintegrityproof.yaml +++ b/packages/vocab/src/dataintegrityproof.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: DataIntegrityProof uri: "https://w3id.org/security#DataIntegrityProof" entity: true diff --git a/packages/fedify/src/vocab/delete.yaml b/packages/vocab/src/delete.yaml similarity index 95% rename from packages/fedify/src/vocab/delete.yaml rename to packages/vocab/src/delete.yaml index f66447545..413014158 100644 --- a/packages/fedify/src/vocab/delete.yaml +++ b/packages/vocab/src/delete.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Delete compactName: Delete uri: "https://www.w3.org/ns/activitystreams#Delete" diff --git a/packages/fedify/src/vocab/didservice.yaml b/packages/vocab/src/didservice.yaml similarity index 94% rename from packages/fedify/src/vocab/didservice.yaml rename to packages/vocab/src/didservice.yaml index ce1b714c9..7260ff145 100644 --- a/packages/fedify/src/vocab/didservice.yaml +++ b/packages/vocab/src/didservice.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: DidService uri: "https://www.w3.org/ns/did#Service" entity: true diff --git a/packages/fedify/src/vocab/dislike.yaml b/packages/vocab/src/dislike.yaml similarity index 91% rename from packages/fedify/src/vocab/dislike.yaml rename to packages/vocab/src/dislike.yaml index 29d4d9d9c..83c50825a 100644 --- a/packages/fedify/src/vocab/dislike.yaml +++ b/packages/vocab/src/dislike.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Dislike compactName: Dislike uri: "https://www.w3.org/ns/activitystreams#Dislike" diff --git a/packages/fedify/src/vocab/document.yaml b/packages/vocab/src/document.yaml similarity index 95% rename from packages/fedify/src/vocab/document.yaml rename to packages/vocab/src/document.yaml index 997afd1ac..c312b55d2 100644 --- a/packages/fedify/src/vocab/document.yaml +++ b/packages/vocab/src/document.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Document compactName: Document uri: "https://www.w3.org/ns/activitystreams#Document" diff --git a/packages/fedify/src/vocab/emoji.yaml b/packages/vocab/src/emoji.yaml similarity index 88% rename from packages/fedify/src/vocab/emoji.yaml rename to packages/vocab/src/emoji.yaml index 9b4362358..811dbdec3 100644 --- a/packages/fedify/src/vocab/emoji.yaml +++ b/packages/vocab/src/emoji.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Emoji compactName: Emoji uri: "http://joinmastodon.org/ns#Emoji" diff --git a/packages/fedify/src/vocab/emojireact.yaml b/packages/vocab/src/emojireact.yaml similarity index 92% rename from packages/fedify/src/vocab/emojireact.yaml rename to packages/vocab/src/emojireact.yaml index 90cffb525..2526e3ae7 100644 --- a/packages/fedify/src/vocab/emojireact.yaml +++ b/packages/vocab/src/emojireact.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: EmojiReact compactName: EmojiReact uri: "http://litepub.social/ns#EmojiReact" diff --git a/packages/fedify/src/vocab/endpoints.yaml b/packages/vocab/src/endpoints.yaml similarity index 98% rename from packages/fedify/src/vocab/endpoints.yaml rename to packages/vocab/src/endpoints.yaml index ef9b04929..1a4bdf86e 100644 --- a/packages/fedify/src/vocab/endpoints.yaml +++ b/packages/vocab/src/endpoints.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Endpoints compactName: as:Endpoints uri: "https://www.w3.org/ns/activitystreams#Endpoints" diff --git a/packages/fedify/src/vocab/event.yaml b/packages/vocab/src/event.yaml similarity index 88% rename from packages/fedify/src/vocab/event.yaml rename to packages/vocab/src/event.yaml index f0fbf1a76..192154e46 100644 --- a/packages/fedify/src/vocab/event.yaml +++ b/packages/vocab/src/event.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Event compactName: Event uri: "https://www.w3.org/ns/activitystreams#Event" diff --git a/packages/fedify/src/vocab/export.yaml b/packages/vocab/src/export.yaml similarity index 83% rename from packages/fedify/src/vocab/export.yaml rename to packages/vocab/src/export.yaml index 952aaade3..c0f1c05c7 100644 --- a/packages/fedify/src/vocab/export.yaml +++ b/packages/vocab/src/export.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Export uri: "https://w3id.org/fep/9091#Export" extends: "https://www.w3.org/ns/did#Service" diff --git a/packages/fedify/src/vocab/flag.yaml b/packages/vocab/src/flag.yaml similarity index 92% rename from packages/fedify/src/vocab/flag.yaml rename to packages/vocab/src/flag.yaml index 73e2a6722..47d8441c2 100644 --- a/packages/fedify/src/vocab/flag.yaml +++ b/packages/vocab/src/flag.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Flag compactName: Flag uri: "https://www.w3.org/ns/activitystreams#Flag" diff --git a/packages/fedify/src/vocab/follow.yaml b/packages/vocab/src/follow.yaml similarity index 94% rename from packages/fedify/src/vocab/follow.yaml rename to packages/vocab/src/follow.yaml index 4c5ef70d5..6e8b4a49d 100644 --- a/packages/fedify/src/vocab/follow.yaml +++ b/packages/vocab/src/follow.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Follow compactName: Follow uri: "https://www.w3.org/ns/activitystreams#Follow" diff --git a/packages/fedify/src/vocab/group.yaml b/packages/vocab/src/group.yaml similarity index 99% rename from packages/fedify/src/vocab/group.yaml rename to packages/vocab/src/group.yaml index afe2aa2ac..a0d3e4d16 100644 --- a/packages/fedify/src/vocab/group.yaml +++ b/packages/vocab/src/group.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Group compactName: Group uri: "https://www.w3.org/ns/activitystreams#Group" diff --git a/packages/fedify/src/vocab/handle.ts b/packages/vocab/src/handle.ts similarity index 100% rename from packages/fedify/src/vocab/handle.ts rename to packages/vocab/src/handle.ts diff --git a/packages/fedify/src/vocab/hashtag.yaml b/packages/vocab/src/hashtag.yaml similarity index 90% rename from packages/fedify/src/vocab/hashtag.yaml rename to packages/vocab/src/hashtag.yaml index f9b924c19..aaf654fd6 100644 --- a/packages/fedify/src/vocab/hashtag.yaml +++ b/packages/vocab/src/hashtag.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Hashtag compactName: Hashtag uri: "https://www.w3.org/ns/activitystreams#Hashtag" diff --git a/packages/fedify/src/vocab/ignore.yaml b/packages/vocab/src/ignore.yaml similarity index 91% rename from packages/fedify/src/vocab/ignore.yaml rename to packages/vocab/src/ignore.yaml index e95afb8bd..142a59ee6 100644 --- a/packages/fedify/src/vocab/ignore.yaml +++ b/packages/vocab/src/ignore.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Ignore compactName: Ignore uri: "https://www.w3.org/ns/activitystreams#Ignore" diff --git a/packages/fedify/src/vocab/image.yaml b/packages/vocab/src/image.yaml similarity index 86% rename from packages/fedify/src/vocab/image.yaml rename to packages/vocab/src/image.yaml index 08940d27d..68ce3ca3c 100644 --- a/packages/fedify/src/vocab/image.yaml +++ b/packages/vocab/src/image.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Image compactName: Image uri: "https://www.w3.org/ns/activitystreams#Image" diff --git a/packages/fedify/src/vocab/intransitiveactivity.yaml b/packages/vocab/src/intransitiveactivity.yaml similarity index 92% rename from packages/fedify/src/vocab/intransitiveactivity.yaml rename to packages/vocab/src/intransitiveactivity.yaml index 97e0c30f4..7119e99e3 100644 --- a/packages/fedify/src/vocab/intransitiveactivity.yaml +++ b/packages/vocab/src/intransitiveactivity.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: IntransitiveActivity compactName: IntransitiveActivity uri: "https://www.w3.org/ns/activitystreams#IntransitiveActivity" diff --git a/packages/fedify/src/vocab/invite.yaml b/packages/vocab/src/invite.yaml similarity index 91% rename from packages/fedify/src/vocab/invite.yaml rename to packages/vocab/src/invite.yaml index 466503ab0..eac1e5e17 100644 --- a/packages/fedify/src/vocab/invite.yaml +++ b/packages/vocab/src/invite.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Invite compactName: Invite uri: "https://www.w3.org/ns/activitystreams#Invite" diff --git a/packages/fedify/src/vocab/join.yaml b/packages/vocab/src/join.yaml similarity index 91% rename from packages/fedify/src/vocab/join.yaml rename to packages/vocab/src/join.yaml index aa4e828c8..8cb76af4a 100644 --- a/packages/fedify/src/vocab/join.yaml +++ b/packages/vocab/src/join.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Join compactName: Join uri: "https://www.w3.org/ns/activitystreams#Join" diff --git a/packages/fedify/src/vocab/key.yaml b/packages/vocab/src/key.yaml similarity index 95% rename from packages/fedify/src/vocab/key.yaml rename to packages/vocab/src/key.yaml index 50b074e50..959fe403a 100644 --- a/packages/fedify/src/vocab/key.yaml +++ b/packages/vocab/src/key.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: CryptographicKey compactName: CryptographicKey uri: "https://w3id.org/security#Key" diff --git a/packages/vocab/src/keys.ts b/packages/vocab/src/keys.ts new file mode 100644 index 000000000..e6378a01b --- /dev/null +++ b/packages/vocab/src/keys.ts @@ -0,0 +1,50 @@ +import { CryptographicKey } from "./vocab.ts"; + +export const ed25519PublicKey = new CryptographicKey({ + id: new URL("https://example.com/person2#key4"), + owner: new URL("https://example.com/person2"), + publicKey: await crypto.subtle.importKey( + "jwk", + { + crv: "Ed25519", + ext: true, + key_ops: ["verify"], + kty: "OKP", + // cSpell: disable + x: "LR8epAGDe-cVq5p2Tx49CCfphpk1rNhkNoY9i-XEUfg", + // cSpell: enable + }, + "Ed25519", + true, + ["verify"], + ), +}) as CryptographicKey & { publicKey: CryptoKey }; + +export const rsaPublicKey = new CryptographicKey({ + id: new URL("https://example.com/key"), + owner: new URL("https://example.com/person"), + publicKey: await crypto.subtle.importKey( + "jwk", + { + kty: "RSA", + alg: "RS256", + // cSpell: disable + n: "yIB9rotX8G6r6_6toT-x24BUiQ_HaPH1Em9dOt4c94s-OPFoEdH7DY7Iym9A8Ll" + + "H4JaGF8KD38bLHWe1S4x0jV3gHJKhK7veJfGZCKUENcQecBZ-YWUs5HWvUIX1vVB" + + "__0luHrg6BQKGOrSOE-WIAxyr0qsWCFfZzQrvSnUD2yvg1arJX2xhms14uxoRd5K" + + "g9efKSCmmQaNEapicARUmFWrIEpGFa_nUUnqimssAGw1eZFqf3wA4TjhsuARBhGa" + + "Jtv_3KEa016eMZxy3kDlOjZnXZTaTgWkXdodwUvy8563fes3Al6BlcS2iJ9qbtha" + + "8rSm0FHqoUKH73JsLPKQIwQ", + e: "AQAB", + // cSpell: enable + key_ops: ["verify"], + ext: true, + }, + { + name: "RSASSA-PKCS1-v1_5", + hash: "SHA-256", + }, + true, + ["verify"], + ), +}) as CryptographicKey & { publicKey: CryptoKey }; diff --git a/packages/fedify/src/vocab/leave.yaml b/packages/vocab/src/leave.yaml similarity index 91% rename from packages/fedify/src/vocab/leave.yaml rename to packages/vocab/src/leave.yaml index 827924aee..272324fff 100644 --- a/packages/fedify/src/vocab/leave.yaml +++ b/packages/vocab/src/leave.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Leave compactName: Leave uri: "https://www.w3.org/ns/activitystreams#Leave" diff --git a/packages/fedify/src/vocab/like.yaml b/packages/vocab/src/like.yaml similarity index 92% rename from packages/fedify/src/vocab/like.yaml rename to packages/vocab/src/like.yaml index 19efd5f35..163394fa8 100644 --- a/packages/fedify/src/vocab/like.yaml +++ b/packages/vocab/src/like.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Like compactName: Like uri: "https://www.w3.org/ns/activitystreams#Like" diff --git a/packages/fedify/src/vocab/link.yaml b/packages/vocab/src/link.yaml similarity index 98% rename from packages/fedify/src/vocab/link.yaml rename to packages/vocab/src/link.yaml index 8aede59f6..ae1127b5b 100644 --- a/packages/fedify/src/vocab/link.yaml +++ b/packages/vocab/src/link.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Link compactName: Link uri: "https://www.w3.org/ns/activitystreams#Link" diff --git a/packages/fedify/src/vocab/listen.yaml b/packages/vocab/src/listen.yaml similarity index 90% rename from packages/fedify/src/vocab/listen.yaml rename to packages/vocab/src/listen.yaml index a718b2788..688d20453 100644 --- a/packages/fedify/src/vocab/listen.yaml +++ b/packages/vocab/src/listen.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Listen compactName: Listen uri: "https://www.w3.org/ns/activitystreams#Listen" diff --git a/packages/fedify/src/vocab/lookup.test.ts b/packages/vocab/src/lookup.test.ts similarity index 91% rename from packages/fedify/src/vocab/lookup.test.ts rename to packages/vocab/src/lookup.test.ts index e245dd4fb..0f8fc0b69 100644 --- a/packages/fedify/src/vocab/lookup.test.ts +++ b/packages/vocab/src/lookup.test.ts @@ -3,14 +3,10 @@ import { mockDocumentLoader, test, } from "@fedify/fixture"; -import { - assert, - assertEquals, - assertInstanceOf, - assertRejects, -} from "@std/assert"; import fetchMock from "fetch-mock"; +import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict"; import { lookupObject, traverseCollection } from "./lookup.ts"; +import { assertInstanceOf } from "./utils.ts"; import { Collection, Note, Object, Person } from "./vocab.ts"; test("lookupObject()", { @@ -51,18 +47,18 @@ test("lookupObject()", { await t.step("actor", async () => { const person = await lookupObject("@johndoe@example.com", options); assertInstanceOf(person, Person); - assertEquals(person.id, new URL("https://example.com/person")); - assertEquals(person.name, "John Doe"); + deepStrictEqual(person.id, new URL("https://example.com/person")); + equal(person.name, "John Doe"); const person2 = await lookupObject("johndoe@example.com", options); - assertEquals(person2, person); + deepStrictEqual(person2, person); const person3 = await lookupObject("acct:johndoe@example.com", options); - assertEquals(person3, person); + deepStrictEqual(person3, person); }); await t.step("object", async () => { const object = await lookupObject("https://example.com/object", options); assertInstanceOf(object, Object); - assertEquals( + deepStrictEqual( object, new Object({ id: new URL("https://example.com/object"), @@ -74,7 +70,7 @@ test("lookupObject()", { options, ); assertInstanceOf(person, Person); - assertEquals( + deepStrictEqual( person, new Person({ id: new URL("https://example.com/hong-gildong"), @@ -96,8 +92,11 @@ test("lookupObject()", { }); await t.step("not found", async () => { - assertEquals(await lookupObject("janedoe@example.com", options), null); - assertEquals(await lookupObject("https://example.com/404", options), null); + deepStrictEqual(await lookupObject("janedoe@example.com", options), null); + deepStrictEqual( + await lookupObject("https://example.com/404", options), + null, + ); }); fetchMock.removeRoutes(); @@ -128,7 +127,7 @@ test("lookupObject()", { }); controller.abort(); - assertEquals(await promise, null); + deepStrictEqual(await promise, null); }); fetchMock.removeRoutes(); @@ -153,7 +152,7 @@ test("lookupObject()", { signal: controller.signal, }); assertInstanceOf(person, Person); - assertEquals(person.id, new URL("https://example.com/person")); + deepStrictEqual(person.id, new URL("https://example.com/person")); }); fetchMock.removeRoutes(); @@ -184,7 +183,7 @@ test("lookupObject()", { ...options, signal: controller.signal, }); - assertEquals(result, null); + deepStrictEqual(result, null); }); fetchMock.removeRoutes(); @@ -214,7 +213,7 @@ test("lookupObject()", { }); controller.abort(); - assertEquals(await promise, null); + deepStrictEqual(await promise, null); }); fetchMock.hardReset(); @@ -234,7 +233,7 @@ test("traverseCollection()", { options, ); assertInstanceOf(collection, Collection); - assertEquals( + deepStrictEqual( await Array.fromAsync(traverseCollection(collection, options)), [ new Note({ content: "This is a simple note" }), @@ -247,7 +246,7 @@ test("traverseCollection()", { options, ); assertInstanceOf(pagedCollection, Collection); - assertEquals( + deepStrictEqual( await Array.fromAsync(traverseCollection(pagedCollection, options)), [ new Note({ content: "This is a simple note" }), @@ -255,7 +254,7 @@ test("traverseCollection()", { new Note({ content: "This is a third simple note" }), ], ); - assertEquals( + deepStrictEqual( await Array.fromAsync( traverseCollection(pagedCollection, { ...options, @@ -301,7 +300,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { }); // Should return null and log a warning (default behavior) - assertEquals(result, null); + deepStrictEqual(result, null); }, ); @@ -325,7 +324,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { throw new Error(`Unexpected URL: ${url}`); }; - await assertRejects( + await rejects( () => lookupObject("https://example.com/note", { documentLoader: crossOriginDocumentLoader, @@ -363,8 +362,8 @@ test("FEP-fe34: lookupObject() cross-origin security", { }); assertInstanceOf(result, Note); - assertEquals(result.id, new URL("https://malicious.com/fake-note")); - assertEquals( + deepStrictEqual(result.id, new URL("https://malicious.com/fake-note")); + deepStrictEqual( result.content, "This is a spoofed note from a different origin", ); @@ -394,8 +393,8 @@ test("FEP-fe34: lookupObject() cross-origin security", { }); assertInstanceOf(result, Note); - assertEquals(result.id, new URL("https://example.com/note")); - assertEquals( + deepStrictEqual(result.id, new URL("https://example.com/note")); + deepStrictEqual( result.content, "This is a legitimate note from the same origin", ); @@ -425,8 +424,8 @@ test("FEP-fe34: lookupObject() cross-origin security", { }); assertInstanceOf(result, Note); - assertEquals(result.id, null); - assertEquals(result.content, "This is a note without an ID"); + deepStrictEqual(result.id, null); + deepStrictEqual(result.content, "This is a note without an ID"); }); await t.step("WebFinger lookup with cross-origin actor URL", async () => { @@ -467,10 +466,10 @@ test("FEP-fe34: lookupObject() cross-origin security", { documentLoader: webfingerDocumentLoader, contextLoader: mockDocumentLoader, }); - assertEquals(result1, null); + deepStrictEqual(result1, null); // With crossOrigin: throw, should throw error - await assertRejects( + await rejects( () => lookupObject("@user@example.com", { documentLoader: webfingerDocumentLoader, @@ -488,7 +487,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { crossOrigin: "trust", }); assertInstanceOf(result2, Person); - assertEquals(result2.id, new URL("https://malicious.com/fake-actor")); + deepStrictEqual(result2.id, new URL("https://malicious.com/fake-actor")); fetchMock.removeRoutes(); fetchMock.hardReset(); @@ -518,7 +517,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { contextLoader: mockDocumentLoader, }); - assertEquals(result, null); // Should be blocked + deepStrictEqual(result, null); // Should be blocked }); await t.step("different port same-origin check", async () => { @@ -545,7 +544,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { contextLoader: mockDocumentLoader, }); - assertEquals(result, null); // Should be blocked + deepStrictEqual(result, null); // Should be blocked }); await t.step("protocol difference same-origin check", async () => { @@ -572,7 +571,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { contextLoader: mockDocumentLoader, }); - assertEquals(result, null); // Should be blocked + deepStrictEqual(result, null); // Should be blocked }); await t.step("error handling with crossOrigin throw option", async () => { @@ -591,7 +590,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { // Should return null because the document loader failed, // not because of cross-origin policy - assertEquals(result, null); + deepStrictEqual(result, null); }); await t.step("malformed JSON handling with cross-origin policy", async () => { @@ -608,7 +607,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { }; // Should return null for malformed JSON regardless of crossOrigin setting - assertEquals( + deepStrictEqual( await lookupObject("https://example.com/note", { documentLoader: malformedJsonDocumentLoader, contextLoader: mockDocumentLoader, @@ -617,7 +616,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { null, ); - assertEquals( + deepStrictEqual( await lookupObject("https://example.com/note", { documentLoader: malformedJsonDocumentLoader, contextLoader: mockDocumentLoader, @@ -626,7 +625,7 @@ test("FEP-fe34: lookupObject() cross-origin security", { null, ); - assertEquals( + deepStrictEqual( await lookupObject("https://example.com/note", { documentLoader: malformedJsonDocumentLoader, contextLoader: mockDocumentLoader, @@ -650,11 +649,11 @@ test("lookupObject() records OpenTelemetry span events", async () => { // Check that the span was recorded const spans = exporter.getSpans("activitypub.lookup_object"); - assertEquals(spans.length, 1); + deepStrictEqual(spans.length, 1); const span = spans[0]; // Check span attributes - assertEquals( + deepStrictEqual( span.attributes["activitypub.object.id"], "https://example.com/object", ); @@ -664,19 +663,19 @@ test("lookupObject() records OpenTelemetry span events", async () => { "activitypub.lookup_object", "activitypub.object.fetched", ); - assertEquals(events.length, 1); + deepStrictEqual(events.length, 1); const event = events[0]; // Verify event attributes - assert(event.attributes != null); - assert(typeof event.attributes["activitypub.object.type"] === "string"); - assert(typeof event.attributes["activitypub.object.json"] === "string"); + ok(event.attributes != null); + ok(typeof event.attributes["activitypub.object.type"] === "string"); + ok(typeof event.attributes["activitypub.object.json"] === "string"); // Verify the JSON contains the object const recordedObject = JSON.parse( event.attributes["activitypub.object.json"] as string, ); - assertEquals(recordedObject.id, "https://example.com/object"); + deepStrictEqual(recordedObject.id, "https://example.com/object"); }); // cSpell: ignore gildong diff --git a/packages/fedify/src/vocab/lookup.ts b/packages/vocab/src/lookup.ts similarity index 98% rename from packages/fedify/src/vocab/lookup.ts rename to packages/vocab/src/lookup.ts index 85ac8752b..2089ce59d 100644 --- a/packages/fedify/src/vocab/lookup.ts +++ b/packages/vocab/src/lookup.ts @@ -4,11 +4,11 @@ import { getDocumentLoader, type RemoteDocument, } from "@fedify/vocab-runtime"; +import { lookupWebFinger } from "@fedify/webfinger"; import { getLogger } from "@logtape/logtape"; import { SpanStatusCode, trace, type TracerProvider } from "@opentelemetry/api"; import { delay } from "es-toolkit"; -import metadata from "../../deno.json" with { type: "json" }; -import { lookupWebFinger } from "../webfinger/lookup.ts"; +import metadata from "../deno.json" with { type: "json" }; import { toAcctUrl } from "./handle.ts"; import { getTypeId } from "./type.ts"; import { type Collection, type Link, Object } from "./vocab.ts"; diff --git a/packages/fedify/src/vocab/mention.yaml b/packages/vocab/src/mention.yaml similarity index 87% rename from packages/fedify/src/vocab/mention.yaml rename to packages/vocab/src/mention.yaml index a3dd2326e..e714fa16a 100644 --- a/packages/fedify/src/vocab/mention.yaml +++ b/packages/vocab/src/mention.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Mention compactName: Mention uri: "https://www.w3.org/ns/activitystreams#Mention" diff --git a/packages/fedify/src/vocab/mod.ts b/packages/vocab/src/mod.ts similarity index 100% rename from packages/fedify/src/vocab/mod.ts rename to packages/vocab/src/mod.ts diff --git a/packages/fedify/src/vocab/move.yaml b/packages/vocab/src/move.yaml similarity index 91% rename from packages/fedify/src/vocab/move.yaml rename to packages/vocab/src/move.yaml index e1de3dcaf..633a2892e 100644 --- a/packages/fedify/src/vocab/move.yaml +++ b/packages/vocab/src/move.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Move compactName: Move uri: "https://www.w3.org/ns/activitystreams#Move" diff --git a/packages/fedify/src/vocab/multikey.yaml b/packages/vocab/src/multikey.yaml similarity index 96% rename from packages/fedify/src/vocab/multikey.yaml rename to packages/vocab/src/multikey.yaml index ff6055034..9f8ffbc63 100644 --- a/packages/fedify/src/vocab/multikey.yaml +++ b/packages/vocab/src/multikey.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Multikey compactName: Multikey uri: "https://w3id.org/security#Multikey" diff --git a/packages/fedify/src/vocab/note.yaml b/packages/vocab/src/note.yaml similarity index 97% rename from packages/fedify/src/vocab/note.yaml rename to packages/vocab/src/note.yaml index 4b474c230..06927ba7d 100644 --- a/packages/fedify/src/vocab/note.yaml +++ b/packages/vocab/src/note.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Note compactName: Note uri: "https://www.w3.org/ns/activitystreams#Note" diff --git a/packages/fedify/src/vocab/object.yaml b/packages/vocab/src/object.yaml similarity index 99% rename from packages/fedify/src/vocab/object.yaml rename to packages/vocab/src/object.yaml index 28a488b8e..627f0c388 100644 --- a/packages/fedify/src/vocab/object.yaml +++ b/packages/vocab/src/object.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Object compactName: Object uri: "https://www.w3.org/ns/activitystreams#Object" diff --git a/packages/fedify/src/vocab/offer.yaml b/packages/vocab/src/offer.yaml similarity index 91% rename from packages/fedify/src/vocab/offer.yaml rename to packages/vocab/src/offer.yaml index c04c45e12..a1658bb45 100644 --- a/packages/fedify/src/vocab/offer.yaml +++ b/packages/vocab/src/offer.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Offer compactName: Offer uri: "https://www.w3.org/ns/activitystreams#Offer" diff --git a/packages/fedify/src/vocab/orderedcollection.yaml b/packages/vocab/src/orderedcollection.yaml similarity index 96% rename from packages/fedify/src/vocab/orderedcollection.yaml rename to packages/vocab/src/orderedcollection.yaml index 3d5399315..38da7dc0a 100644 --- a/packages/fedify/src/vocab/orderedcollection.yaml +++ b/packages/vocab/src/orderedcollection.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: OrderedCollection compactName: OrderedCollection uri: "https://www.w3.org/ns/activitystreams#OrderedCollection" diff --git a/packages/fedify/src/vocab/orderedcollectionpage.yaml b/packages/vocab/src/orderedcollectionpage.yaml similarity index 97% rename from packages/fedify/src/vocab/orderedcollectionpage.yaml rename to packages/vocab/src/orderedcollectionpage.yaml index 5e372e282..31ef53148 100644 --- a/packages/fedify/src/vocab/orderedcollectionpage.yaml +++ b/packages/vocab/src/orderedcollectionpage.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: OrderedCollectionPage compactName: OrderedCollectionPage uri: "https://www.w3.org/ns/activitystreams#OrderedCollectionPage" diff --git a/packages/fedify/src/vocab/organization.yaml b/packages/vocab/src/organization.yaml similarity index 99% rename from packages/fedify/src/vocab/organization.yaml rename to packages/vocab/src/organization.yaml index afc78adbb..ab47bd162 100644 --- a/packages/fedify/src/vocab/organization.yaml +++ b/packages/vocab/src/organization.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Organization compactName: Organization uri: "https://www.w3.org/ns/activitystreams#Organization" diff --git a/packages/fedify/src/vocab/page.yaml b/packages/vocab/src/page.yaml similarity index 87% rename from packages/fedify/src/vocab/page.yaml rename to packages/vocab/src/page.yaml index 5ef06f4b9..c3ee9fb80 100644 --- a/packages/fedify/src/vocab/page.yaml +++ b/packages/vocab/src/page.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Page compactName: Page uri: "https://www.w3.org/ns/activitystreams#Page" diff --git a/packages/fedify/src/vocab/person.yaml b/packages/vocab/src/person.yaml similarity index 99% rename from packages/fedify/src/vocab/person.yaml rename to packages/vocab/src/person.yaml index 1fccfbefb..044896452 100644 --- a/packages/fedify/src/vocab/person.yaml +++ b/packages/vocab/src/person.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Person compactName: Person uri: "https://www.w3.org/ns/activitystreams#Person" diff --git a/packages/fedify/src/vocab/place.yaml b/packages/vocab/src/place.yaml similarity index 98% rename from packages/fedify/src/vocab/place.yaml rename to packages/vocab/src/place.yaml index 66b0354ef..a4ee078a2 100644 --- a/packages/fedify/src/vocab/place.yaml +++ b/packages/vocab/src/place.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Place compactName: Place uri: "https://www.w3.org/ns/activitystreams#Place" diff --git a/packages/fedify/src/vocab/profile.yaml b/packages/vocab/src/profile.yaml similarity index 95% rename from packages/fedify/src/vocab/profile.yaml rename to packages/vocab/src/profile.yaml index a3597d8bb..dbaca6066 100644 --- a/packages/fedify/src/vocab/profile.yaml +++ b/packages/vocab/src/profile.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Profile compactName: Profile uri: "https://www.w3.org/ns/activitystreams#Profile" diff --git a/packages/fedify/src/vocab/propertyvalue.yaml b/packages/vocab/src/propertyvalue.yaml similarity index 95% rename from packages/fedify/src/vocab/propertyvalue.yaml rename to packages/vocab/src/propertyvalue.yaml index 524aadb58..dcdef5784 100644 --- a/packages/fedify/src/vocab/propertyvalue.yaml +++ b/packages/vocab/src/propertyvalue.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: PropertyValue compactName: PropertyValue # The below URI intentionally lacks a path slash due to Mastodon's mistake: diff --git a/packages/fedify/src/vocab/question.yaml b/packages/vocab/src/question.yaml similarity index 98% rename from packages/fedify/src/vocab/question.yaml rename to packages/vocab/src/question.yaml index 959f9bfac..0ec71ceb8 100644 --- a/packages/fedify/src/vocab/question.yaml +++ b/packages/vocab/src/question.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Question compactName: Question uri: "https://www.w3.org/ns/activitystreams#Question" diff --git a/packages/fedify/src/vocab/read.yaml b/packages/vocab/src/read.yaml similarity index 89% rename from packages/fedify/src/vocab/read.yaml rename to packages/vocab/src/read.yaml index 4b2a79cce..6fc2ec69a 100644 --- a/packages/fedify/src/vocab/read.yaml +++ b/packages/vocab/src/read.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Read compactName: Read uri: "https://www.w3.org/ns/activitystreams#Read" diff --git a/packages/fedify/src/vocab/reject.yaml b/packages/vocab/src/reject.yaml similarity index 91% rename from packages/fedify/src/vocab/reject.yaml rename to packages/vocab/src/reject.yaml index d470877bf..1d584f609 100644 --- a/packages/fedify/src/vocab/reject.yaml +++ b/packages/vocab/src/reject.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Reject compactName: Reject uri: "https://www.w3.org/ns/activitystreams#Reject" diff --git a/packages/fedify/src/vocab/relationship.yaml b/packages/vocab/src/relationship.yaml similarity index 97% rename from packages/fedify/src/vocab/relationship.yaml rename to packages/vocab/src/relationship.yaml index 00b9cf0e5..aceb726ce 100644 --- a/packages/fedify/src/vocab/relationship.yaml +++ b/packages/vocab/src/relationship.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Relationship compactName: Relationship uri: "https://www.w3.org/ns/activitystreams#Relationship" diff --git a/packages/fedify/src/vocab/remove.yaml b/packages/vocab/src/remove.yaml similarity index 91% rename from packages/fedify/src/vocab/remove.yaml rename to packages/vocab/src/remove.yaml index d6f67dd60..c3daf58e3 100644 --- a/packages/fedify/src/vocab/remove.yaml +++ b/packages/vocab/src/remove.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Remove compactName: Remove uri: "https://www.w3.org/ns/activitystreams#Remove" diff --git a/packages/fedify/src/vocab/service.yaml b/packages/vocab/src/service.yaml similarity index 99% rename from packages/fedify/src/vocab/service.yaml rename to packages/vocab/src/service.yaml index 596f39cf7..52f00ca90 100644 --- a/packages/fedify/src/vocab/service.yaml +++ b/packages/vocab/src/service.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Service compactName: Service uri: "https://www.w3.org/ns/activitystreams#Service" diff --git a/packages/fedify/src/vocab/source.yaml b/packages/vocab/src/source.yaml similarity index 94% rename from packages/fedify/src/vocab/source.yaml rename to packages/vocab/src/source.yaml index 86624e735..1b6f4262a 100644 --- a/packages/fedify/src/vocab/source.yaml +++ b/packages/vocab/src/source.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Source compactName: as:Source uri: "https://www.w3.org/ns/activitystreams#Source" diff --git a/packages/fedify/src/vocab/tentativeaccept.yaml b/packages/vocab/src/tentativeaccept.yaml similarity index 91% rename from packages/fedify/src/vocab/tentativeaccept.yaml rename to packages/vocab/src/tentativeaccept.yaml index e7dd2f768..f0bc798b3 100644 --- a/packages/fedify/src/vocab/tentativeaccept.yaml +++ b/packages/vocab/src/tentativeaccept.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: TentativeAccept compactName: TentativeAccept uri: "https://www.w3.org/ns/activitystreams#TentativeAccept" diff --git a/packages/fedify/src/vocab/tentativereject.yaml b/packages/vocab/src/tentativereject.yaml similarity index 91% rename from packages/fedify/src/vocab/tentativereject.yaml rename to packages/vocab/src/tentativereject.yaml index b03fc45c1..6d29b0186 100644 --- a/packages/fedify/src/vocab/tentativereject.yaml +++ b/packages/vocab/src/tentativereject.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: TentativeReject compactName: TentativeReject uri: "https://www.w3.org/ns/activitystreams#TentativeReject" diff --git a/packages/fedify/src/vocab/tombstone.yaml b/packages/vocab/src/tombstone.yaml similarity index 94% rename from packages/fedify/src/vocab/tombstone.yaml rename to packages/vocab/src/tombstone.yaml index 8ee90e3ef..573c71beb 100644 --- a/packages/fedify/src/vocab/tombstone.yaml +++ b/packages/vocab/src/tombstone.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Tombstone compactName: Tombstone uri: "https://www.w3.org/ns/activitystreams#Tombstone" diff --git a/packages/fedify/src/vocab/travel.yaml b/packages/vocab/src/travel.yaml similarity index 93% rename from packages/fedify/src/vocab/travel.yaml rename to packages/vocab/src/travel.yaml index 73626b35b..cc451d7c6 100644 --- a/packages/fedify/src/vocab/travel.yaml +++ b/packages/vocab/src/travel.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Travel compactName: Travel uri: "https://www.w3.org/ns/activitystreams#Travel" diff --git a/packages/fedify/src/vocab/type.test.ts b/packages/vocab/src/type.test.ts similarity index 64% rename from packages/fedify/src/vocab/type.test.ts rename to packages/vocab/src/type.test.ts index 3fc4b2e56..21c3ce939 100644 --- a/packages/fedify/src/vocab/type.test.ts +++ b/packages/vocab/src/type.test.ts @@ -1,20 +1,20 @@ import { test } from "@fedify/fixture"; -import { assertEquals } from "@std/assert/assert-equals"; +import { deepStrictEqual } from "node:assert/strict"; import { getTypeId } from "./type.ts"; import { Person } from "./vocab.ts"; test("getTypeId()", () => { const obj = new Person({}); - assertEquals( + deepStrictEqual( getTypeId(obj), new URL("https://www.w3.org/ns/activitystreams#Person"), ); const obj2: Person | null = null; - assertEquals(getTypeId(obj2), null); + deepStrictEqual(getTypeId(obj2), null); const obj3: Person | undefined = undefined; - assertEquals(getTypeId(obj3), undefined); + deepStrictEqual(getTypeId(obj3), undefined); const obj4: Person | null | undefined = null; - assertEquals(getTypeId(obj4), null); + deepStrictEqual(getTypeId(obj4), null); const obj5: Person | null | undefined = undefined; - assertEquals(getTypeId(obj5), undefined); + deepStrictEqual(getTypeId(obj5), undefined); }); diff --git a/packages/fedify/src/vocab/type.ts b/packages/vocab/src/type.ts similarity index 100% rename from packages/fedify/src/vocab/type.ts rename to packages/vocab/src/type.ts diff --git a/packages/fedify/src/vocab/undo.yaml b/packages/vocab/src/undo.yaml similarity index 95% rename from packages/fedify/src/vocab/undo.yaml rename to packages/vocab/src/undo.yaml index 754876940..14d60ee1c 100644 --- a/packages/fedify/src/vocab/undo.yaml +++ b/packages/vocab/src/undo.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Undo compactName: Undo uri: "https://www.w3.org/ns/activitystreams#Undo" diff --git a/packages/fedify/src/vocab/update.yaml b/packages/vocab/src/update.yaml similarity index 97% rename from packages/fedify/src/vocab/update.yaml rename to packages/vocab/src/update.yaml index 6b5b17b25..07683edfa 100644 --- a/packages/fedify/src/vocab/update.yaml +++ b/packages/vocab/src/update.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Update compactName: Update uri: "https://www.w3.org/ns/activitystreams#Update" diff --git a/packages/vocab/src/utils.ts b/packages/vocab/src/utils.ts new file mode 100644 index 000000000..5185907b4 --- /dev/null +++ b/packages/vocab/src/utils.ts @@ -0,0 +1,9 @@ +import { ok } from "node:assert"; + +export function assertInstanceOf( + value: unknown, + // deno-lint-ignore no-explicit-any + constructor: new (...args: any[]) => T, +): asserts value is T { + ok(value instanceof constructor); +} diff --git a/packages/fedify/src/vocab/video.yaml b/packages/vocab/src/video.yaml similarity index 88% rename from packages/fedify/src/vocab/video.yaml rename to packages/vocab/src/video.yaml index 978f4b6c0..f9fc74045 100644 --- a/packages/fedify/src/vocab/video.yaml +++ b/packages/vocab/src/video.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: Video compactName: Video uri: "https://www.w3.org/ns/activitystreams#Video" diff --git a/packages/fedify/src/vocab/view.yaml b/packages/vocab/src/view.yaml similarity index 89% rename from packages/fedify/src/vocab/view.yaml rename to packages/vocab/src/view.yaml index d16e59409..2778acbe2 100644 --- a/packages/fedify/src/vocab/view.yaml +++ b/packages/vocab/src/view.yaml @@ -1,4 +1,4 @@ -$schema: ../../../vocab-tools/schema.yaml +$schema: ../../vocab-tools/schema.yaml name: View compactName: View uri: "https://www.w3.org/ns/activitystreams#View" diff --git a/packages/fedify/src/vocab/vocab.bench.ts b/packages/vocab/src/vocab.bench.ts similarity index 100% rename from packages/fedify/src/vocab/vocab.bench.ts rename to packages/vocab/src/vocab.bench.ts diff --git a/packages/fedify/src/vocab/vocab.test.ts b/packages/vocab/src/vocab.test.ts similarity index 75% rename from packages/fedify/src/vocab/vocab.test.ts rename to packages/vocab/src/vocab.test.ts index cd502ea1b..a7eb026ce 100644 --- a/packages/fedify/src/vocab/vocab.test.ts +++ b/packages/vocab/src/vocab.test.ts @@ -6,17 +6,15 @@ import { type PropertySchema, type TypeSchema, } from "@fedify/vocab-tools"; -import { - assert, - assertEquals, - assertFalse, - assertInstanceOf, - assertNotEquals, - assertRejects, - assertThrows, -} from "@std/assert"; import { pascalCase } from "es-toolkit"; -import { ed25519PublicKey, rsaPublicKey1 } from "../testing/keys.ts"; +import { + deepStrictEqual, + notDeepStrictEqual, + ok, + rejects, + throws, +} from "node:assert/strict"; +import { assertInstanceOf } from "./utils.ts"; import * as vocab from "./vocab.ts"; import { Activity, @@ -45,34 +43,29 @@ test("new Object()", () => { new LanguageString("你好", "zh"), ], }); - assertEquals(obj.name, "Test"); - assertEquals(obj.contents[0], new LanguageString("Hello", "en")); - assertEquals(obj.contents[1], new LanguageString("你好", "zh")); + deepStrictEqual(obj.name, "Test"); + deepStrictEqual(obj.contents[0], new LanguageString("Hello", "en")); + deepStrictEqual(obj.contents[1], new LanguageString("你好", "zh")); - assertThrows( + throws( () => new Object({ id: 123 as unknown as URL }), TypeError, - "The id must be a URL.", ); - assertThrows( + throws( () => new Object({ name: "singular", names: ["plural"] }), TypeError, - "Cannot initialize both name and names at the same time.", ); - assertThrows( + throws( () => new Object({ name: 123 as unknown as string }), TypeError, - "The name must be of type string | LanguageString.", ); - assertThrows( + throws( () => new Object({ names: "foo" as unknown as string[] }), TypeError, - "The names must be an array of type string | LanguageString.", ); - assertThrows( + throws( () => new Object({ names: ["foo", 123 as unknown as string] }), TypeError, - "The names must be an array of type string | LanguageString.", ); }); @@ -88,43 +81,38 @@ test("Object.clone()", () => { const clone = obj.clone({ content: "Modified" }); assertInstanceOf(clone, Object); - assertEquals(clone.id, new URL("https://example.com/")); - assertEquals(clone.name, "Test"); - assertEquals(clone.content, "Modified"); + deepStrictEqual(clone.id, new URL("https://example.com/")); + deepStrictEqual(clone.name, "Test"); + deepStrictEqual(clone.content, "Modified"); const cloned2 = obj.clone({ id: new URL("https://example.com/modified") }); assertInstanceOf(cloned2, Object); - assertEquals(cloned2.id, new URL("https://example.com/modified")); - assertEquals(cloned2.name, "Test"); - assertEquals(cloned2.contents, [ + deepStrictEqual(cloned2.id, new URL("https://example.com/modified")); + deepStrictEqual(cloned2.name, "Test"); + deepStrictEqual(cloned2.contents, [ new LanguageString("Hello", "en"), new LanguageString("你好", "zh"), ]); - assertThrows( + throws( () => obj.clone({ id: 123 as unknown as URL }), TypeError, - "The id must be a URL.", ); - assertThrows( + throws( () => obj.clone({ name: "singular", names: ["plural"] }), TypeError, - "Cannot update both name and names at the same time.", ); - assertThrows( + throws( () => obj.clone({ name: 123 as unknown as string }), TypeError, - "The name must be of type string | LanguageString.", ); - assertThrows( + throws( () => obj.clone({ names: "foo" as unknown as string[] }), TypeError, - "The names must be an array of type string | LanguageString.", ); - assertThrows( + throws( () => obj.clone({ names: ["foo", 123 as unknown as string] }), TypeError, - "The names must be an array of type string | LanguageString.", ); }); @@ -144,15 +132,15 @@ test("Object.fromJsonLd()", async () => { "published": "2025-01-01 12:34:56", }, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader }); assertInstanceOf(obj, Object); - assertEquals(obj.name, "Test"); - assertEquals(obj.contents, [ + deepStrictEqual(obj.name, "Test"); + deepStrictEqual(obj.contents, [ new LanguageString("Hello", "en"), new LanguageString("你好", "zh"), ]); assertInstanceOf(obj.source, Source); - assertEquals(obj.source.content, "Hello"); - assertEquals(obj.source.mediaType, "text/plain"); - assertEquals(obj.published, Temporal.Instant.from("2025-01-01T12:34:56Z")); + deepStrictEqual(obj.source.content, "Hello"); + deepStrictEqual(obj.source.mediaType, "text/plain"); + deepStrictEqual(obj.published, Temporal.Instant.from("2025-01-01T12:34:56Z")); const createJsonLd = { "@context": "https://www.w3.org/ns/activitystreams", @@ -172,28 +160,26 @@ test("Object.fromJsonLd()", async () => { { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader }, ); assertInstanceOf(create, Create); - assertEquals(create.name, "Test"); - assertEquals(create.contents, [ + deepStrictEqual(create.name, "Test"); + deepStrictEqual(create.contents, [ new LanguageString("Hello", "en"), new LanguageString("你好", "zh"), ]); - assertEquals(await create.toJsonLd(), createJsonLd); + deepStrictEqual(await create.toJsonLd(), createJsonLd); const note = await create.getObject(); assertInstanceOf(note, Note); - assertEquals(note.content, "Content"); + deepStrictEqual(note.content, "Content"); const empty = await Object.fromJsonLd({}); assertInstanceOf(empty, Object); - await assertRejects( + await rejects( () => Object.fromJsonLd(null), TypeError, - "Invalid JSON-LD: null.", ); - await assertRejects( + await rejects( () => Object.fromJsonLd(undefined), TypeError, - "Invalid JSON-LD: undefined.", ); }); @@ -205,7 +191,7 @@ test("Object.toJsonLd()", async () => { new LanguageString("你好", "zh"), ], }); - assertEquals( + deepStrictEqual( await obj.toJsonLd({ format: "expand", contextLoader: mockDocumentLoader }), [ { @@ -222,7 +208,7 @@ test("Object.toJsonLd()", async () => { }, ], ); - assertEquals(await obj.toJsonLd({ contextLoader: mockDocumentLoader }), { + deepStrictEqual(await obj.toJsonLd({ contextLoader: mockDocumentLoader }), { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1", @@ -253,7 +239,7 @@ test("Note.toJsonLd()", async () => { }), ], }); - assertEquals(await note.toJsonLd({ contextLoader: mockDocumentLoader }), { + deepStrictEqual(await note.toJsonLd({ contextLoader: mockDocumentLoader }), { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1", @@ -290,7 +276,7 @@ test("Note.toJsonLd()", async () => { const noteWithName = note.clone({ name: "Test", }); - assertEquals( + deepStrictEqual( await noteWithName.toJsonLd({ contextLoader: mockDocumentLoader }), await noteWithName.toJsonLd({ contextLoader: mockDocumentLoader, @@ -311,15 +297,15 @@ test("Activity.fromJsonLd()", async () => { { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader }, ); assertInstanceOf(follow, Follow); - assertEquals( + deepStrictEqual( follow.id, new URL("https://activitypub.academy/80c50305-7405-4e38-809f-697647a1f679"), ); - assertEquals( + deepStrictEqual( follow.actorId, new URL("https://activitypub.academy/users/egulia_anbeiss"), ); - assertEquals( + deepStrictEqual( follow.objectId, new URL("https://example.com/users/hongminhee"), ); @@ -352,14 +338,14 @@ test("Activity.fromJsonLd()", async () => { ); const proofs: DataIntegrityProof[] = []; for await (const proof of create.getProofs()) proofs.push(proof); - assertEquals(proofs.length, 1); - assertEquals(proofs[0].cryptosuite, "eddsa-jcs-2022"); - assertEquals( + deepStrictEqual(proofs.length, 1); + deepStrictEqual(proofs[0].cryptosuite, "eddsa-jcs-2022"); + deepStrictEqual( proofs[0].verificationMethodId, new URL("https://server.example/users/alice#ed25519-key"), ); - assertEquals(proofs[0].proofPurpose, "assertionMethod"); - assertEquals( + deepStrictEqual(proofs[0].proofPurpose, "assertionMethod"); + deepStrictEqual( proofs[0].proofValue, decodeMultibase( // cSpell: disable @@ -367,7 +353,7 @@ test("Activity.fromJsonLd()", async () => { // cSpell: enable ), ); - assertEquals( + deepStrictEqual( proofs[0].created, Temporal.Instant.from("2023-02-24T23:36:38Z"), ); @@ -385,16 +371,16 @@ test({ contextLoader: mockDocumentLoader, }); assertInstanceOf(announce, Announce); - assertEquals(announce.id, new URL("https://example.com/announce")); + deepStrictEqual(announce.id, new URL("https://example.com/announce")); const object = await announce.getObject(); assertInstanceOf(object, Object); - assertEquals(object.id, new URL("https://example.com/object")); - assertEquals(object.name, "Fetched object"); + deepStrictEqual(object.id, new URL("https://example.com/object")); + deepStrictEqual(object.name, "Fetched object"); // Is hydration applied to toJsonLd()? const jsonLd = await activity.toJsonLd(); - assertEquals(jsonLd, { + deepStrictEqual(jsonLd, { "@context": [ "https://w3id.org/identity/v1", "https://www.w3.org/ns/activitystreams", @@ -416,7 +402,7 @@ test({ const activity2 = new Activity({ object: new URL("https://example.com/not-found"), }); - assertEquals(await activity2.getObject({ suppressError: true }), null); + deepStrictEqual(await activity2.getObject({ suppressError: true }), null); const activity3 = await Activity.fromJsonLd({ "@context": "https://www.w3.org/ns/activitystreams", @@ -429,7 +415,7 @@ test({ }); const object3 = await activity3.getObject(); assertInstanceOf(object3, Note); - assertEquals(await object3.toJsonLd(), { + deepStrictEqual(await object3.toJsonLd(), { "@context": "https://www.w3.org/ns/activitystreams", type: "Note", content: "Hello world", @@ -455,12 +441,12 @@ test({ contextLoader: mockDocumentLoader, }), ); - assertEquals(objects.length, 2); + deepStrictEqual(objects.length, 2); assertInstanceOf(objects[0], Object); - assertEquals(objects[0].id, new URL("https://example.com/object")); - assertEquals(objects[0].name, "Fetched object"); + deepStrictEqual(objects[0].id, new URL("https://example.com/object")); + deepStrictEqual(objects[0].name, "Fetched object"); assertInstanceOf(objects[1], Object); - assertEquals(objects[1].name, "Second object"); + deepStrictEqual(objects[1].name, "Second object"); const activity2 = new Activity({ objects: [ @@ -473,9 +459,9 @@ test({ const objects2 = await Array.fromAsync( activity2.getObjects({ suppressError: true }), ); - assertEquals(objects2.length, 1); + deepStrictEqual(objects2.length, 1); assertInstanceOf(objects2[0], Object); - assertEquals(objects2[0].name, "Second object"); + deepStrictEqual(objects2[0].name, "Second object"); }, }); @@ -496,19 +482,18 @@ test("Activity.clone()", async () => { }), summary: "Modified", }); - assertEquals((await activity.getActor())?.name, "John Doe"); - assertEquals((await clone.getActor())?.name, "John Doe"); - assertEquals((await activity.getObject())?.name, "Test"); - assertEquals((await clone.getObject())?.name, "Modified"); - assertEquals(activity.name, "Test"); - assertEquals(clone.name, "Test"); - assertEquals(activity.summary, "Test"); - assertEquals(clone.summary, "Modified"); - - assertThrows( + deepStrictEqual((await activity.getActor())?.name, "John Doe"); + deepStrictEqual((await clone.getActor())?.name, "John Doe"); + deepStrictEqual((await activity.getObject())?.name, "Test"); + deepStrictEqual((await clone.getObject())?.name, "Modified"); + deepStrictEqual(activity.name, "Test"); + deepStrictEqual(clone.name, "Test"); + deepStrictEqual(activity.summary, "Test"); + deepStrictEqual(clone.summary, "Modified"); + + throws( () => activity.clone({ summary: "singular", summaries: ["plural"] }), TypeError, - "Cannot update both summary and summaries at the same time.", ); }); @@ -517,9 +502,9 @@ test("Question.voters", async () => { voters: 123, }); const json = await question.toJsonLd({ format: "compact" }); - assert(typeof json === "object" && json != null); - assert("votersCount" in json); - assertEquals(json["votersCount"], 123); + ok(typeof json === "object" && json != null); + ok("votersCount" in json); + deepStrictEqual((json as Record)["votersCount"], 123); }); test({ @@ -535,7 +520,7 @@ test({ new LanguageString("你好", "zh"), ], }); - assertEquals( + deepStrictEqual( Deno.inspect(obj, { colors: false, sorted: true, compact: false }), "Deno" in globalThis ? "Object {\n" + @@ -587,7 +572,7 @@ test("Person.fromJsonLd()", async () => { contextLoader: mockDocumentLoader, baseUrl: new URL("https://todon.eu/"), }); - assertEquals( + deepStrictEqual( person.publicKeyId, new URL("https://todon.eu/users/hongminhee#main-key"), ); @@ -595,7 +580,7 @@ test("Person.fromJsonLd()", async () => { documentLoader: mockDocumentLoader, }); assertInstanceOf(publicKey, CryptographicKey); - assertEquals( + deepStrictEqual( publicKey?.ownerId, new URL("https://todon.eu/users/hongminhee"), ); @@ -615,7 +600,7 @@ test("Person.fromJsonLd()", async () => { "alsoKnownAs": "at://did:plc:x7xdowahlhm5xulzqw4ehv6q", // cSpell: enable }); - assertEquals( + deepStrictEqual( person2.aliasId, // cSpell: disable new URL("at://did%3Aplc%3Ax7xdowahlhm5xulzqw4ehv6q"), @@ -627,7 +612,7 @@ test("Person.toJsonLd()", async () => { const person = new Person({ aliases: [new URL("https://example.com/alias")], }); - assertEquals(await person.toJsonLd(), { + deepStrictEqual(await person.toJsonLd(), { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", @@ -681,11 +666,11 @@ test("Collection.fromJsonLd()", async () => { "id": "https://example.com/collection/jzc50wc28l", "inboxOf": "https://example.com/person/bup9a8eqm", }); - assertEquals( + deepStrictEqual( collection.id, new URL("https://example.com/collection/jzc50wc28l"), ); - assertEquals( + deepStrictEqual( collection.inboxOfId, new URL("https://example.com/person/bup9a8eqm"), ); @@ -720,8 +705,8 @@ test("Note.quoteUrl", async () => { quoteUrl: "https://example.com/object", type: "Note", }; - assertEquals(await note.toJsonLd(), expected); - assertEquals(await note.toJsonLd({ format: "compact" }), expected); + deepStrictEqual(await note.toJsonLd(), expected); + deepStrictEqual(await note.toJsonLd({ format: "compact" }), expected); const jsonLd: Record = { "@context": [ @@ -740,15 +725,15 @@ test("Note.quoteUrl", async () => { quoteUri: "https://example.com/object3", }; const loaded = await Note.fromJsonLd(jsonLd); - assertEquals(loaded.quoteUrl, new URL("https://example.com/object")); + deepStrictEqual(loaded.quoteUrl, new URL("https://example.com/object")); delete jsonLd.quoteUrl; const loaded2 = await Note.fromJsonLd(jsonLd); - assertEquals(loaded2.quoteUrl, new URL("https://example.com/object2")); + deepStrictEqual(loaded2.quoteUrl, new URL("https://example.com/object2")); delete jsonLd._misskey_quote; const loaded3 = await Note.fromJsonLd(jsonLd); - assertEquals(loaded3.quoteUrl, new URL("https://example.com/object3")); + deepStrictEqual(loaded3.quoteUrl, new URL("https://example.com/object3")); }); test("Key.publicKey", async () => { @@ -776,7 +761,7 @@ test("Key.publicKey", async () => { ), }); const jsonLd = await key.toJsonLd({ contextLoader: mockDocumentLoader }); - assertEquals(jsonLd, { + deepStrictEqual(jsonLd, { "@context": "https://w3id.org/security/v1", publicKeyPem: "-----BEGIN PUBLIC KEY-----\n" + // cSpell: disable @@ -795,8 +780,11 @@ test("Key.publicKey", async () => { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, }); - assertNotEquals(loadedKey.publicKey, null); - assertEquals(await crypto.subtle.exportKey("jwk", loadedKey.publicKey!), jwk); + notDeepStrictEqual(loadedKey.publicKey, null); + deepStrictEqual( + await crypto.subtle.exportKey("jwk", loadedKey.publicKey!), + jwk, + ); }); test("Place.fromJsonLd()", async () => { @@ -810,14 +798,14 @@ test("Place.fromJsonLd()", async () => { units: "miles", }, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader }); assertInstanceOf(place, Place); - assertEquals(place.name, "Fresno Area"); - assertEquals(place.latitude, 36.75); - assertEquals(place.longitude, 119.7667); - assertEquals(place.radius, 15); - assertEquals(place.units, "miles"); + deepStrictEqual(place.name, "Fresno Area"); + deepStrictEqual(place.latitude, 36.75); + deepStrictEqual(place.longitude, 119.7667); + deepStrictEqual(place.radius, 15); + deepStrictEqual(place.units, "miles"); let jsonLd = await place.toJsonLd({ contextLoader: mockDocumentLoader }); - assertEquals(jsonLd, { + deepStrictEqual(jsonLd, { "@context": "https://www.w3.org/ns/activitystreams", type: "Place", name: "Fresno Area", @@ -831,7 +819,7 @@ test("Place.fromJsonLd()", async () => { format: "compact", contextLoader: mockDocumentLoader, }); - assertEquals(jsonLd, { + deepStrictEqual(jsonLd, { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1", @@ -851,7 +839,7 @@ test("Actor.getOutbox()", async () => { }); const outbox = await person.getOutbox({ documentLoader: mockDocumentLoader }); assertInstanceOf(outbox, OrderedCollectionPage); - assertEquals(outbox.totalItems, 1); + deepStrictEqual(outbox.totalItems, 1); }); test("Link.fromJsonLd()", async () => { @@ -862,8 +850,8 @@ test("Link.fromJsonLd()", async () => { "href": "at://did:plc:ia76kvnndjutgedggx2ibrem/app.bsky.feed.post/3lyxjjs27jkqg", }); - assertEquals(link.rel, "canonical"); - assertEquals( + deepStrictEqual(link.rel, "canonical"); + deepStrictEqual( link.href, new URL( "at://did%3Aplc%3Aia76kvnndjutgedggx2ibrem/app.bsky.feed.post/3lyxjjs27jkqg", @@ -875,7 +863,7 @@ test("Link.fromJsonLd()", async () => { "type": "Link", "href": "at://bnewbold.bsky.team/app.bsky.feed.post/3jwdwj2ctlk26", }); - assertEquals( + deepStrictEqual( link2.href, new URL("at://bnewbold.bsky.team/app.bsky.feed.post/3jwdwj2ctlk26"), ); @@ -885,7 +873,7 @@ test("Link.fromJsonLd()", async () => { "type": "Link", "href": "at://did:plc:ia76kvnndjutgedggx2ibrem", }); - assertEquals( + deepStrictEqual( link3.href, new URL("at://did%3Aplc%3Aia76kvnndjutgedggx2ibrem"), ); @@ -909,7 +897,7 @@ test("Person.fromJsonLd() with relative URLs", async () => { }); const icon = await person.getIcon(); - assertEquals( + deepStrictEqual( icon?.url, new URL("https://example.com/avatars/test-avatar.jpg"), ); @@ -935,7 +923,7 @@ test("Person.fromJsonLd() with relative URLs", async () => { }); const icon2 = await person2.getIcon(); - assertEquals( + deepStrictEqual( icon2?.url, new URL("https://media.example.com/avatars/test-avatar.jpg"), ); @@ -963,7 +951,7 @@ test("Person.fromJsonLd() with relative URLs and baseUrl", async () => { }); const icon = await personWithBase.getIcon(); - assertEquals( + deepStrictEqual( icon?.url, new URL("https://example.com/avatars/test-avatar.jpg"), ); @@ -985,12 +973,12 @@ test("FEP-fe34: Trust tracking in object construction", async () => { // Trust should be automatically set for embedded objects during construction // We can verify this by checking that the object is returned immediately // without requiring remote fetching - assertEquals(create.objectId, new URL("https://example.com/note")); + deepStrictEqual(create.objectId, new URL("https://example.com/note")); // Should return the embedded object directly (no remote fetch needed) const result = await create.getObject(); - assertEquals(result, note); - assertEquals(result?.content, "Hello World"); + deepStrictEqual(result, note); + deepStrictEqual(result?.content, "Hello World"); }); test("FEP-fe34: Trust tracking in object cloning", () => { @@ -1015,7 +1003,10 @@ test("FEP-fe34: Trust tracking in object cloning", () => { object: newNote, }); - assertEquals(clonedCreate.objectId, new URL("https://example.com/new-note")); + deepStrictEqual( + clonedCreate.objectId, + new URL("https://example.com/new-note"), + ); }); test("FEP-fe34: crossOrigin ignore behavior (default)", async () => { @@ -1047,7 +1038,7 @@ test("FEP-fe34: crossOrigin ignore behavior (default)", async () => { const result = await create.getObject({ documentLoader: crossOriginDocumentLoader, }); - assertEquals(result, null); + deepStrictEqual(result, null); }); test("FEP-fe34: crossOrigin throw behavior", async () => { @@ -1075,14 +1066,13 @@ test("FEP-fe34: crossOrigin throw behavior", async () => { }); // Should throw an error when encountering cross-origin objects - await assertRejects( + await rejects( () => create.getObject({ documentLoader: crossOriginDocumentLoader, crossOrigin: "throw", }), Error, - "The object's @id (https://malicious.com/fake-note) has a different origin than the document URL (https://different-origin.com/note)", ); }); @@ -1117,8 +1107,8 @@ test("FEP-fe34: crossOrigin trust behavior", async () => { }); assertInstanceOf(result, Note); - assertEquals(result?.id, new URL("https://malicious.com/fake-note")); - assertEquals(result?.content, "This is a spoofed note"); + deepStrictEqual(result?.id, new URL("https://malicious.com/fake-note")); + deepStrictEqual(result?.content, "This is a spoofed note"); }); test("FEP-fe34: Same origin objects are trusted", async () => { @@ -1151,67 +1141,71 @@ test("FEP-fe34: Same origin objects are trusted", async () => { }); assertInstanceOf(result, Note); - assertEquals(result?.id, new URL("https://example.com/note")); - assertEquals(result?.content, "This is a legitimate note"); + deepStrictEqual(result?.id, new URL("https://example.com/note")); + deepStrictEqual(result?.content, "This is a legitimate note"); }); -test("FEP-fe34: Embedded cross-origin objects from JSON-LD are ignored by default", async () => { - // Mock document loader for creating the Create object from JSON-LD - // deno-lint-ignore require-await - const createDocumentLoader = async (url: string) => { - if (url === "https://example.com/create") { - return { - documentUrl: url, - contextUrl: null, - document: { - "@context": "https://www.w3.org/ns/activitystreams", - "@type": "Create", - "@id": "https://example.com/create", - "actor": "https://example.com/actor", - "object": { - "@type": "Note", - "@id": "https://different-origin.com/note", // Different origin from parent! - "content": "Embedded note from JSON-LD", +test( + "FEP-fe34: Embedded cross-origin objects from JSON-LD are ignored by default", + async () => { + // Mock document loader for creating the Create object from JSON-LD + // deno-lint-ignore require-await + const createDocumentLoader = async (url: string) => { + if (url === "https://example.com/create") { + return { + documentUrl: url, + contextUrl: null, + document: { + "@context": "https://www.w3.org/ns/activitystreams", + "@type": "Create", + "@id": "https://example.com/create", + "actor": "https://example.com/actor", + "object": { + "@type": "Note", + // Different origin from parent! + "@id": "https://different-origin.com/note", + "content": "Embedded note from JSON-LD", + }, }, - }, - }; - } - throw new Error("Document not found"); - }; + }; + } + throw new Error("Document not found"); + }; - // Create object from JSON-LD (embedded objects won't be trusted) - const create = await Create.fromJsonLd( - await createDocumentLoader("https://example.com/create").then((r) => - r.document - ), - { documentLoader: createDocumentLoader }, - ); + // Create object from JSON-LD (embedded objects won't be trusted) + const create = await Create.fromJsonLd( + await createDocumentLoader("https://example.com/create").then((r) => + r.document + ), + { documentLoader: createDocumentLoader }, + ); - // Mock document loader that would return the "legitimate" version - // deno-lint-ignore require-await - const objectDocumentLoader = async (url: string) => { - if (url === "https://different-origin.com/note") { - return { - documentUrl: url, - contextUrl: null, - document: { - "@context": "https://www.w3.org/ns/activitystreams", - "@type": "Note", - "@id": "https://different-origin.com/note", - "content": "Legitimate note from origin", - }, - }; - } - throw new Error("Document not found"); - }; + // Mock document loader that would return the "legitimate" version + // deno-lint-ignore require-await + const objectDocumentLoader = async (url: string) => { + if (url === "https://different-origin.com/note") { + return { + documentUrl: url, + contextUrl: null, + document: { + "@context": "https://www.w3.org/ns/activitystreams", + "@type": "Note", + "@id": "https://different-origin.com/note", + "content": "Legitimate note from origin", + }, + }; + } + throw new Error("Document not found"); + }; - // Should fetch from origin instead of trusting embedded object - const result = await create.getObject({ - documentLoader: objectDocumentLoader, - }); - assertInstanceOf(result, Note); - assertEquals(result?.content, "Legitimate note from origin"); -}); + // Should fetch from origin instead of trusting embedded object + const result = await create.getObject({ + documentLoader: objectDocumentLoader, + }); + assertInstanceOf(result, Note); + deepStrictEqual(result?.content, "Legitimate note from origin"); + }, +); test("FEP-fe34: Constructor vs JSON-LD parsing trust difference", async () => { // 1. Constructor-created objects: embedded objects are trusted @@ -1226,7 +1220,7 @@ test("FEP-fe34: Constructor vs JSON-LD parsing trust difference", async () => { // Should return the embedded object directly (trusted) const constructorResult = await constructorCreate.getObject(); - assertEquals(constructorResult?.content, "Constructor embedded note"); + deepStrictEqual(constructorResult?.content, "Constructor embedded note"); // 2. JSON-LD parsed objects: embedded objects are NOT trusted const jsonLdCreate = await Create.fromJsonLd({ @@ -1261,7 +1255,7 @@ test("FEP-fe34: Constructor vs JSON-LD parsing trust difference", async () => { // Should fetch from origin instead of using embedded object (not trusted) const jsonLdResult = await jsonLdCreate.getObject({ documentLoader }); - assertEquals(jsonLdResult?.content, "Fetched from origin"); + deepStrictEqual(jsonLdResult?.content, "Fetched from origin"); }); test("FEP-fe34: Array properties respect cross-origin policy", async () => { @@ -1311,9 +1305,9 @@ test("FEP-fe34: Array properties respect cross-origin policy", async () => { } // Should only get the same-origin item, cross-origin item should be filtered out - assertEquals(items.length, 1); + deepStrictEqual(items.length, 1); assertInstanceOf(items[0], Note); - assertEquals((items[0] as Note).content, "Legitimate note 2"); + deepStrictEqual((items[0] as Note).content, "Legitimate note 2"); }); test("FEP-fe34: Array properties with crossOrigin trust option", async () => { @@ -1364,104 +1358,107 @@ test("FEP-fe34: Array properties with crossOrigin trust option", async () => { } // Should get both items when trust mode is enabled - assertEquals(items.length, 2); + deepStrictEqual(items.length, 2); assertInstanceOf(items[0], Note); assertInstanceOf(items[1], Note); - assertEquals((items[0] as Note).content, "Fake note 1"); - assertEquals((items[1] as Note).content, "Legitimate note 2"); + deepStrictEqual((items[0] as Note).content, "Fake note 1"); + deepStrictEqual((items[1] as Note).content, "Legitimate note 2"); }); -test("FEP-fe34: Embedded objects in arrays from JSON-LD respect cross-origin policy", async () => { - // Mock document loader for creating the Collection object from JSON-LD - // deno-lint-ignore require-await - const collectionDocumentLoader = async (url: string) => { - if (url === "https://example.com/collection") { - return { - documentUrl: url, - contextUrl: null, - document: { - "@context": "https://www.w3.org/ns/activitystreams", - "@type": "Collection", - "@id": "https://example.com/collection", - "items": [ - { - "@type": "Note", - "@id": "https://example.com/trusted-note", // Same origin - "content": "Trusted embedded note from JSON-LD", - }, - { - "@type": "Note", - "@id": "https://different-origin.com/untrusted-note", // Different origin! - "content": "Untrusted embedded note from JSON-LD", - }, - ], - }, - }; - } - throw new Error("Document not found"); - }; +test( + "FEP-fe34: Embedded objects in arrays from JSON-LD respect cross-origin policy", + async () => { + // Mock document loader for creating the Collection object from JSON-LD + // deno-lint-ignore require-await + const collectionDocumentLoader = async (url: string) => { + if (url === "https://example.com/collection") { + return { + documentUrl: url, + contextUrl: null, + document: { + "@context": "https://www.w3.org/ns/activitystreams", + "@type": "Collection", + "@id": "https://example.com/collection", + "items": [ + { + "@type": "Note", + "@id": "https://example.com/trusted-note", // Same origin + "content": "Trusted embedded note from JSON-LD", + }, + { + "@type": "Note", + "@id": "https://different-origin.com/untrusted-note", // Different origin! + "content": "Untrusted embedded note from JSON-LD", + }, + ], + }, + }; + } + throw new Error("Document not found"); + }; - // Create collection from JSON-LD (embedded objects won't be trusted) - const collection = await Collection.fromJsonLd( - await collectionDocumentLoader("https://example.com/collection").then((r) => - r.document - ), - { documentLoader: collectionDocumentLoader }, - ); + // Create collection from JSON-LD (embedded objects won't be trusted) + const collection = await Collection.fromJsonLd( + await collectionDocumentLoader("https://example.com/collection").then(( + r, + ) => r.document), + { documentLoader: collectionDocumentLoader }, + ); - // Mock document loader for fetching objects - // deno-lint-ignore require-await - const itemDocumentLoader = async (url: string) => { - if (url === "https://example.com/trusted-note") { - return { - documentUrl: url, - contextUrl: null, - document: { - "@context": "https://www.w3.org/ns/activitystreams", - "@type": "Note", - "@id": "https://example.com/trusted-note", - "content": "Trusted note from origin", - }, - }; - } else if (url === "https://different-origin.com/untrusted-note") { - return { - documentUrl: url, - contextUrl: null, - document: { - "@context": "https://www.w3.org/ns/activitystreams", - "@type": "Note", - "@id": "https://different-origin.com/untrusted-note", - "content": "Legitimate note from actual origin", - }, - }; - } - throw new Error("Document not found"); - }; + // Mock document loader for fetching objects + // deno-lint-ignore require-await + const itemDocumentLoader = async (url: string) => { + if (url === "https://example.com/trusted-note") { + return { + documentUrl: url, + contextUrl: null, + document: { + "@context": "https://www.w3.org/ns/activitystreams", + "@type": "Note", + "@id": "https://example.com/trusted-note", + "content": "Trusted note from origin", + }, + }; + } else if (url === "https://different-origin.com/untrusted-note") { + return { + documentUrl: url, + contextUrl: null, + document: { + "@context": "https://www.w3.org/ns/activitystreams", + "@type": "Note", + "@id": "https://different-origin.com/untrusted-note", + "content": "Legitimate note from actual origin", + }, + }; + } + throw new Error("Document not found"); + }; - const items = []; - for await ( - const item of collection.getItems({ documentLoader: itemDocumentLoader }) - ) { - items.push(item); - } + const items = []; + for await ( + const item of collection.getItems({ documentLoader: itemDocumentLoader }) + ) { + items.push(item); + } - // Should get both items - assertEquals(items.length, 2); + // Should get both items + deepStrictEqual(items.length, 2); - // First item (same origin) - should use embedded object since it's same-origin as parent - assertInstanceOf(items[0], Note); - assertEquals( - (items[0] as Note).content, - "Trusted embedded note from JSON-LD", - ); + // First item (same origin) - should use embedded object since it's same-origin as parent + assertInstanceOf(items[0], Note); + deepStrictEqual( + (items[0] as Note).content, + "Trusted embedded note from JSON-LD", + ); - // Second item (cross-origin) - should be fetched from origin, not embedded version - assertInstanceOf(items[1], Note); - assertEquals( - (items[1] as Note).content, - "Legitimate note from actual origin", - ); -}); + // Second item (cross-origin) - should be fetched from origin, not embedded version + assertInstanceOf(items[1], Note); + deepStrictEqual( + (items[1] as Note).content, + "Legitimate note from actual origin", + ); + }, +); function getAllProperties( type: TypeSchema, @@ -1474,6 +1471,55 @@ function getAllProperties( return props; } +const ed25519PublicKey = new CryptographicKey({ + id: new URL("https://example.com/person2#key4"), + owner: new URL("https://example.com/person2"), + publicKey: await crypto.subtle.importKey( + "jwk", + { + crv: "Ed25519", + ext: true, + key_ops: ["verify"], + kty: "OKP", + // cSpell: disable + x: "LR8epAGDe-cVq5p2Tx49CCfphpk1rNhkNoY9i-XEUfg", + // cSpell: enable + }, + "Ed25519", + true, + ["verify"], + ), +}) as CryptographicKey & { publicKey: CryptoKey }; + +const rsaPublicKey = new CryptographicKey({ + id: new URL("https://example.com/key"), + owner: new URL("https://example.com/person"), + publicKey: await crypto.subtle.importKey( + "jwk", + { + kty: "RSA", + alg: "RS256", + // cSpell: disable + n: "yIB9rotX8G6r6_6toT-x24BUiQ_HaPH1Em9dOt4c94s-OPFoEdH7DY7Iym9A8Ll" + + "H4JaGF8KD38bLHWe1S4x0jV3gHJKhK7veJfGZCKUENcQecBZ-YWUs5HWvUIX1vVB" + + "__0luHrg6BQKGOrSOE-WIAxyr0qsWCFfZzQrvSnUD2yvg1arJX2xhms14uxoRd5K" + + "g9efKSCmmQaNEapicARUmFWrIEpGFa_nUUnqimssAGw1eZFqf3wA4TjhsuARBhGa" + + "Jtv_3KEa016eMZxy3kDlOjZnXZTaTgWkXdodwUvy8563fes3Al6BlcS2iJ9qbtha" + + "8rSm0FHqoUKH73JsLPKQIwQ", + e: "AQAB", + // cSpell: enable + key_ops: ["verify"], + ext: true, + }, + { + name: "RSASSA-PKCS1-v1_5", + hash: "SHA-256", + }, + true, + ["verify"], + ), +}) as CryptographicKey & { publicKey: CryptoKey }; + // deno-lint-ignore no-explicit-any const sampleValues: Record = { "http://www.w3.org/2001/XMLSchema#boolean": true, @@ -1504,7 +1550,7 @@ const sampleValues: Record = { ]), "fedify:langTag": new Intl.Locale("en-Latn-US"), "fedify:url": new URL("https://fedify.dev/"), - "fedify:publicKey": rsaPublicKey1.publicKey, + "fedify:publicKey": rsaPublicKey.publicKey, "fedify:multibaseKey": ed25519PublicKey.publicKey, "fedify:proofPurpose": "assertionMethod", "fedify:units": "m", @@ -1524,6 +1570,10 @@ for (const typeUri in types) { }); } +const { assertSnapshot } = await import("@std/testing/snapshot").catch( + () => ({ assertSnapshot: () => Promise.resolve() }), +); + for (const typeUri in types) { const type = types[typeUri]; // @ts-ignore: classes are all different @@ -1542,33 +1592,33 @@ for (const typeUri in types) { for (const property of allProperties) { if (areAllScalarTypes(property.range, types)) { if (property.functional || property.singularAccessor) { - assertEquals( + deepStrictEqual( instance[property.singularName], sampleValues[property.range[0]], ); } if (!property.functional) { - assertEquals( + deepStrictEqual( instance[property.pluralName], property.range.map((t) => sampleValues[t]), ); } } else { if (property.functional || property.singularAccessor) { - assertEquals( + deepStrictEqual( await instance[`get${pascalCase(property.singularName)}`].call( instance, { documentLoader: mockDocumentLoader }, ), sampleValues[property.range[0]], ); - assertEquals( + deepStrictEqual( instance[`${property.singularName}Id`], sampleValues[property.range[0]].id, ); } if (!property.functional) { - assertEquals( + deepStrictEqual( await Array.fromAsync( instance[`get${pascalCase(property.pluralName)}`].call( instance, @@ -1577,7 +1627,7 @@ for (const typeUri in types) { ), property.range.map((t) => sampleValues[t]), ); - assertEquals( + deepStrictEqual( instance[`${property.singularName}Ids`], property.range.map((t) => sampleValues[t].id).filter((i) => i != null @@ -1590,24 +1640,24 @@ for (const typeUri in types) { for (const property of allProperties) { if (areAllScalarTypes(property.range, types)) { if (property.functional || property.singularAccessor) { - assertEquals(empty[property.singularName], null); + deepStrictEqual(empty[property.singularName], null); } if (!property.functional) { - assertEquals(empty[property.pluralName], []); + deepStrictEqual(empty[property.pluralName], []); } } else { if (property.functional || property.singularAccessor) { - assertEquals( + deepStrictEqual( await empty[`get${pascalCase(property.singularName)}`].call( empty, { documentLoader: mockDocumentLoader }, ), null, ); - assertEquals(empty[`${property.singularName}Id`], null); + deepStrictEqual(empty[`${property.singularName}Id`], null); } if (!property.functional) { - assertEquals( + deepStrictEqual( await Array.fromAsync( empty[`get${pascalCase(property.pluralName)}`].call( empty, @@ -1616,7 +1666,7 @@ for (const typeUri in types) { ), [], ); - assertEquals(empty[`${property.singularName}Ids`], []); + deepStrictEqual(empty[`${property.singularName}Ids`], []); } } } @@ -1624,7 +1674,7 @@ for (const typeUri in types) { for (const property of allProperties) { if (!property.functional && property.singularAccessor) { - assertThrows( + throws( () => new cls({ [property.singularName]: sampleValues[property.range[0]], @@ -1649,20 +1699,20 @@ for (const typeUri in types) { for (const property of allProperties) { if (areAllScalarTypes(property.range, types)) continue; if (property.functional || property.singularAccessor) { - assertEquals( + deepStrictEqual( instance2[`${property.singularName}Id`], new URL("https://example.com/test"), ); } if (!property.functional) { - assertEquals( + deepStrictEqual( instance2[`${property.singularName}Ids`], [new URL("https://example.com/test")], ); } } - assertThrows( + throws( () => new cls({ id: 123 as unknown as URL }), TypeError, "The id must be a URL.", @@ -1677,7 +1727,7 @@ for (const typeUri in types) { } else { wrongValues[property.pluralName] = [{}]; } - assertThrows(() => new cls(wrongValues), TypeError); + throws(() => new cls(wrongValues), TypeError); } }); @@ -1685,7 +1735,7 @@ for (const typeUri in types) { const instance = new cls({}); for (const property of allProperties) { if (!property.functional && property.singularAccessor) { - assertThrows( + throws( () => instance.clone({ [property.singularName]: sampleValues[property.range[0]], @@ -1696,7 +1746,7 @@ for (const typeUri in types) { } } - assertThrows( + throws( () => instance.clone({ id: 123 as unknown as URL }), TypeError, "The id must be a URL.", @@ -1710,7 +1760,7 @@ for (const typeUri in types) { } else { wrongValues[property.pluralName] = [{}]; } - assertThrows(() => instance.clone(wrongValues), TypeError); + throws(() => instance.clone(wrongValues), TypeError); } }); @@ -1729,60 +1779,67 @@ for (const typeUri in types) { }; if (property.functional || property.singularAccessor) { - test(`${type.name}.get${pascalCase(property.singularName)}() [auto]`, async () => { - const instance = new cls({ - [property.singularName]: new URL("https://example.com/test"), - }); - const value = await instance[`get${pascalCase(property.singularName)}`] - .call(instance, { documentLoader: docLoader }); - assertEquals(value, sampleValues[property.range[0]]); - - if (property.untyped) return; - const wrongRef = new cls({ - [property.singularName]: new URL("https://example.com/wrong-type"), - }); - await assertRejects( - () => - wrongRef[`get${pascalCase(property.singularName)}`].call( - wrongRef, - { - documentLoader: mockDocumentLoader, - }, - ), - TypeError, - ); - }); - } - if (!property.functional) { - test(`${type.name}.get${pascalCase(property.pluralName)}() [auto]`, async () => { - const instance = new cls({ - [property.pluralName]: [new URL("https://example.com/test")], - }); - const value = instance[`get${pascalCase(property.pluralName)}`].call( - instance, - { documentLoader: docLoader }, - ); - assertEquals(await Array.fromAsync(value), [ - sampleValues[property.range[0]], - ]); - - if (property.untyped) return; - const wrongRef = new cls({ - [property.pluralName]: [new URL("https://example.com/wrong-type")], - }); - await assertRejects( - () => - Array.fromAsync( - wrongRef[`get${pascalCase(property.pluralName)}`].call( + test( + `${type.name}.get${pascalCase(property.singularName)}() [auto]`, + async () => { + const instance = new cls({ + [property.singularName]: new URL("https://example.com/test"), + }); + const value = + await instance[`get${pascalCase(property.singularName)}`] + .call(instance, { documentLoader: docLoader }); + deepStrictEqual(value, sampleValues[property.range[0]]); + + if (property.untyped) return; + const wrongRef = new cls({ + [property.singularName]: new URL("https://example.com/wrong-type"), + }); + await rejects( + () => + wrongRef[`get${pascalCase(property.singularName)}`].call( wrongRef, { documentLoader: mockDocumentLoader, }, ), - ), - TypeError, - ); - }); + TypeError, + ); + }, + ); + } + if (!property.functional) { + test( + `${type.name}.get${pascalCase(property.pluralName)}() [auto]`, + async () => { + const instance = new cls({ + [property.pluralName]: [new URL("https://example.com/test")], + }); + const value = instance[`get${pascalCase(property.pluralName)}`].call( + instance, + { documentLoader: docLoader }, + ); + deepStrictEqual(await Array.fromAsync(value), [ + sampleValues[property.range[0]], + ]); + + if (property.untyped) return; + const wrongRef = new cls({ + [property.pluralName]: [new URL("https://example.com/wrong-type")], + }); + await rejects( + () => + Array.fromAsync( + wrongRef[`get${pascalCase(property.pluralName)}`].call( + wrongRef, + { + documentLoader: mockDocumentLoader, + }, + ), + ), + TypeError, + ); + }, + ); } } @@ -1793,17 +1850,17 @@ for (const typeUri in types) { "@type": typeUri, }, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader }, - ); + ) as vocab.Object; assertInstanceOf(instance, cls); - assertEquals(instance.id, new URL("https://example.com/")); - assertEquals( + deepStrictEqual(instance.id, new URL("https://example.com/")); + deepStrictEqual( await instance.toJsonLd(), { "@id": "https://example.com/", "@type": typeUri, }, ); - assertEquals( + deepStrictEqual( await instance.toJsonLd({ format: "compact", contextLoader: mockDocumentLoader, @@ -1817,15 +1874,15 @@ for (const typeUri in types) { ); if (type.extends != null) { - await assertRejects(() => + await rejects(() => cls.fromJsonLd({ "@id": "https://example.com/", "@type": "https://example.com/", }), TypeError); } - await assertRejects(() => cls.fromJsonLd(null), TypeError); - await assertRejects(() => cls.fromJsonLd(undefined), TypeError); + await rejects(() => cls.fromJsonLd(null), TypeError); + await rejects(() => cls.fromJsonLd(undefined), TypeError); }); test(`${type.name}.toJsonLd() [auto]`, async () => { @@ -1836,14 +1893,14 @@ for (const typeUri in types) { const jsonLd = await instance.toJsonLd({ contextLoader: mockDocumentLoader, }); - assertEquals(jsonLd["@context"], type.defaultContext); - assertEquals(jsonLd.id, "https://example.com/"); + deepStrictEqual(jsonLd["@context"], type.defaultContext); + deepStrictEqual(jsonLd.id, "https://example.com/"); const restored = await cls.fromJsonLd(jsonLd, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, }); - assertEquals(restored, instance); - assertEquals( + deepStrictEqual(restored, instance); + deepStrictEqual( await restored.toJsonLd({ contextLoader: mockDocumentLoader }), jsonLd, ); @@ -1853,13 +1910,16 @@ for (const typeUri in types) { format: "compact", context: "https://www.w3.org/ns/activitystreams", }); - assertEquals(jsonLd2["@context"], "https://www.w3.org/ns/activitystreams"); - assertEquals(jsonLd2.id, "https://example.com/"); + deepStrictEqual( + jsonLd2["@context"], + "https://www.w3.org/ns/activitystreams", + ); + deepStrictEqual(jsonLd2.id, "https://example.com/"); const restored2 = await cls.fromJsonLd(jsonLd2, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, }); - assertEquals(restored2, instance); + deepStrictEqual(restored2, instance); const expanded = await instance.toJsonLd({ contextLoader: mockDocumentLoader, @@ -1869,7 +1929,7 @@ for (const typeUri in types) { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, }); - assertEquals(restored3, instance); + deepStrictEqual(restored3, instance); const instance2 = new cls({ id: new URL("https://example.com/"), @@ -1890,14 +1950,14 @@ for (const typeUri in types) { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader, }); - assertEquals(restored4, instance2); + deepStrictEqual(restored4, instance2); - assertRejects( + rejects( () => instance.toJsonLd({ context: "https://www.w3.org/ns/activitystreams" }), TypeError, ); - assertRejects( + rejects( () => instance.toJsonLd({ format: "expand", @@ -1908,13 +1968,9 @@ for (const typeUri in types) { }); if ("Deno" in globalThis) { - const { assertSnapshot } = await import("@std/testing/snapshot").catch( - () => ({ assertSnapshot: () => Promise.resolve() }), - ); - - test(`Deno.inspect(${type.name}) [auto]`, async (t) => { + Deno.test(`Deno.inspect(${type.name}) [auto]`, async (t) => { const empty = new cls({}); - assertEquals(Deno.inspect(empty), `${type.name} {}`); + deepStrictEqual(Deno.inspect(empty), `${type.name} {}`); const instance = new cls({ id: new URL("https://example.com/"), @@ -1938,7 +1994,7 @@ for (const typeUri in types) { globalThis.Object.fromEntries( type.properties.filter((p) => !p.functional).map( (p) => { - assertFalse(p.functional); + ok(!p.functional); return [ p.pluralName, [sampleValues[p.range[0]], sampleValues[p.range[0]]], @@ -1947,11 +2003,12 @@ for (const typeUri in types) { ), ), ); + // @ts-ignore: t is TestContext in node:test but Deno.TestContext in Deno await assertSnapshot(t, Deno.inspect(instance3)); }); } test(`${type.name}.typeId`, () => { - assertEquals(cls.typeId, new URL(type.uri)); + deepStrictEqual(cls.typeId, new URL(type.uri)); }); } diff --git a/packages/vocab/tsdown.config.ts b/packages/vocab/tsdown.config.ts new file mode 100644 index 000000000..ad15857d2 --- /dev/null +++ b/packages/vocab/tsdown.config.ts @@ -0,0 +1,65 @@ +import { cp, glob } from "node:fs/promises"; +import { join, sep } from "node:path"; +import { defineConfig } from "tsdown"; + +export default [ + defineConfig({ + entry: [ + "./src/mod.ts", + ], + dts: true, + format: ["esm", "cjs"], + platform: "neutral", + external: [/^node:/], + outputOptions(outputOptions, format) { + if (format === "cjs") { + outputOptions.intro = ` + const { Temporal } = require("@js-temporal/polyfill"); + `; + } else { + outputOptions.intro = ` + import { Temporal } from "@js-temporal/polyfill"; + `; + } + return outputOptions; + }, + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + dts: true, + external: [/^node:/], + inputOptions: { + onwarn(warning, defaultHandler) { + if ( + warning.code === "UNRESOLVED_IMPORT" && + warning.id?.endsWith("vocab.test.ts") && + warning.exporter && + warning.exporter === "@std/testing/snapshot" + ) { + return; + } + defaultHandler(warning); + }, + }, + outputOptions: { + intro: ` + import { Temporal } from "@js-temporal/polyfill"; + globalThis.addEventListener = () => {}; + `, + }, + hooks: { + "build:done": async (ctx) => { + for await (const file of glob("src/**/*.yaml")) { + await cp( + file, + join(ctx.options.outDir, file.replace(`src${sep}`, "")), + { force: true }, + ); + } + }, + }, + }), +]; + +// cSpell: ignore onwarn diff --git a/packages/webfinger/README.md b/packages/webfinger/README.md new file mode 100644 index 000000000..a6bfc1459 --- /dev/null +++ b/packages/webfinger/README.md @@ -0,0 +1,141 @@ + + +@fedify/webfinger: WebFinger client library for ActivityPub +=========================================================== + +[![JSR][JSR badge]][JSR] +[![npm][npm badge]][npm] + +This package provides a WebFinger client implementation for looking up +ActivityPub actors and other resources in the fediverse. It is part of the +[Fedify] framework but can be used independently. + +[JSR]: https://jsr.io/@fedify/webfinger +[JSR badge]: https://jsr.io/badges/@fedify/webfinger +[npm]: https://www.npmjs.com/package/@fedify/webfinger +[npm badge]: https://img.shields.io/npm/v/@fedify/webfinger?logo=npm +[Fedify]: https://fedify.dev/ + + +Features +-------- + + - WebFinger resource lookup ([RFC 7033]) + - Support for `acct:` URI scheme + - Automatic HTTPS URL construction + - Configurable redirect handling + - OpenTelemetry integration for tracing + - Private IP address validation for security + +[RFC 7033]: https://datatracker.ietf.org/doc/html/rfc7033 + + +Installation +------------ + +~~~~ bash +deno add jsr:@fedify/webfinger # Deno +npm add @fedify/webfinger # npm +pnpm add @fedify/webfinger # pnpm +yarn add @fedify/webfinger # Yarn +bun add @fedify/webfinger # Bun +~~~~ + + +Usage +----- + +### Looking up a WebFinger resource + +You can look up a WebFinger resource using the `lookupWebFinger()` function: + +~~~~ typescript +import { lookupWebFinger } from "@fedify/webfinger"; + +// Look up by acct: URI +const result = await lookupWebFinger("acct:alice@example.com"); + +// Look up by URL +const result2 = await lookupWebFinger("https://example.com/users/alice"); +~~~~ + +### Working with the result + +The result is a `ResourceDescriptor` object containing the subject, aliases, +properties, and links: + +~~~~ typescript +import { lookupWebFinger } from "@fedify/webfinger"; + +const result = await lookupWebFinger("acct:alice@example.com"); +if (result != null) { + console.log("Subject:", result.subject); + console.log("Aliases:", result.aliases); + + // Find the ActivityPub actor URL + const actorLink = result.links?.find( + (link) => link.rel === "self" && link.type === "application/activity+json" + ); + if (actorLink?.href != null) { + console.log("Actor URL:", actorLink.href); + } +} +~~~~ + +### Configuration options + +The `lookupWebFinger()` function accepts various options: + +~~~~ typescript +import { lookupWebFinger } from "@fedify/webfinger"; + +const result = await lookupWebFinger("acct:alice@example.com", { + // Custom User-Agent header + userAgent: "MyApp/1.0", + + // Maximum redirects to follow (default: 5) + maxRedirection: 3, + + // AbortSignal for cancellation + signal: AbortSignal.timeout(5000), +}); +~~~~ + + +API +--- + +### Functions + + - `lookupWebFinger(resource, options?)`: Looks up a WebFinger resource and + returns a `ResourceDescriptor` or `null` if not found. + +### Types + + - `ResourceDescriptor`: Describes a WebFinger resource with subject, aliases, + properties, and links. + - `Link`: Represents a link in a WebFinger response with relation type, media + type, href, titles, and properties. + - `LookupWebFingerOptions`: Options for the `lookupWebFinger()` function. + + +Documentation +------------- + +For comprehensive documentation, please refer to: + + - [WebFinger documentation](https://fedify.dev/manual/webfinger) + - [API reference](https://jsr.io/@fedify/webfinger/doc/~) + + +Related packages +---------------- + + - *@fedify/fedify*: The main Fedify framework + - *@fedify/vocab*: Activity Vocabulary library + + +License +------- + +[MIT License](https://github.com/fedify-dev/fedify/blob/main/LICENSE) diff --git a/packages/webfinger/deno.json b/packages/webfinger/deno.json new file mode 100644 index 000000000..e49acf7da --- /dev/null +++ b/packages/webfinger/deno.json @@ -0,0 +1,26 @@ +{ + "name": "@fedify/webfinger", + "version": "2.0.0", + "license": "MIT", + "exports": { + ".": "./src/mod.ts" + }, + "description": "WebFinger client library for Fedify", + "author": { + "name": "Hong Minhee", + "email": "hong@minhee.org", + "url": "https://hongminhee.org/" + }, + "imports": { + "es-toolkit": "npm:es-toolkit@^1.42.0", + "fetch-mock": "npm:fetch-mock@^12.5.4" + }, + "exclude": [ + "dist", + "node_modules" + ], + "tasks": { + "check": "deno fmt --check && deno lint && deno check src/*.ts", + "test": "deno test" + } +} diff --git a/packages/webfinger/package.json b/packages/webfinger/package.json new file mode 100644 index 000000000..35d6879f1 --- /dev/null +++ b/packages/webfinger/package.json @@ -0,0 +1,71 @@ +{ + "name": "@fedify/webfinger", + "version": "2.0.0", + "homepage": "https://fedify.dev/", + "repository": { + "type": "git", + "url": "git+https://github.com/fedify-dev/fedify.git", + "directory": "packages/webfinger" + }, + "bugs": { + "url": "https://github.com/fedify-dev/fedify/issues" + }, + "funding": [ + "https://opencollective.com/fedify", + "https://github.com/sponsors/dahlia" + ], + "engines": { + "deno": ">=2.0.0", + "node": ">=22.0.0", + "bun": ">=1.1.0" + }, + "description": "WebFinger client library for ActivityPub", + "type": "module", + "main": "./dist/mod.cjs", + "module": "./dist/mod.js", + "types": "./dist/mod.d.ts", + "exports": { + ".": { + "types": { + "import": "./dist/mod.d.ts", + "require": "./dist/mod.d.cts", + "default": "./dist/mod.d.ts" + }, + "import": "./dist/mod.js", + "require": "./dist/mod.cjs", + "default": "./dist/mod.js" + }, + "./package.json": "./package.json" + }, + "scripts": { + "build": "tsdown", + "prepack": "tsdown", + "prepublish": "tsdown", + "test": "tsdown && cd dist/ && node --test" + }, + "keywords": [ + "Fedify", + "WebFinger", + "ActivityPub", + "Fediverse" + ], + "author": { + "name": "Hong Minhee", + "email": "hong@minhee.org", + "url": "https://hongminhee.org/" + }, + "license": "MIT", + "devDependencies": { + "@fedify/fixture": "workspace:*", + "@types/node": "^24.2.1", + "fetch-mock": "catalog:", + "tsdown": "catalog:", + "typescript": "catalog:" + }, + "dependencies": { + "@fedify/vocab-runtime": "workspace:*", + "@logtape/logtape": "catalog:", + "@opentelemetry/api": "catalog:", + "es-toolkit": "catalog:" + } +} diff --git a/packages/fedify/src/webfinger/jrd.ts b/packages/webfinger/src/jrd.ts similarity index 100% rename from packages/fedify/src/webfinger/jrd.ts rename to packages/webfinger/src/jrd.ts diff --git a/packages/fedify/src/webfinger/lookup.test.ts b/packages/webfinger/src/lookup.test.ts similarity index 83% rename from packages/fedify/src/webfinger/lookup.test.ts rename to packages/webfinger/src/lookup.test.ts index 9ebac6383..33e93ffc3 100644 --- a/packages/fedify/src/webfinger/lookup.test.ts +++ b/packages/webfinger/src/lookup.test.ts @@ -1,7 +1,7 @@ import { test } from "@fedify/fixture"; -import { assertEquals } from "@std/assert"; import { withTimeout } from "es-toolkit"; import fetchMock from "fetch-mock"; +import { deepStrictEqual } from "node:assert/strict"; import type { ResourceDescriptor } from "./jrd.ts"; import { lookupWebFinger } from "./lookup.ts"; @@ -11,18 +11,18 @@ test({ sanitizeResources: false, async fn(t) { await t.step("invalid resource", async () => { - assertEquals(await lookupWebFinger("acct:johndoe"), null); - assertEquals(await lookupWebFinger(new URL("acct:johndoe")), null); - assertEquals(await lookupWebFinger("acct:johndoe@"), null); - assertEquals(await lookupWebFinger(new URL("acct:johndoe@")), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe"), null); + deepStrictEqual(await lookupWebFinger(new URL("acct:johndoe")), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe@"), null); + deepStrictEqual(await lookupWebFinger(new URL("acct:johndoe@")), null); }); await t.step("connection refused", async () => { - assertEquals( + deepStrictEqual( await lookupWebFinger("acct:johndoe@fedify-test.internal"), null, ); - assertEquals( + deepStrictEqual( await lookupWebFinger("https://fedify-test.internal/foo"), null, ); @@ -35,8 +35,8 @@ test({ ); await t.step("not found", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); - assertEquals(await lookupWebFinger("https://example.com/foo"), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe@example.com"), null); + deepStrictEqual(await lookupWebFinger("https://example.com/foo"), null); }); const expected: ResourceDescriptor = { @@ -50,7 +50,10 @@ test({ ); await t.step("acct", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), expected); + deepStrictEqual( + await lookupWebFinger("acct:johndoe@example.com"), + expected, + ); }); const expected2: ResourceDescriptor = { @@ -64,7 +67,10 @@ test({ ); await t.step("https", async () => { - assertEquals(await lookupWebFinger("https://example.com/foo"), expected2); + deepStrictEqual( + await lookupWebFinger("https://example.com/foo"), + expected2, + ); }); fetchMock.removeRoutes(); @@ -74,7 +80,7 @@ test({ ); await t.step("invalid response", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe@example.com"), null); }); fetchMock.removeRoutes(); @@ -93,8 +99,8 @@ test({ ); await t.step("private address", async () => { - assertEquals(await lookupWebFinger("acct:test@localhost"), null); - assertEquals( + deepStrictEqual(await lookupWebFinger("acct:test@localhost"), null); + deepStrictEqual( await lookupWebFinger("acct:test@localhost", { allowPrivateAddress: true, }), @@ -125,7 +131,10 @@ test({ ); await t.step("redirection", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), expected); + deepStrictEqual( + await lookupWebFinger("acct:johndoe@example.com"), + expected, + ); }); fetchMock.removeRoutes(); @@ -142,7 +151,7 @@ test({ () => lookupWebFinger("acct:johndoe@example.com"), 2000, ); - assertEquals(result, null); + deepStrictEqual(result, null); }); fetchMock.removeRoutes(); @@ -155,7 +164,7 @@ test({ ); await t.step("redirection to different protocol", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe@example.com"), null); }); fetchMock.removeRoutes(); @@ -168,7 +177,7 @@ test({ ); await t.step("redirection to private address", async () => { - assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); + deepStrictEqual(await lookupWebFinger("acct:johndoe@example.com"), null); }); fetchMock.removeRoutes(); @@ -192,7 +201,7 @@ test({ await t.step("custom maxRedirection", async () => { // Test with maxRedirection: 2 (should fail) redirectCount = 0; - assertEquals( + deepStrictEqual( await lookupWebFinger("acct:johndoe@example.com", { maxRedirection: 2, }), @@ -201,7 +210,7 @@ test({ // Test with maxRedirection: 3 (should succeed) redirectCount = 0; - assertEquals( + deepStrictEqual( await lookupWebFinger("acct:johndoe@example.com", { maxRedirection: 3, }), @@ -210,7 +219,7 @@ test({ // Test with default maxRedirection: 5 (should succeed) redirectCount = 0; - assertEquals( + deepStrictEqual( await lookupWebFinger("acct:johndoe@example.com"), expected, ); @@ -238,7 +247,7 @@ test({ // Abort the request right after starting it controller.abort(); - assertEquals(await promise, null); + deepStrictEqual(await promise, null); }); fetchMock.removeRoutes(); @@ -272,7 +281,7 @@ test({ // Cancel during the delayed second request after redirection setTimeout(() => controller.abort(), 100); - assertEquals(await promise, null); + deepStrictEqual(await promise, null); }); fetchMock.removeRoutes(); @@ -297,7 +306,7 @@ test({ const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); - assertEquals(result, null); + deepStrictEqual(result, null); }); fetchMock.removeRoutes(); @@ -312,7 +321,7 @@ test({ const result = await lookupWebFinger("acct:johndoe@example.com", { signal: controller.signal, }); - assertEquals(result, expected); + deepStrictEqual(result, expected); }); fetchMock.hardReset(); diff --git a/packages/fedify/src/webfinger/lookup.ts b/packages/webfinger/src/lookup.ts similarity index 99% rename from packages/fedify/src/webfinger/lookup.ts rename to packages/webfinger/src/lookup.ts index c9b19c0fd..46d150fdb 100644 --- a/packages/fedify/src/webfinger/lookup.ts +++ b/packages/webfinger/src/lookup.ts @@ -11,7 +11,7 @@ import { trace, type TracerProvider, } from "@opentelemetry/api"; -import metadata from "../../deno.json" with { type: "json" }; +import metadata from "../deno.json" with { type: "json" }; import type { ResourceDescriptor } from "./jrd.ts"; const logger = getLogger(["fedify", "webfinger", "lookup"]); diff --git a/packages/fedify/src/webfinger/mod.ts b/packages/webfinger/src/mod.ts similarity index 100% rename from packages/fedify/src/webfinger/mod.ts rename to packages/webfinger/src/mod.ts diff --git a/packages/webfinger/tsdown.config.ts b/packages/webfinger/tsdown.config.ts new file mode 100644 index 000000000..900365250 --- /dev/null +++ b/packages/webfinger/tsdown.config.ts @@ -0,0 +1,20 @@ +import { glob } from "node:fs/promises"; +import { sep } from "node:path"; +import { defineConfig } from "tsdown"; + +export default [ + defineConfig({ + entry: ["src/mod.ts"], + dts: true, + format: ["esm", "cjs"], + platform: "node", + external: [/^node:/], + }), + defineConfig({ + entry: (await Array.fromAsync(glob(`src/**/*.test.ts`))) + .map((f) => f.replace(sep, "/")), + format: ["esm", "cjs"], + platform: "node", + external: [/^node:/], + }), +]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3669a255c..61fa841d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,9 @@ catalogs: '@logtape/logtape': specifier: ^1.3.5 version: 1.3.5 + '@multiformats/base-x': + specifier: ^4.0.1 + version: 4.0.1 '@nestjs/common': specifier: ^11.0.1 version: 11.1.4 @@ -63,6 +66,9 @@ catalogs: amqplib: specifier: ^0.10.9 version: 0.10.9 + asn1js: + specifier: ^3.0.6 + version: 3.0.7 byte-encodings: specifier: ^1.0.11 version: 1.0.11 @@ -75,6 +81,9 @@ catalogs: express: specifier: ^4.0.0 version: 4.21.2 + fast-check: + specifier: ^3.22.0 + version: 3.23.2 fastify: specifier: ^5.2.0 version: 5.6.1 @@ -99,6 +108,9 @@ catalogs: next: specifier: ^15.4.6 version: 15.5.0 + pkijs: + specifier: ^3.3.3 + version: 3.3.3 postgres: specifier: ^3.4.7 version: 3.4.7 @@ -108,6 +120,9 @@ catalogs: typescript: specifier: ^5.9.3 version: 5.9.3 + urlpattern-polyfill: + specifier: ^10.1.0 + version: 10.1.0 importers: @@ -175,6 +190,9 @@ importers: '@fedify/testing': specifier: 'workspace:' version: link:../packages/testing + '@fedify/vocab': + specifier: 'workspace:' + version: link:../packages/vocab '@fedify/vocab-runtime': specifier: 'workspace:' version: link:../packages/vocab-runtime @@ -301,6 +319,9 @@ importers: '@fedify/fedify': specifier: 'workspace:' version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab devDependencies: typescript: specifier: 'catalog:' @@ -317,6 +338,9 @@ importers: '@fedify/fedify': specifier: workspace:* version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab elysia: specifier: 'catalog:' version: 1.3.8(exact-mirror@0.1.3(@sinclair/typebox@0.34.38))(file-type@21.0.0)(typescript@5.9.3) @@ -333,6 +357,9 @@ importers: '@fedify/fedify': specifier: 'workspace:' version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab '@logtape/logtape': specifier: 'catalog:' version: 1.3.5 @@ -361,6 +388,9 @@ importers: '@fedify/fedify': specifier: 'workspace:' version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab fastify: specifier: 'catalog:' version: 5.6.1 @@ -380,6 +410,9 @@ importers: '@fedify/koa': specifier: 'workspace:' version: link:../../packages/koa + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab '@logtape/logtape': specifier: 'catalog:' version: 1.3.5 @@ -408,6 +441,9 @@ importers: '@fedify/next': specifier: 'workspace:' version: link:../../packages/next + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab next: specifier: 15.5.0 version: 15.5.0(@opentelemetry/api@1.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -454,6 +490,9 @@ importers: '@fedify/fedify': specifier: 'workspace:' version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab '@logtape/logtape': specifier: 'catalog:' version: 1.3.5 @@ -500,6 +539,9 @@ importers: '@fedify/fedify': specifier: 'workspace:' version: link:../../packages/fedify + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab next: specifier: 15.3.1 version: 15.3.1(@opentelemetry/api@1.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -549,6 +591,9 @@ importers: '@fedify/sveltekit': specifier: 'workspace:' version: link:../../packages/sveltekit + '@fedify/vocab': + specifier: 'workspace:' + version: link:../../packages/vocab x-forwarded-fetch: specifier: ^0.2.0 version: 0.2.0 @@ -678,6 +723,9 @@ importers: '@fedify/sqlite': specifier: workspace:* version: link:../sqlite + '@fedify/vocab': + specifier: workspace:* + version: link:../vocab '@fedify/vocab-runtime': specifier: workspace:* version: link:../vocab-runtime @@ -844,18 +892,21 @@ importers: packages/fedify: dependencies: + '@fedify/vocab': + specifier: workspace:* + version: link:../vocab '@fedify/vocab-runtime': specifier: workspace:* version: link:../vocab-runtime + '@fedify/webfinger': + specifier: workspace:* + version: link:../webfinger '@js-temporal/polyfill': specifier: ^0.5.1 version: 0.5.1 '@logtape/logtape': specifier: 'catalog:' version: 1.3.5 - '@multiformats/base-x': - specifier: ^4.0.1 - version: 4.0.1 '@opentelemetry/api': specifier: 'catalog:' version: 1.9.0 @@ -868,9 +919,6 @@ importers: '@opentelemetry/semantic-conventions': specifier: ^1.27.0 version: 1.34.0 - asn1js: - specifier: ^3.0.7 - version: 3.0.7 byte-encodings: specifier: 'catalog:' version: 1.0.11 @@ -886,9 +934,6 @@ importers: multicodec: specifier: ^3.2.1 version: 3.2.1 - pkijs: - specifier: ^3.3.3 - version: 3.3.3 structured-field-values: specifier: ^2.0.4 version: 2.0.4 @@ -899,7 +944,7 @@ importers: specifier: ^3.1.1 version: 3.1.1 urlpattern-polyfill: - specifier: ^10.1.0 + specifier: 'catalog:' version: 10.1.0 devDependencies: '@fedify/fixture': @@ -917,9 +962,6 @@ importers: '@types/node': specifier: ^24.2.1 version: 24.3.0 - fast-check: - specifier: ^3.22.0 - version: 3.23.2 fetch-mock: specifier: 'catalog:' version: 12.6.0 @@ -954,12 +996,18 @@ importers: specifier: 'catalog:' version: 2.2.0(@opentelemetry/api@1.9.0) devDependencies: + '@js-temporal/polyfill': + specifier: 'catalog:' + version: 0.5.1 tsdown: specifier: 'catalog:' version: 0.12.9(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 + urlpattern-polyfill: + specifier: 'catalog:' + version: 10.1.0 packages/h3: dependencies: @@ -1148,6 +1196,9 @@ importers: '@fedify/fedify': specifier: workspace:^ version: link:../fedify + '@fedify/vocab': + specifier: workspace:* + version: link:../vocab '@js-temporal/polyfill': specifier: 'catalog:' version: 0.5.1 @@ -1155,9 +1206,6 @@ importers: specifier: 'catalog:' version: 1.3.5 devDependencies: - '@fedify/testing': - specifier: workspace:^ - version: link:../testing '@fedify/vocab-runtime': specifier: workspace:^ version: link:../vocab-runtime @@ -1167,6 +1215,9 @@ importers: typescript: specifier: 'catalog:' version: 5.9.3 + urlpattern-polyfill: + specifier: 'catalog:' + version: 10.1.0 packages/sqlite: dependencies: @@ -1231,20 +1282,78 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/vocab: + dependencies: + '@fedify/vocab-tools': + specifier: workspace:* + version: link:../vocab-tools + '@fedify/webfinger': + specifier: workspace:* + version: link:../webfinger + '@js-temporal/polyfill': + specifier: 'catalog:' + version: 0.5.1 + '@logtape/logtape': + specifier: 'catalog:' + version: 1.3.5 + '@multiformats/base-x': + specifier: 'catalog:' + version: 4.0.1 + '@opentelemetry/api': + specifier: 'catalog:' + version: 1.9.0 + asn1js: + specifier: 'catalog:' + version: 3.0.7 + es-toolkit: + specifier: 'catalog:' + version: 1.43.0 + 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 + devDependencies: + '@fedify/fixture': + specifier: workspace:* + version: link:../fixture + '@fedify/vocab-runtime': + specifier: workspace:* + version: link:../vocab-runtime + '@types/node': + specifier: 'catalog:' + version: 22.19.1 + fast-check: + specifier: 'catalog:' + version: 3.23.2 + fetch-mock: + specifier: 'catalog:' + version: 12.6.0 + tsdown: + specifier: 'catalog:' + version: 0.12.9(typescript@5.9.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + packages/vocab-runtime: dependencies: '@logtape/logtape': specifier: 'catalog:' version: 1.3.5 '@multiformats/base-x': - specifier: ^4.0.1 + specifier: 'catalog:' version: 4.0.1 '@opentelemetry/api': specifier: 'catalog:' version: 1.9.0 asn1js: - specifier: ^3.0.6 - version: 3.0.6 + specifier: 'catalog:' + version: 3.0.7 byte-encodings: specifier: 'catalog:' version: 1.0.11 @@ -1252,8 +1361,8 @@ importers: specifier: ^3.2.1 version: 3.2.1 pkijs: - specifier: ^3.2.5 - version: 3.2.5 + specifier: 'catalog:' + version: 3.3.3 devDependencies: '@types/node': specifier: ^24.2.1 @@ -1293,6 +1402,37 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/webfinger: + dependencies: + '@fedify/vocab-runtime': + specifier: workspace:* + version: link:../vocab-runtime + '@logtape/logtape': + specifier: 'catalog:' + version: 1.3.5 + '@opentelemetry/api': + specifier: 'catalog:' + version: 1.9.0 + es-toolkit: + specifier: 'catalog:' + version: 1.43.0 + devDependencies: + '@fedify/fixture': + specifier: workspace:* + version: link:../fixture + '@types/node': + specifier: ^24.2.1 + version: 24.3.0 + fetch-mock: + specifier: 'catalog:' + version: 12.6.0 + tsdown: + specifier: 'catalog:' + version: 0.12.9(typescript@5.9.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + packages: '@algolia/autocomplete-core@1.17.7': @@ -2962,10 +3102,6 @@ packages: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -4808,10 +4944,6 @@ packages: as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} - asn1js@3.0.6: - resolution: {integrity: sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==} - engines: {node: '>=12.0.0'} - asn1js@3.0.7: resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==} engines: {node: '>=12.0.0'} @@ -7333,10 +7465,6 @@ packages: pkg-types@2.2.0: resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} - pkijs@3.2.5: - resolution: {integrity: sha512-WX0la7n7CbnguuaIQoT4Fc0IJckPDOUldzOwlZ0nwpOcySS+Six/tXBdc0RX17J5o1To0SAr3xDJjDLsOfDFQA==} - engines: {node: '>=12.0.0'} - pkijs@3.3.3: resolution: {integrity: sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==} engines: {node: '>=16.0.0'} @@ -10356,8 +10484,6 @@ snapshots: '@noble/hashes@1.4.0': {} - '@noble/hashes@1.8.0': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -12631,12 +12757,6 @@ snapshots: dependencies: printable-characters: 1.0.42 - asn1js@3.0.6: - dependencies: - pvtsutils: 1.3.6 - pvutils: 1.1.3 - tslib: 2.8.1 - asn1js@3.0.7: dependencies: pvtsutils: 1.3.6 @@ -13617,7 +13737,7 @@ snapshots: get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.14 + 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) @@ -13632,7 +13752,7 @@ snapshots: get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.14 + 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)) @@ -15828,15 +15948,6 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 - pkijs@3.2.5: - dependencies: - '@noble/hashes': 1.8.0 - asn1js: 3.0.7 - bytestreamjs: 2.0.1 - pvtsutils: 1.3.6 - pvutils: 1.1.3 - tslib: 2.8.1 - pkijs@3.3.3: dependencies: '@noble/hashes': 1.4.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6103b0422..c8b389d63 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -19,8 +19,10 @@ packages: - packages/sqlite - packages/sveltekit - packages/testing +- packages/vocab - packages/vocab-runtime - packages/vocab-tools +- packages/webfinger - docs - examples/cloudflare-workers - examples/elysia @@ -38,6 +40,7 @@ catalog: "@js-temporal/polyfill": ^0.5.1 "@logtape/file": ^1.3.5 "@logtape/logtape": ^1.3.5 + "@multiformats/base-x": ^4.0.1 "@opentelemetry/api": ^1.9.0 "@opentelemetry/core": ^2.0.0 "@opentelemetry/sdk-trace-base": ^2.0.0 @@ -52,18 +55,22 @@ catalog: "@types/node": ^22.17.0 "@nestjs/common": ^11.0.1 amqplib: ^0.10.9 + asn1js: ^3.0.6 byte-encodings: ^1.0.11 elysia: ^1.3.8 es-toolkit: 1.43.0 express: ^4.0.0 - fastify: ^5.2.0 + fast-check: ^3.22.0 fastify-plugin: ^5.0.1 + fastify: ^5.2.0 fetch-mock: ^12.5.4 h3: ^1.15.0 hono: ^4.0.0 ioredis: ^5.8.2 koa: ^2.16.0 next: ^15.4.6 + pkijs: ^3.3.3 postgres: ^3.4.7 tsdown: ^0.12.9 typescript: ^5.9.3 + urlpattern-polyfill: "^10.1.0"