From 90fdf1983a89988e65b2077b3557fdbf57d2ceab Mon Sep 17 00:00:00 2001 From: dktsudgg Date: Sat, 25 Jul 2026 14:52:48 +0900 Subject: [PATCH 1/2] Fix check-each failure for @fedify/elysia `mise run check-each elysia` failed because Deno could not resolve the bare `elysia` import. The package declares elysia only in `peerDependencies`, which Deno ignores, and no import map listed it. Every type error the task reported traced back to that one unresolved import. This commit includes the following changes: - Added `elysia` to the root deno.json imports, pointing at `npm:elysia@^1.3.8`, the same range as the pnpm catalog. This only affects the development environment: the published package still declares elysia through `peerDependencies`, so nothing changes for users. - Regenerated deno.lock to match. - Switched the `fedify()` signature to `AnyElysia` with an explicit return type. The public API no longer depends on Elysia's internal generics, and TypeScript still links each `federation` to its `contextDataFactory`. Assisted-by: Claude Code:claude-fable-5 --- deno.json | 1 + deno.lock | 111 +++++++++++++++++++---------------- packages/elysia/src/index.ts | 8 +-- 3 files changed, 66 insertions(+), 54 deletions(-) diff --git a/deno.json b/deno.json index cdef4dd87..369b08670 100644 --- a/deno.json +++ b/deno.json @@ -77,6 +77,7 @@ "astro": "npm:astro@^7.0.0", "byte-encodings": "npm:byte-encodings@^1.0.11", "chalk": "npm:chalk@^5.6.2", + "elysia": "npm:elysia@^1.3.8", "es-toolkit": "npm:es-toolkit@^1.46.1", "h3": "npm:h3@^1.15.0", "hono": "jsr:@hono/hono@^4.8.3", diff --git a/deno.lock b/deno.lock index 8bf54dba3..38199a485 100644 --- a/deno.lock +++ b/deno.lock @@ -106,7 +106,7 @@ "npm:@remix-run/node-fetch-server@0.12": "0.12.0", "npm:@solidjs/start@^1.3.0": "1.3.2_acorn@8.17.0_ioredis@5.10.1_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0", "npm:@standard-schema/spec@^1.1.0": "1.1.0", - "npm:@sveltejs/kit@2": "2.57.1_@opentelemetry+api@1.9.1_typescript@6.0.3_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0", + "npm:@sveltejs/kit@2": "2.57.1_@opentelemetry+api@1.9.1_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0", "npm:@types/amqplib@*": "0.10.8", "npm:@types/amqplib@~0.10.7": "0.10.8", "npm:@types/babel__core@^7.20.5": "7.20.5", @@ -127,6 +127,7 @@ "npm:cli-table3@~0.6.5": "0.6.5", "npm:dax@~0.46.1": "0.46.1", "npm:devalue@^5.8.1": "5.8.1", + "npm:elysia@^1.3.8": "1.4.29_@sinclair+typebox@0.34.52_exact-mirror@0.2.7__@sinclair+typebox@0.34.52_file-type@22.0.1_openapi-types@12.1.3", "npm:enquirer@^2.4.1": "2.4.1", "npm:es-toolkit@^1.46.1": "1.46.1", "npm:esbuild-wasm@~0.25.11": "0.25.12", @@ -905,8 +906,8 @@ "@bruits/satteri-wasm32-wasi@0.9.5": { "integrity": "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==", "dependencies": [ - "@emnapi/core@1.11.1", - "@emnapi/runtime@1.11.1", + "@emnapi/core", + "@emnapi/runtime", "@napi-rs/wasm-runtime@1.1.6_@emnapi+core@1.11.1_@emnapi+runtime@1.11.1" ], "cpu": ["wasm32"] @@ -1084,25 +1085,12 @@ "tslib@2.8.1" ] }, - "@emnapi/core@1.11.2": { - "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", - "dependencies": [ - "@emnapi/wasi-threads", - "tslib@2.8.1" - ] - }, "@emnapi/runtime@1.11.1": { "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", "dependencies": [ "tslib@2.8.1" ] }, - "@emnapi/runtime@1.11.2": { - "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", - "dependencies": [ - "tslib@2.8.1" - ] - }, "@emnapi/wasi-threads@1.2.2": { "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", "dependencies": [ @@ -2889,14 +2877,14 @@ "@img/sharp-wasm32@0.33.5": { "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", "dependencies": [ - "@emnapi/runtime@1.11.2" + "@emnapi/runtime" ], "cpu": ["wasm32"] }, "@img/sharp-wasm32@0.35.3": { "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", "dependencies": [ - "@emnapi/runtime@1.11.2" + "@emnapi/runtime" ] }, "@img/sharp-webcontainers-wasm32@0.35.3": { @@ -3595,16 +3583,14 @@ "@napi-rs/wasm-runtime@1.1.6_@emnapi+core@1.11.1_@emnapi+runtime@1.11.1": { "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "dependencies": [ - "@emnapi/core@1.11.1", - "@emnapi/runtime@1.11.1", + "@emnapi/core", + "@emnapi/runtime", "@tybys/wasm-util" ] }, "@napi-rs/wasm-runtime@1.1.6_@emnapi+core@1.11.2_@emnapi+runtime@1.11.2": { "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "dependencies": [ - "@emnapi/core@1.11.2", - "@emnapi/runtime@1.11.2", "@tybys/wasm-util" ] }, @@ -4123,7 +4109,7 @@ "zod@3.25.76" ] }, - "@netlify/sdk@1.67.0_graphql@16.14.2": { + "@netlify/sdk@1.67.0_graphql@16.14.2_@types+react@19.2.17": { "integrity": "sha512-ogDibdluTkqLtKBVWye6tzh3D9GJ3jfHe7IhnbMYc1HlNiLz7QqOrLpVyqm8pOvXW5PZfJ11JPyTcs69/yTztQ==", "dependencies": [ "@commander-js/extra-typings", @@ -4957,8 +4943,8 @@ "@rolldown/binding-wasm32-wasi@1.1.5": { "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", "dependencies": [ - "@emnapi/core@1.11.1", - "@emnapi/runtime@1.11.1", + "@emnapi/core", + "@emnapi/runtime", "@napi-rs/wasm-runtime@1.1.6_@emnapi+core@1.11.1_@emnapi+runtime@1.11.1" ], "cpu": ["wasm32"] @@ -5402,6 +5388,9 @@ "@sideway/pinpoint@2.0.0": { "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, + "@sinclair/typebox@0.34.52": { + "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==" + }, "@sindresorhus/is@4.6.0": { "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" }, @@ -5473,13 +5462,13 @@ "lodash" ] }, - "@stackbit/cms-core@2.0.1_graphql@16.14.2": { + "@stackbit/cms-core@2.0.1_graphql@16.14.2_@types+react@19.2.17": { "integrity": "sha512-fsBLMP6hBIS8idS1bYGerV+tIgx/OVOmme47kMaoJWBKpQYqGMhKSZodGCkORUM4xRhTxncavHWI+jds+Kp62Q==", "dependencies": [ "@babel/parser@7.29.7", "@babel/traverse", "@iarna/toml", - "@netlify/sdk@1.67.0_graphql@16.14.2", + "@netlify/sdk@1.67.0_graphql@16.14.2_@types+react@19.2.17", "@stackbit/sdk", "@stackbit/types", "@stackbit/utils", @@ -5499,7 +5488,7 @@ "uuid@9.0.1" ] }, - "@stackbit/cms-git@0.4.18_graphql@16.14.2": { + "@stackbit/cms-git@0.4.18_graphql@16.14.2_@types+react@19.2.17": { "integrity": "sha512-eqRY3sC8xaJ6OrWPpRptEhe/6/0mt6TsAk0LMVsDERekzLOYQqnmsqPNFN0tIaTd9FXqPSmravW6jc6b+aAXMA==", "dependencies": [ "@stackbit/artisanal-names", @@ -5631,7 +5620,7 @@ "acorn@8.17.0" ] }, - "@sveltejs/kit@2.57.1_@opentelemetry+api@1.9.1_typescript@6.0.3_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0": { + "@sveltejs/kit@2.57.1_@opentelemetry+api@1.9.1_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0": { "integrity": "sha512-VRdSbB96cI1EnRh09CqmnQqP/YJvET5buj8S6k7CxaJqBJD4bw4fRKDjcarAj/eX9k2eHifQfDH8NtOh+ZxxPw==", "dependencies": [ "@opentelemetry/api", @@ -5658,7 +5647,7 @@ ], "bin": true }, - "@sveltejs/vite-plugin-svelte@7.0.0_svelte@5.55.4__acorn@8.17.0_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0_acorn@8.17.0": { + "@sveltejs/vite-plugin-svelte@7.0.0_svelte@5.55.4__acorn@8.17.0_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0": { "integrity": "sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g==", "dependencies": [ "deepmerge", @@ -5666,7 +5655,7 @@ "obug", "svelte", "vite@7.3.2_@types+node@24.12.2_tsx@4.21.0_yaml@2.9.0", - "vitefu@1.1.3_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0" + "vitefu" ] }, "@szmarczak/http-timer@4.0.6": { @@ -6853,7 +6842,7 @@ "unifont", "unstorage@1.17.5_ioredis@5.10.1_@types+node@24.12.2_mysql2@3.22.3__@types+node@24.12.2", "vite@8.1.4_@types+node@24.12.2_esbuild@0.28.1_tsx@4.21.0_yaml@2.9.0", - "vitefu@1.1.3_vite@8.1.4__@types+node@24.12.2__esbuild@0.28.1__tsx@4.21.0__yaml@2.9.0_@types+node@24.12.2_esbuild@0.28.1_tsx@4.21.0_yaml@2.9.0", + "vitefu", "xxhash-wasm", "yargs-parser@22.0.0", "zod@4.3.6" @@ -8534,6 +8523,18 @@ "electron-to-chromium@1.5.389": { "integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==" }, + "elysia@1.4.29_@sinclair+typebox@0.34.52_exact-mirror@0.2.7__@sinclair+typebox@0.34.52_file-type@22.0.1_openapi-types@12.1.3": { + "integrity": "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA==", + "dependencies": [ + "@sinclair/typebox", + "cookie@1.1.1", + "exact-mirror", + "fast-decode-uri-component", + "file-type@22.0.1", + "memoirist", + "openapi-types" + ] + }, "emoji-regex-xs@1.0.0": { "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==" }, @@ -9286,6 +9287,15 @@ "eventsource@2.0.2": { "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==" }, + "exact-mirror@0.2.7_@sinclair+typebox@0.34.52": { + "integrity": "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg==", + "dependencies": [ + "@sinclair/typebox" + ], + "optionalPeers": [ + "@sinclair/typebox" + ] + }, "execa@5.1.1": { "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dependencies": [ @@ -9616,6 +9626,15 @@ "uint8array-extras" ] }, + "file-type@22.0.1": { + "integrity": "sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA==", + "dependencies": [ + "@tokenizer/inflate", + "strtok3@10.3.5", + "token-types@6.1.2", + "uint8array-extras" + ] + }, "file-uri-to-path@1.0.0": { "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, @@ -11926,6 +11945,9 @@ "media-typer@0.3.0": { "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, + "memoirist@0.4.0": { + "integrity": "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg==" + }, "memoize-one@6.0.0": { "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, @@ -12781,6 +12803,9 @@ "openapi-typescript-helpers" ] }, + "openapi-types@12.1.3": { + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" + }, "openapi-typescript-helpers@0.0.15": { "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==" }, @@ -13940,11 +13965,7 @@ "dts-resolver", "get-tsconfig@5.0.0-beta.5", "obug", - "rolldown", - "typescript@7.0.2" - ], - "optionalPeers": [ - "typescript@7.0.2" + "rolldown" ] }, "rolldown@1.1.5": { @@ -15255,12 +15276,10 @@ "tinyglobby", "tree-kill", "tsx", - "typescript@7.0.2", "unconfig-core" ], "optionalPeers": [ - "tsx", - "typescript@7.0.2" + "tsx" ], "bin": true }, @@ -15880,7 +15899,7 @@ "solid-js", "solid-refresh", "vite@7.3.2_@types+node@24.12.2_tsx@4.21.0_yaml@2.9.0", - "vitefu@1.1.3_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0" + "vitefu" ] }, "vite@6.4.2_@types+node@24.12.2_tsx@4.21.0_yaml@2.9.0": { @@ -15950,15 +15969,6 @@ ], "bin": true }, - "vitefu@1.1.3_vite@7.3.2__@types+node@24.12.2__tsx@4.21.0__yaml@2.9.0": { - "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", - "dependencies": [ - "vite@7.3.2_@types+node@24.12.2_tsx@4.21.0_yaml@2.9.0" - ], - "optionalPeers": [ - "vite@7.3.2_@types+node@24.12.2_tsx@4.21.0_yaml@2.9.0" - ] - }, "vitefu@1.1.3_vite@8.1.4__@types+node@24.12.2__esbuild@0.28.1__tsx@4.21.0__yaml@2.9.0_@types+node@24.12.2_esbuild@0.28.1_tsx@4.21.0_yaml@2.9.0": { "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", "dependencies": [ @@ -16516,6 +16526,7 @@ "npm:astro@7", "npm:byte-encodings@^1.0.11", "npm:chalk@^5.6.2", + "npm:elysia@^1.3.8", "npm:es-toolkit@^1.46.1", "npm:h3@^1.15.0", "npm:ioredis@^5.8.2", diff --git a/packages/elysia/src/index.ts b/packages/elysia/src/index.ts index 8a1648abb..85a95b676 100644 --- a/packages/elysia/src/index.ts +++ b/packages/elysia/src/index.ts @@ -1,5 +1,5 @@ import type { Federation } from "@fedify/fedify"; -import type { Elysia } from "elysia"; +import type { AnyElysia } from "elysia"; export type ContextDataFactory = ( req?: Request, @@ -8,8 +8,8 @@ export type ContextDataFactory = ( export const fedify = ( federation: Federation, contextDataFactory: ContextDataFactory, -) => { - return (app: Elysia) => +): (app: AnyElysia) => AnyElysia => { + return (app: AnyElysia) => app .decorate("federation", federation) .onRequest(async ({ request, set, federation }) => { @@ -19,7 +19,7 @@ export const fedify = ( // Create context data using the factory or default to empty object const contextData = await contextDataFactory(request); - const response = await federation.fetch(request, { + const response: Response = await federation.fetch(request, { contextData, onNotFound: () => { // Let Elysia handle non-federation routes From 541aef580bd14c392414f8a636e49057724e135d Mon Sep 17 00:00:00 2001 From: dktsudgg Date: Sun, 26 Jul 2026 13:53:17 +0900 Subject: [PATCH 2/2] Add context data tests for @fedify/elysia This commit includes the following changes: - Added two tests with a minimal fake federation: fedify() calls the context data factory when handling a request, and the factory's return value reaches federation.fetch() as its contextData option. - Added the test and test:bun scripts to package.json because `mise run test-each elysia` did not pick up the new tests without them. The tests now run on Node.js and Bun, the runtimes Elysia targets. Assisted-by: Claude Code:claude-fable-5 --- packages/elysia/package.json | 4 ++- packages/elysia/src/index.test.ts | 49 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 packages/elysia/src/index.test.ts diff --git a/packages/elysia/package.json b/packages/elysia/package.json index 407ee7627..ddf2bb880 100644 --- a/packages/elysia/package.json +++ b/packages/elysia/package.json @@ -46,7 +46,9 @@ "build:self": "tsdown", "build": "pnpm --filter @fedify/elysia... run build:self", "prepack": "pnpm build", - "prepublish": "pnpm build" + "prepublish": "pnpm build", + "test": "node --experimental-transform-types --test", + "test:bun": "bun test src/" }, "peerDependencies": { "elysia": "^1.3.6", diff --git a/packages/elysia/src/index.test.ts b/packages/elysia/src/index.test.ts new file mode 100644 index 000000000..1d4084dc1 --- /dev/null +++ b/packages/elysia/src/index.test.ts @@ -0,0 +1,49 @@ +import { Elysia } from "elysia"; +import { strict as assert } from "node:assert"; +import { describe, test } from "node:test"; +import { fedify } from "./index.ts"; + +interface MockFederation { + fetch(request: Request, options: unknown): Promise; +} + +describe("[elysia] fedify() plugin", () => { + test("fedify() calls the context data factory when handling a request", async () => { + const elysia = new Elysia(); + const mockFederation: MockFederation = { + fetch: () => Promise.resolve(new Response("OK")), + }; + let count = 0; + const mockContextDataFactory = () => { + // increases count if this method called + count++; + }; + + elysia.use(fedify(mockFederation as never, mockContextDataFactory)); + await elysia.handle(new Request("http://localhost/")); + + assert.strictEqual(count, 1, "the context data factory must be called"); + }); + + test("fedify() calls federation.fetch() with the context data", async () => { + const elysia = new Elysia(); + const mockFederation: MockFederation = { + fetch: (_req, opts) => { + // return context data + const contextData = (opts as { contextData: string }).contextData; + return Promise.resolve(new Response(contextData)); + }, + }; + const mockContextDataFactory = () => "Hello World"; + + elysia.use(fedify(mockFederation as never, mockContextDataFactory)); + const actual = await elysia.handle(new Request("http://localhost/")) + .then((res) => res.text()); + + assert.strictEqual( + actual, + "Hello World", + "federation.fetch() must receive the context data returned by the factory", + ); + }); +});