From cff9ddeb56292a039995b03b9e4a7186314ac4f6 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Tue, 9 Jun 2026 08:24:02 +0000 Subject: [PATCH 1/5] Speed up type-checking of dispatcher path types The setCollectionDispatcher() and setOrderedCollectionDispatcher() overloads typed `path` as RFC 6570 template-literal unions: `Rfc6570Expression` is an 8-member union, and the overloads interpolated it up to four times, so each `path` type expanded to a Cartesian product of up to 8^4 = 4096 template-literal variants. TypeScript spent almost all of `deno check`'s time structurally comparing these types, making a cold check of middleware.ts take on the order of ~30s. Collapse those overloads to a single `path: string` signature in both the Federatable interface and FederationBuilderImpl. Path validity is still enforced at runtime via @fedify/uri-template (isPath() and Router.variables(), already used in builder.ts), so nothing is lost except the costly compile-time RFC 6570 shape checking. https://github.com/fedify-dev/fedify/issues/613 Assisted-by: Claude Code:claude-opus-4-8 Assisted-by: Codex:gpt-5.5 --- packages/fedify/src/federation/builder.ts | 146 ------------------- packages/fedify/src/federation/federation.ts | 144 +----------------- 2 files changed, 3 insertions(+), 287 deletions(-) diff --git a/packages/fedify/src/federation/builder.ts b/packages/fedify/src/federation/builder.ts index 6aa15016b..03dd62efc 100644 --- a/packages/fedify/src/federation/builder.ts +++ b/packages/fedify/src/federation/builder.ts @@ -1253,94 +1253,6 @@ export class FederationBuilderImpl return setters; } - setCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - setCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - setCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - setCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; setCollectionDispatcher< TObject extends Object, TParam extends string, @@ -1368,64 +1280,6 @@ export class FederationBuilderImpl ); } - setOrderedCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - setOrderedCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - setOrderedCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; setOrderedCollectionDispatcher< TObject extends Object, TParam extends string, diff --git a/packages/fedify/src/federation/federation.ts b/packages/fedify/src/federation/federation.ts index e1d5e9d40..68e4ae6e7 100644 --- a/packages/fedify/src/federation/federation.ts +++ b/packages/fedify/src/federation/federation.ts @@ -13,7 +13,6 @@ import type { import type { MeterProvider, TracerProvider } from "@opentelemetry/api"; import type { ActivityTransformer } from "../compat/types.ts"; import type { HttpMessageSignaturesSpec } from "../sig/http.ts"; -import type { CircuitBreakerOptions } from "./circuit-breaker.ts"; import type { ActorAliasMapper, ActorDispatcher, @@ -39,6 +38,7 @@ import type { UnverifiedActivityHandler, WebFingerLinksDispatcher, } from "./callback.ts"; +import type { CircuitBreakerOptions } from "./circuit-breaker.ts"; import type { Context, InboxContext, RequestContext } from "./context.ts"; import type { KvStore } from "./kv.ts"; import type { @@ -512,145 +512,7 @@ export interface Federatable { setCollectionDispatcher( name: string | symbol, itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - - /** - * Registers a collection of objects dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of objects to dispatch. - * @template TParam The parameter names of the requested URL. - * @param name A unique name for the collection dispatcher. - * @param itemType The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the collection dispatcher. - * The syntax is based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). - * The path must have one or more variables. - * @param dispatcher A collection dispatcher callback to register. - */ - setCollectionDispatcher( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - - /** - * Registers a collection of objects dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of objects to dispatch. - * @template TParam The parameter names of the requested URL. - * @param name A unique name for the collection dispatcher. - * @param itemType The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the collection dispatcher. - * The syntax is based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). - * The path must have one or more variables. - * @param dispatcher A collection dispatcher callback to register. - */ - setCollectionDispatcher( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - - /** - * Registers an ordered collection of objects dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of objects to dispatch. - * @template TParam The parameter names of the requested URL. - * @param name A unique name for the collection dispatcher. - * @param itemType The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the collection dispatcher. - * The syntax is based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). - * The path must have one or more variables. - * @param dispatcher A collection dispatcher callback to register. - */ - setOrderedCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression}${string}`, - dispatcher: CustomCollectionDispatcher< - TObject, - TParam, - RequestContext, - TContextData - >, - ): CustomCollectionCallbackSetters< - TParam, - RequestContext, - TContextData - >; - - /** - * Registers an ordered collection of objects dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of objects to dispatch. - * @template TParam The parameter names of the requested URL. - * @param name A unique name for the collection dispatcher. - * @param itemType The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the collection dispatcher. - * The syntax is based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). - * The path must have one or more variables. - * @param dispatcher A collection dispatcher callback to register. - */ - setOrderedCollectionDispatcher< - TObject extends Object, - TParam extends string, - >( - name: string | symbol, - itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, + path: string, dispatcher: CustomCollectionDispatcher< TObject, TParam, @@ -683,7 +545,7 @@ export interface Federatable { >( name: string | symbol, itemType: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, + path: string, dispatcher: CustomCollectionDispatcher< TObject, TParam, From caf06ba763153a119718650e02bd8d2fd71c80d8 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Tue, 9 Jun 2026 08:56:36 +0000 Subject: [PATCH 2/5] Speed up type-checking of object dispatcher paths Same root cause as the previous commit: setObjectDispatcher() still typed `path` as RFC 6570 template-literal unions. Its widest overloads interpolated `Rfc6570Expression` (an 8-member union) up to three times, expanding `path` to 8^3 = 512 template-literal variants, plus several simple multi-variable forms. These were the last remaining combinatorial dispatcher path types, and the context boundary checks (ContextImpl/FederationImpl vs Context/Federation) dragged them in throughout the type graph. Collapse the setObjectDispatcher() overloads to a single `path: string` signature in both the Federatable interface and FederationBuilderImpl. Path validity (including the "one or more variables" requirement) is still enforced at runtime via assertPath() and Router.variables() in the existing implementation. This roughly halves the remaining cold project type-check: locally `deno task check:types` drops from ~24s to ~12s, on top of the ~99s -> ~24s from the previous commit. https://github.com/fedify-dev/fedify/issues/613 Assisted-by: Claude Code:claude-opus-4-8 Assisted-by: Codex:gpt-5.5 --- packages/fedify/src/federation/builder.ts | 37 ------- packages/fedify/src/federation/federation.ts | 104 +------------------ 2 files changed, 1 insertion(+), 140 deletions(-) diff --git a/packages/fedify/src/federation/builder.ts b/packages/fedify/src/federation/builder.ts index 03dd62efc..6b8b9a29d 100644 --- a/packages/fedify/src/federation/builder.ts +++ b/packages/fedify/src/federation/builder.ts @@ -593,43 +593,6 @@ export class FederationBuilderImpl this.webFingerLinksDispatcher = dispatcher; } - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; setObjectDispatcher( cls: ConstructorWithTypeId, path: string, diff --git a/packages/fedify/src/federation/federation.ts b/packages/fedify/src/federation/federation.ts index 68e4ae6e7..97a988f70 100644 --- a/packages/fedify/src/federation/federation.ts +++ b/packages/fedify/src/federation/federation.ts @@ -143,109 +143,7 @@ export interface Federatable { */ setObjectDispatcher( cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - - /** - * Registers an object dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of object to dispatch. - * @template TParam The parameter names of the requested URL. - * @param cls The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the object dispatcher. The syntax is - * based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path - * must have one or more variables. - * @param dispatcher An object dispatcher callback to register. - */ - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - - /** - * Registers an object dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of object to dispatch. - * @template TParam The parameter names of the requested URL. - * @param cls The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the object dispatcher. The syntax is - * based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path - * must have one or more variables. - * @param dispatcher An object dispatcher callback to register. - */ - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: - `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - - /** - * Registers an object dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of object to dispatch. - * @template TParam The parameter names of the requested URL. - * @param cls The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the object dispatcher. The syntax is - * based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path - * must have one or more variables. - * @param dispatcher An object dispatcher callback to register. - */ - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}${Rfc6570Expression}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - - /** - * Registers an object dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of object to dispatch. - * @template TParam The parameter names of the requested URL. - * @param cls The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the object dispatcher. The syntax is - * based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path - * must have one or more variables. - * @param dispatcher An object dispatcher callback to register. - */ - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< - TParam - >}${string}`, - dispatcher: ObjectDispatcher, - ): ObjectCallbackSetters; - - /** - * Registers an object dispatcher. - * - * @template TContextData The context data to pass to the {@link Context}. - * @template TObject The type of object to dispatch. - * @template TParam The parameter names of the requested URL. - * @param cls The Activity Vocabulary class of the object to dispatch. - * @param path The URI path pattern for the object dispatcher. The syntax is - * based on URI Template - * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path - * must have one or more variables. - * @param dispatcher An object dispatcher callback to register. - */ - setObjectDispatcher( - cls: ConstructorWithTypeId, - path: `${string}${Rfc6570Expression}${string}`, + path: string, dispatcher: ObjectDispatcher, ): ObjectCallbackSetters; From dc705522665d7ef7011dacb711b96c28a4f6e1e9 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Tue, 9 Jun 2026 09:20:24 +0000 Subject: [PATCH 3/5] Revert `Federatable` --- packages/fedify/src/federation/federation.ts | 248 ++++++++++++++++++- 1 file changed, 244 insertions(+), 4 deletions(-) diff --git a/packages/fedify/src/federation/federation.ts b/packages/fedify/src/federation/federation.ts index 97a988f70..e1d5e9d40 100644 --- a/packages/fedify/src/federation/federation.ts +++ b/packages/fedify/src/federation/federation.ts @@ -13,6 +13,7 @@ import type { import type { MeterProvider, TracerProvider } from "@opentelemetry/api"; import type { ActivityTransformer } from "../compat/types.ts"; import type { HttpMessageSignaturesSpec } from "../sig/http.ts"; +import type { CircuitBreakerOptions } from "./circuit-breaker.ts"; import type { ActorAliasMapper, ActorDispatcher, @@ -38,7 +39,6 @@ import type { UnverifiedActivityHandler, WebFingerLinksDispatcher, } from "./callback.ts"; -import type { CircuitBreakerOptions } from "./circuit-breaker.ts"; import type { Context, InboxContext, RequestContext } from "./context.ts"; import type { KvStore } from "./kv.ts"; import type { @@ -143,7 +143,109 @@ export interface Federatable { */ setObjectDispatcher( cls: ConstructorWithTypeId, - path: string, + path: + `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, + dispatcher: ObjectDispatcher, + ): ObjectCallbackSetters; + + /** + * Registers an object dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of object to dispatch. + * @template TParam The parameter names of the requested URL. + * @param cls The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the object dispatcher. The syntax is + * based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path + * must have one or more variables. + * @param dispatcher An object dispatcher callback to register. + */ + setObjectDispatcher( + cls: ConstructorWithTypeId, + path: + `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, + dispatcher: ObjectDispatcher, + ): ObjectCallbackSetters; + + /** + * Registers an object dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of object to dispatch. + * @template TParam The parameter names of the requested URL. + * @param cls The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the object dispatcher. The syntax is + * based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path + * must have one or more variables. + * @param dispatcher An object dispatcher callback to register. + */ + setObjectDispatcher( + cls: ConstructorWithTypeId, + path: + `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, + dispatcher: ObjectDispatcher, + ): ObjectCallbackSetters; + + /** + * Registers an object dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of object to dispatch. + * @template TParam The parameter names of the requested URL. + * @param cls The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the object dispatcher. The syntax is + * based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path + * must have one or more variables. + * @param dispatcher An object dispatcher callback to register. + */ + setObjectDispatcher( + cls: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< + TParam + >}${string}${Rfc6570Expression}${string}`, + dispatcher: ObjectDispatcher, + ): ObjectCallbackSetters; + + /** + * Registers an object dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of object to dispatch. + * @template TParam The parameter names of the requested URL. + * @param cls The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the object dispatcher. The syntax is + * based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path + * must have one or more variables. + * @param dispatcher An object dispatcher callback to register. + */ + setObjectDispatcher( + cls: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< + TParam + >}${string}`, + dispatcher: ObjectDispatcher, + ): ObjectCallbackSetters; + + /** + * Registers an object dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of object to dispatch. + * @template TParam The parameter names of the requested URL. + * @param cls The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the object dispatcher. The syntax is + * based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path + * must have one or more variables. + * @param dispatcher An object dispatcher callback to register. + */ + setObjectDispatcher( + cls: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}`, dispatcher: ObjectDispatcher, ): ObjectCallbackSetters; @@ -410,7 +512,75 @@ export interface Federatable { setCollectionDispatcher( name: string | symbol, itemType: ConstructorWithTypeId, - path: string, + path: `${string}${Rfc6570Expression< + TParam + >}${string}${Rfc6570Expression< + TParam + >}${string}${Rfc6570Expression< + TParam + >}${string}`, + dispatcher: CustomCollectionDispatcher< + TObject, + TParam, + RequestContext, + TContextData + >, + ): CustomCollectionCallbackSetters< + TParam, + RequestContext, + TContextData + >; + + /** + * Registers a collection of objects dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of objects to dispatch. + * @template TParam The parameter names of the requested URL. + * @param name A unique name for the collection dispatcher. + * @param itemType The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the collection dispatcher. + * The syntax is based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). + * The path must have one or more variables. + * @param dispatcher A collection dispatcher callback to register. + */ + setCollectionDispatcher( + name: string | symbol, + itemType: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< + TParam + >}${string}`, + dispatcher: CustomCollectionDispatcher< + TObject, + TParam, + RequestContext, + TContextData + >, + ): CustomCollectionCallbackSetters< + TParam, + RequestContext, + TContextData + >; + + /** + * Registers a collection of objects dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of objects to dispatch. + * @template TParam The parameter names of the requested URL. + * @param name A unique name for the collection dispatcher. + * @param itemType The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the collection dispatcher. + * The syntax is based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). + * The path must have one or more variables. + * @param dispatcher A collection dispatcher callback to register. + */ + setCollectionDispatcher( + name: string | symbol, + itemType: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}`, dispatcher: CustomCollectionDispatcher< TObject, TParam, @@ -443,7 +613,77 @@ export interface Federatable { >( name: string | symbol, itemType: ConstructorWithTypeId, - path: string, + path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< + TParam + >}${string}${Rfc6570Expression}${string}`, + dispatcher: CustomCollectionDispatcher< + TObject, + TParam, + RequestContext, + TContextData + >, + ): CustomCollectionCallbackSetters< + TParam, + RequestContext, + TContextData + >; + + /** + * Registers an ordered collection of objects dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of objects to dispatch. + * @template TParam The parameter names of the requested URL. + * @param name A unique name for the collection dispatcher. + * @param itemType The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the collection dispatcher. + * The syntax is based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). + * The path must have one or more variables. + * @param dispatcher A collection dispatcher callback to register. + */ + setOrderedCollectionDispatcher< + TObject extends Object, + TParam extends string, + >( + name: string | symbol, + itemType: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}${Rfc6570Expression< + TParam + >}${string}`, + dispatcher: CustomCollectionDispatcher< + TObject, + TParam, + RequestContext, + TContextData + >, + ): CustomCollectionCallbackSetters< + TParam, + RequestContext, + TContextData + >; + + /** + * Registers an ordered collection of objects dispatcher. + * + * @template TContextData The context data to pass to the {@link Context}. + * @template TObject The type of objects to dispatch. + * @template TParam The parameter names of the requested URL. + * @param name A unique name for the collection dispatcher. + * @param itemType The Activity Vocabulary class of the object to dispatch. + * @param path The URI path pattern for the collection dispatcher. + * The syntax is based on URI Template + * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). + * The path must have one or more variables. + * @param dispatcher A collection dispatcher callback to register. + */ + setOrderedCollectionDispatcher< + TObject extends Object, + TParam extends string, + >( + name: string | symbol, + itemType: ConstructorWithTypeId, + path: `${string}${Rfc6570Expression}${string}`, dispatcher: CustomCollectionDispatcher< TObject, TParam, From 878ab20a2b67e01b8d88431aa13e2e2d1b458384 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Tue, 9 Jun 2026 09:39:51 +0000 Subject: [PATCH 4/5] Add changelog entry for dispatcher type-check speedup Record in CHANGES.md that TypeScript type-checking was sped up by simplifying the internal `path` parameter types of the object, collection, and ordered collection dispatcher methods, dropping a full codebase type check from ~99s to ~13s. https://github.com/fedify-dev/fedify/issues/613 https://github.com/fedify-dev/fedify/pull/800 Assisted-by: Claude Code:claude-opus-4-8 --- CHANGES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ab426ace9..78f0cdf32 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -248,8 +248,18 @@ To be released. matching. The deprecated `Router` export from *@fedify/fedify* remains available for compatibility. [[#418], [#758] by ChanHaeng Lee] + - Significantly sped up TypeScript type-checking by simplifying the internal + `path` parameter types of the `setObjectDispatcher()`, + `setCollectionDispatcher()`, and `setOrderedCollectionDispatcher()` methods. + These methods previously expanded `path` into thousands of RFC 6570 + template-literal variants, which dominated type-checking time; a full + codebase type check now completes in roughly 13 seconds instead of around + 99 seconds. The public dispatcher method signatures and runtime path + validation are unchanged. [[#613], [#800] by ChanHaeng Lee] + [#316]: https://github.com/fedify-dev/fedify/issues/316 [#418]: https://github.com/fedify-dev/fedify/issues/418 +[#613]: https://github.com/fedify-dev/fedify/issues/613 [#619]: https://github.com/fedify-dev/fedify/issues/619 [#620]: https://github.com/fedify-dev/fedify/issues/620 [#735]: https://github.com/fedify-dev/fedify/issues/735 @@ -276,6 +286,7 @@ To be released. [#778]: https://github.com/fedify-dev/fedify/pull/778 [#782]: https://github.com/fedify-dev/fedify/issues/782 [#787]: https://github.com/fedify-dev/fedify/pull/787 +[#800]: https://github.com/fedify-dev/fedify/pull/800 ### @fedify/cli From bb2ef0a17c7e2961231dcb6308ee4e24ecd77d26 Mon Sep 17 00:00:00 2001 From: ChanHaeng Lee <2chanhaeng@gmail.com> Date: Wed, 10 Jun 2026 03:36:29 +0000 Subject: [PATCH 5/5] Address review feedback on dispatcher path types Document on setObjectDispatcher(), setCollectionDispatcher(), and setOrderedCollectionDispatcher() that the RFC 6570 template-literal `path` overloads were removed for type-checking efficiency, so URI variable types can no longer be inferred from `path` and the variable name should be supplied through the `TParam` generic argument instead. Also clarify in CHANGES.md that this is a partial fix for the issue below, targeting the dispatcher overload hot path; other contributors to check-all cost may remain. Requested by @sij411 in https://github.com/fedify-dev/fedify/pull/800#pullrequestreview-4458410331 https://github.com/fedify-dev/fedify/issues/613 https://github.com/fedify-dev/fedify/pull/800 Assisted-by: Claude Code:claude-opus-4-8 --- CHANGES.md | 4 +++- packages/fedify/src/federation/builder.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 78f0cdf32..397f897ae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -255,7 +255,9 @@ To be released. template-literal variants, which dominated type-checking time; a full codebase type check now completes in roughly 13 seconds instead of around 99 seconds. The public dispatcher method signatures and runtime path - validation are unchanged. [[#613], [#800] by ChanHaeng Lee] + validation are unchanged. This is a partial fix for [#613] that targets + the dispatcher overload hot path; other contributors to `check-all` cost + may remain. [[#613], [#800] by ChanHaeng Lee] [#316]: https://github.com/fedify-dev/fedify/issues/316 [#418]: https://github.com/fedify-dev/fedify/issues/418 diff --git a/packages/fedify/src/federation/builder.ts b/packages/fedify/src/federation/builder.ts index 6b8b9a29d..1503ccf7b 100644 --- a/packages/fedify/src/federation/builder.ts +++ b/packages/fedify/src/federation/builder.ts @@ -593,6 +593,12 @@ export class FederationBuilderImpl this.webFingerLinksDispatcher = dispatcher; } + /** + * The RFC 6570 template-literal `path` overloads were removed for + * type-checking efficiency, so the URI variable types can no longer be + * inferred from `path` (now typed as a plain `string`); to use them, specify + * the variable name through the `TParam` generic argument. + */ setObjectDispatcher( cls: ConstructorWithTypeId, path: string, @@ -1216,6 +1222,12 @@ export class FederationBuilderImpl return setters; } + /** + * The RFC 6570 template-literal `path` overloads were removed for + * type-checking efficiency, so the URI variable types can no longer be + * inferred from `path` (now typed as a plain `string`); to use them, specify + * the variable name through the `TParam` generic argument. + */ setCollectionDispatcher< TObject extends Object, TParam extends string, @@ -1243,6 +1255,12 @@ export class FederationBuilderImpl ); } + /** + * The RFC 6570 template-literal `path` overloads were removed for + * type-checking efficiency, so the URI variable types can no longer be + * inferred from `path` (now typed as a plain `string`); to use them, specify + * the variable name through the `TParam` generic argument. + */ setOrderedCollectionDispatcher< TObject extends Object, TParam extends string,