UNPKG

@fedify/fedify

Version:

An ActivityPub server framework

1,202 lines (1,201 loc) • 81.3 kB
import { Temporal } from "@js-temporal/polyfill"; import { URLPattern } from "urlpattern-polyfill"; import { KvKey, KvStore } from "./kv-DRaeSXco.js"; import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions } from "./docloader-Q42SMRIB.js"; import { GetNodeInfoOptions, JsonValue, NodeInfo } from "./client-DvtwXO7t.js"; import { Activity, Collection, CryptographicKey, Hashtag, Link, Multikey, Object as Object$1 } from "./vocab-CzEfWQk2.js"; import { Actor, Recipient } from "./actor-CPpvuBKU.js"; import { HttpMessageSignaturesSpec } from "./http-DMTrO3Ye.js"; import { GetKeyOwnerOptions } from "./owner-D0cOz8R5.js"; import { LookupObjectOptions, TraverseCollectionOptions } from "./mod-CDzlVCUF.js"; import { LookupWebFingerOptions, ResourceDescriptor } from "./lookup-Bf-K85bV.js"; import { MessageQueue } from "./mq-DYKDDJmp.js"; import { Span, TracerProvider } from "@opentelemetry/api"; //#region compat/types.d.ts /** * A function that transforms an activity object. * @since 1.4.0 */ type ActivityTransformer<TContextData> = (activity: Activity, context: Context<TContextData>) => Activity; //#endregion //#region federation/collection.d.ts /** * A page of items. */ interface PageItems<TItem> { prevCursor?: string | null; nextCursor?: string | null; items: TItem[]; } /** * Calculates the [partial follower collection digest][1]. * * [1]: https://w3id.org/fep/8fcf#partial-follower-collection-digest * @param uris The URIs to calculate the digest. Duplicate URIs are ignored. * @returns The digest. */ declare function digest(uris: Iterable<string | URL>): Promise<Uint8Array>; /** * Builds [`Collection-Synchronization`][1] header content. * * [1]: https://w3id.org/fep/8fcf#the-collection-synchronization-http-header * * @param collectionId The sender's followers collection URI. * @param actorIds The actor URIs to digest. * @returns The header content. */ declare function buildCollectionSynchronizationHeader(collectionId: string | URL, actorIds: Iterable<string | URL>): Promise<string>; //#endregion //#region federation/send.d.ts /** * A key pair for an actor who sends an activity. * @since 0.10.0 */ interface SenderKeyPair { /** * The actor's private key to sign the request. */ privateKey: CryptoKey; /** * The public key ID that corresponds to the private key. */ keyId: URL; } /** * Parameters for {@link sendActivity}. */ //#endregion //#region federation/callback.d.ts /** * A callback that dispatches a {@link NodeInfo} object. * * @typeParam TContextData The context data to pass to the {@link Context}. */ type NodeInfoDispatcher<TContextData> = (context: RequestContext<TContextData>) => NodeInfo | Promise<NodeInfo>; /** * A callback that dispatches an {@link Actor} object. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param identifier The actor's internal identifier or username. */ type ActorDispatcher<TContextData> = (context: RequestContext<TContextData>, identifier: string) => Actor | null | Promise<Actor | null>; /** * A callback that dispatches key pairs for an actor. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The context. * @param identifier The actor's internal identifier or username. * @returns The key pairs. * @since 0.10.0 */ type ActorKeyPairsDispatcher<TContextData> = (context: Context<TContextData>, identifier: string) => CryptoKeyPair[] | Promise<CryptoKeyPair[]>; /** * A callback that maps a WebFinger username to the corresponding actor's * internal identifier, or `null` if the username is not found. * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The context. * @param username The WebFinger username. * @returns The actor's internal identifier, or `null` if the username is not * found. * @since 0.15.0 */ type ActorHandleMapper<TContextData> = (context: Context<TContextData>, username: string) => string | null | Promise<string | null>; /** * A callback that maps a WebFinger query to the corresponding actor's * internal identifier or username, or `null` if the query is not found. * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param resource The URL that was queried through WebFinger. * @returns The actor's internal identifier or username, or `null` if the query * is not found. * @since 1.4.0 */ type ActorAliasMapper<TContextData> = (context: RequestContext<TContextData>, resource: URL) => { identifier: string; } | { username: string; } | null | Promise<{ identifier: string; } | { username: string; } | null>; /** * A callback that dispatches an object. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam TParam The parameter names of the requested URL. * @since 0.7.0 */ type ObjectDispatcher<TContextData, TObject extends Object$1, TParam extends string> = (context: RequestContext<TContextData>, values: Record<TParam, string>) => TObject | null | Promise<TObject | null>; /** * A callback that dispatches a collection. * * @typeParam TItem The type of items in the collection. * @typeParam TContext The type of the context. {@link Context} or * {@link RequestContext}. * @typeParam TContextData The context data to pass to the `TContext`. * @typeParam TFilter The type of the filter, if any. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param cursor The cursor to start the collection from, or `null` to dispatch * the entire collection without pagination. * @param filter The filter to apply to the collection, if any. */ type CollectionDispatcher<TItem, TContext extends Context<TContextData>, TContextData, TFilter> = (context: TContext, identifier: string, cursor: string | null, filter?: TFilter) => PageItems<TItem> | null | Promise<PageItems<TItem> | null>; /** * A callback that counts the number of items in a collection. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param filter The filter to apply to the collection, if any. */ type CollectionCounter<TContextData, TFilter> = (context: RequestContext<TContextData>, identifier: string, filter?: TFilter) => number | bigint | null | Promise<number | bigint | null>; /** * A callback that returns a cursor for a collection. * * @typeParam TContext The type of the context. {@link Context} or * {@link RequestContext}. * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TFilter The type of the filter, if any. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param filter The filter to apply to the collection, if any. */ type CollectionCursor<TContext extends Context<TContextData>, TContextData, TFilter> = (context: TContext, identifier: string, filter?: TFilter) => string | null | Promise<string | null>; /** * A callback that listens for activities in an inbox. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TActivity The type of activity to listen for. * @param context The inbox context. * @param activity The activity that was received. */ type InboxListener<TContextData, TActivity extends Activity> = (context: InboxContext<TContextData>, activity: TActivity) => void | Promise<void>; /** * A callback that handles errors in an inbox. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The inbox context. */ type InboxErrorHandler<TContextData> = (context: Context<TContextData>, error: Error) => void | Promise<void>; /** * A callback that dispatches the key pair for the authenticated document loader * of the {@link Context} passed to the shared inbox listener. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The context. * @returns The username or the internal identifier of the actor or the key pair * for the authenticated document loader of the {@link Context} passed * to the shared inbox listener. If `null` is returned, the request is * not authorized. * @since 0.11.0 */ type SharedInboxKeyDispatcher<TContextData> = (context: Context<TContextData>) => SenderKeyPair | { identifier: string; } | { username: string; } | { handle: string; } | null | Promise<SenderKeyPair | { identifier: string; } | { username: string; } | { handle: string; } | null>; /** * A callback that handles errors during outbox processing. * * @param error The error that occurred. * @param activity The activity that caused the error. If it is `null`, the * error occurred during deserializing the activity. * @since 0.6.0 */ type OutboxErrorHandler = (error: Error, activity: Activity | null) => void | Promise<void>; /** * A callback that determines if a request is authorized or not. * * @typeParam TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param identifier The internal identifier of the actor that is being requested. * @param signedKey *Deprecated in Fedify 1.5.0 in favor of * {@link RequestContext.getSignedKey} method.* * The key that was used to sign the request, or `null` if * the request was not signed or the signature was invalid. * @param signedKeyOwner *Deprecated in Fedify 1.5.0 in favor of * {@link RequestContext.getSignedKeyOwner} method.* * The actor that owns the key that was used to sign the * request, or `null` if the request was not signed or the * signature was invalid, or if the key is not associated * with an actor. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ type AuthorizePredicate<TContextData> = (context: RequestContext<TContextData>, identifier: string, signedKey: CryptographicKey | null, signedKeyOwner: Actor | null) => boolean | Promise<boolean>; /** * A callback that determines if a request is authorized or not. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TParam The parameter names of the requested URL. * @param context The request context. * @param values The parameters of the requested URL. * @param signedKey *Deprecated in Fedify 1.5.0 in favor of * {@link RequestContext.getSignedKey} method.* * The key that was used to sign the request, or `null` if * the request was not signed or the signature was invalid. * @param signedKeyOwner *Deprecated in Fedify 1.5.0 in favor of * {@link RequestContext.getSignedKeyOwner} method.* * The actor that owns the key that was used to sign the * request, or `null` if the request was not signed or the * signature was invalid, or if the key is not associated * with an actor. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ type ObjectAuthorizePredicate<TContextData, TParam extends string> = (context: RequestContext<TContextData>, values: Record<TParam, string>, signedKey: CryptographicKey | null, signedKeyOwner: Actor | null) => boolean | Promise<boolean>; //#endregion //#region federation/handler.d.ts /** * Options for the {@link respondWithObject} and * {@link respondWithObjectIfAcceptable} functions. * @since 0.3.0 */ interface RespondWithObjectOptions { /** * The document loader to use for compacting JSON-LD. * @since 0.8.0 */ contextLoader: DocumentLoader; } /** * Responds with the given object in JSON-LD format. * * @param object The object to respond with. * @param options Options. * @since 0.3.0 */ declare function respondWithObject(object: Object$1, options?: RespondWithObjectOptions): Promise<Response>; /** * Responds with the given object in JSON-LD format if the request accepts * JSON-LD. * * @param object The object to respond with. * @param request The request to check for JSON-LD acceptability. * @param options Options. * @since 0.3.0 */ declare function respondWithObjectIfAcceptable(object: Object$1, request: Request, options?: RespondWithObjectOptions): Promise<Response | null>; //#endregion //#region federation/router.d.ts /** * Options for the {@link Router}. * @since 0.12.0 */ interface RouterOptions { /** * Whether to ignore trailing slashes when matching paths. */ trailingSlashInsensitive?: boolean; } /** * The result of {@link Router.route} method. * @since 1.3.0 */ interface RouterRouteResult { /** * The matched route name. */ name: string; /** * The URL template of the matched route. */ template: string; /** * The values extracted from the URL. */ values: Record<string, string>; } /** * URL router and constructor based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). */ declare class Router { #private; /** * Whether to ignore trailing slashes when matching paths. * @since 1.6.0 */ trailingSlashInsensitive: boolean; /** * Create a new {@link Router}. * @param options Options for the router. */ constructor(options?: RouterOptions); clone(): Router; /** * Checks if a path name exists in the router. * @param name The name of the path. * @returns `true` if the path name exists, otherwise `false`. */ has(name: string): boolean; /** * Adds a new path rule to the router. * @param template The path pattern. * @param name The name of the path. * @returns The names of the variables in the path pattern. */ add(template: string, name: string): Set<string>; /** * Resolves a path name and values from a URL, if any match. * @param url The URL to resolve. * @returns The name of the path and its values, if any match. Otherwise, * `null`. */ route(url: string): RouterRouteResult | null; /** * Constructs a URL/path from a path name and values. * @param name The name of the path. * @param values The values to expand the path with. * @returns The URL/path, if the name exists. Otherwise, `null`. */ build(name: string, values: Record<string, string>): string | null; } /** * An error thrown by the {@link Router}. */ declare class RouterError extends Error { /** * Create a new {@link RouterError}. * @param message The error message. */ constructor(message: string); } //#endregion //#region federation/builder.d.ts /** * Creates a new {@link FederationBuilder} instance. * @returns A new {@link FederationBuilder} instance. * @since 1.6.0 */ declare function createFederationBuilder<TContextData>(): FederationBuilder<TContextData>; //#endregion //#region federation/queue.d.ts interface SenderKeyJwkPair { keyId: string; privateKey: JsonWebKey; } /** * A message that represents a task to be processed by the background worker. * The concrete type of the message depends on the `type` property. * * Please do not depend on the concrete types of the messages, as they may * change in the future. You should treat the `Message` type as an opaque * type. * @since 1.6.0 */ type Message = FanoutMessage | OutboxMessage | InboxMessage; interface FanoutMessage { type: "fanout"; id: ReturnType<typeof crypto.randomUUID>; baseUrl: string; keys: SenderKeyJwkPair[]; inboxes: Record<string, { actorIds: string[]; sharedInbox: boolean; }>; activity: unknown; activityId?: string; activityType: string; collectionSync?: string; traceContext: Record<string, string>; } interface OutboxMessage { type: "outbox"; id: ReturnType<typeof crypto.randomUUID>; baseUrl: string; keys: SenderKeyJwkPair[]; activity: unknown; activityId?: string; activityType: string; inbox: string; sharedInbox: boolean; started: string; attempt: number; headers: Record<string, string>; traceContext: Record<string, string>; } interface InboxMessage { type: "inbox"; id: ReturnType<typeof crypto.randomUUID>; baseUrl: string; activity: unknown; started: string; attempt: number; identifier: string | null; traceContext: Record<string, string>; } //#endregion //#region federation/retry.d.ts /** * The context passed to a {@link RetryPolicy} callback. * @since 0.12.0 */ interface RetryContext { /** * The elapsed time since the first attempt. */ readonly elapsedTime: Temporal.Duration; /** * The number of attempts so far. */ readonly attempts: number; } /** * A policy that determines the delay before the next retry. * @param context The retry context. * @returns The delay before the next retry, or `null` to stop retrying. * It must not negative. * @since 0.12.0 */ type RetryPolicy = (context: RetryContext) => Temporal.Duration | null; /** * Options for {@link createExponentialBackoffPolicy} function. * @since 0.12.0 */ interface CreateExponentialBackoffPolicyOptions { /** * The initial delay before the first retry. Defaults to 1 second. */ readonly initialDelay?: Temporal.DurationLike; /** * The maximum delay between retries. Defaults to 12 hours. */ readonly maxDelay?: Temporal.DurationLike; /** * The maximum number of attempts before giving up. * Defaults to 10. */ readonly maxAttempts?: number; /** * The factor to multiply the previous delay by for each retry. * Defaults to 2. */ readonly factor?: number; /** * Whether to add jitter to the delay to avoid synchronization. * Turned on by default. */ readonly jitter?: boolean; } /** * Creates an exponential backoff retry policy. The delay between retries * starts at the `initialDelay` and is multiplied by the `factor` for each * subsequent retry, up to the `maxDelay`. The policy will give up after * `maxAttempts` attempts. The actual delay is randomized to avoid * synchronization (jitter). * @param options The options for the policy. * @returns The retry policy. * @since 0.12.0 */ declare function createExponentialBackoffPolicy(options?: CreateExponentialBackoffPolicyOptions): RetryPolicy; //#endregion //#region federation/middleware.d.ts /** * Options for {@link createFederation} function. * @typeParam TContextData The type of the context data. * @since 0.10.0 * @deprecated Use {@link FederationOptions} instead. */ interface CreateFederationOptions<TContextData> extends FederationOptions<TContextData> {} /** * Configures the task queues for sending and receiving activities. * @since 1.3.0 */ interface FederationQueueOptions { /** * The message queue for incoming activities. If not provided, incoming * activities will not be queued and will be processed immediately. */ inbox?: MessageQueue; /** * The message queue for outgoing activities. If not provided, outgoing * activities will not be queued and will be sent immediately. */ outbox?: MessageQueue; /** * The message queue for fanning out outgoing activities. If not provided, * outgoing activities will not be fanned out in the background, but will be * fanned out immediately, which causes slow response times on * {@link Context.sendActivity} calls. */ fanout?: MessageQueue; } /** * Prefixes for namespacing keys in the Deno KV store. */ interface FederationKvPrefixes { /** * The key prefix used for storing whether activities have already been * processed or not. * @default `["_fedify", "activityIdempotence"]` */ activityIdempotence: KvKey; /** * The key prefix used for storing remote JSON-LD documents. * @default `["_fedify", "remoteDocument"]` */ remoteDocument: KvKey; /** * The key prefix used for caching public keys. * @default `["_fedify", "publicKey"]` * @since 0.12.0 */ publicKey: KvKey; /** * The key prefix used for caching HTTP Message Signatures specs. * The cached spec is used to reduce the number of requests to make signed * requests ("double-knocking" technique). * @default `["_fedify", "httpMessageSignaturesSpec"]` * @since 1.6.0 */ httpMessageSignaturesSpec: KvKey; } /** * Options for {@link CreateFederationOptions.origin} when it is not a string. * @since 1.5.0 */ interface FederationOrigin { /** * The canonical hostname for fediverse handles (which are looked up through * WebFinger). This is used for WebFinger lookups. It has to be a valid * hostname, e.g., `"example.com"`. */ handleHost: string; /** * The canonical origin for web URLs. This is used for constructing absolute * URLs. It has to start with either `"http://"` or `"https://"`, and must * not contain a path or query string, e.g., `"https://example.com"`. */ webOrigin: string; } /** * Create a new {@link Federation} instance. * @param parameters Parameters for initializing the instance. * @returns A new {@link Federation} instance. * @since 0.10.0 */ declare function createFederation<TContextData>(options: CreateFederationOptions<TContextData>): Federation<TContextData>; //#endregion //#region federation/federation.d.ts /** * Options for {@link Federation.startQueue} method. * @since 1.0.0 */ interface FederationStartQueueOptions { /** * The signal to abort the task queue. */ signal?: AbortSignal; /** * Starts the task worker only for the specified queue. If unspecified, * which is the default, the task worker starts for all three queues: * inbox, outbox, and fanout. * @since 1.3.0 */ queue?: "inbox" | "outbox" | "fanout"; } /** * A common interface between {@link Federation} and {@link FederationBuilder}. * @typeParam TContextData The context data to pass to the {@link Context}. * @since 1.6.0 */ interface Federatable<TContextData> { /** * Registers a NodeInfo dispatcher. * @param path The URI path pattern for the NodeInfo dispatcher. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have no variables. * @param dispatcher A NodeInfo dispatcher callback to register. * @throws {RouterError} Thrown if the path pattern is invalid. */ setNodeInfoDispatcher(path: string, dispatcher: NodeInfoDispatcher<TContextData>): void; /** * Registers an actor dispatcher. * * @example * ``` typescript * federation.setActorDispatcher( * "/users/{identifier}", * async (ctx, identifier) => { * return new Person({ * id: ctx.getActorUri(identifier), * // ... * }); * } * ); * ``` * * @param path The URI path pattern for the actor dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher An actor dispatcher callback to register. * @returns An object with methods to set other actor dispatcher callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setActorDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: ActorDispatcher<TContextData>): ActorCallbackSetters<TContextData>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @typeParam TContextData The context data to pass to the {@link Context}. * @typeParam TObject The type of object to dispatch. * @typeParam 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<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & { typeId: URL; }, path: `${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an inbox dispatcher. * * @param path The URI path pattern for the inbox dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`, and must match * the inbox listener path. * @param dispatcher An inbox dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setInboxDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers an outbox dispatcher. * * @example * ``` typescript * federation.setOutboxDispatcher( * "/users/{identifier}/outbox", * async (ctx, identifier, options) => { * let items: Activity[]; * let nextCursor: string; * // ... * return { items, nextCursor }; * } * ); * ``` * * @param path The URI path pattern for the outbox dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher An outbox dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setOutboxDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a following collection dispatcher. * @param path The URI path pattern for the following collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A following collection callback to register. * @returns An object with methods to set other following collection * callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setFollowingDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Actor | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a followers collection dispatcher. * @param path The URI path pattern for the followers collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A followers collection callback to register. * @returns An object with methods to set other followers collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setFollowersDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Recipient, Context<TContextData>, TContextData, URL>): CollectionCallbackSetters<Context<TContextData>, TContextData, URL>; /** * Registers a liked collection dispatcher. * @param path The URI path pattern for the liked collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A liked collection callback to register. * @returns An object with methods to set other liked collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setLikedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1 | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a featured collection dispatcher. * @param path The URI path pattern for the featured collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A featured collection callback to register. * @returns An object with methods to set other featured collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setFeaturedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a featured tags collection dispatcher. * @param path The URI path pattern for the featured tags collection. * The syntax is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A featured tags collection callback to register. * @returns An object with methods to set other featured tags collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setFeaturedTagsDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Hashtag, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Assigns the URL path for the inbox and starts setting inbox listeners. * * @example * ``` typescript * federation * .setInboxListeners("/users/{identifier}/inbox", "/inbox") * .on(Follow, async (ctx, follow) => { * const from = await follow.getActor(ctx); * if (!isActor(from)) return; * // ... * }) * .on(Undo, async (ctx, undo) => { * // ... * }); * ``` * * @param inboxPath The URI path pattern for the inbox. The syntax is based * on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). * The path must have one variable: `{identifier}`, and must * match the inbox dispatcher path. * @param sharedInboxPath An optional URI path pattern for the shared inbox. * The syntax is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). * The path must have no variables. * @returns An object to register inbox listeners. * @throws {RouteError} Thrown if the path pattern is invalid. */ setInboxListeners(inboxPath: `${string}{identifier}${string}` | `${string}{handle}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>; } /** * An object that registers federation-related business logic and dispatches * requests to the appropriate handlers. * * It also provides a middleware interface for handling requests before your * web framework's router; see {@link Federation.fetch}. * @typeParam TContextData The context data to pass to the {@link Context}. * @since 0.13.0 */ interface Federation<TContextData> extends Federatable<TContextData> { /** * Manually start the task queue. * * This method is useful when you set the `manuallyStartQueue` option to * `true` in the {@link createFederation} function. * @param contextData The context data to pass to the context. * @param options Additional options for starting the queue. */ startQueue(contextData: TContextData, options?: FederationStartQueueOptions): Promise<void>; /** * Processes a queued message task. This method handles different types of * tasks such as fanout, outbox, and inbox messages. * * Note that you usually do not need to call this method directly unless you * are deploying your federated application on a platform that does not * support long-running processing, such as Cloudflare Workers. * @param contextData The context data to pass to the context. * @param message The message that represents the task to be processed. * @returns A promise that resolves when the message has been processed. * @since 1.6.0 */ processQueuedTask(contextData: TContextData, message: Message): Promise<void>; /** * Create a new context. * @param baseUrl The base URL of the server. The `pathname` remains root, * and the `search` and `hash` are stripped. * @param contextData The context data to pass to the context. * @returns The new context. */ createContext(baseUrl: URL, contextData: TContextData): Context<TContextData>; /** * Create a new context for a request. * @param request The request object. * @param contextData The context data to pass to the context. * @returns The new request context. */ createContext(request: Request, contextData: TContextData): RequestContext<TContextData>; /** * Handles a request related to federation. If a request is not related to * federation, the `onNotFound` or `onNotAcceptable` callback is called. * * Usually, this method is called from a server's request handler or * a web framework's middleware. * * @param request The request object. * @param parameters The parameters for handling the request. * @returns The response to the request. */ fetch(request: Request, options: FederationFetchOptions<TContextData>): Promise<Response>; } /** * A builder for creating a {@link Federation} object. It defers the actual * instantiation of the {@link Federation} object until the {@link build} * method is called so that dispatchers and listeners can be registered * before the {@link Federation} object is instantiated. * @typeParam TContextData The context data to pass to the {@link Context}. * @since 1.6.0 */ interface FederationBuilder<TContextData> extends Federatable<TContextData> { /** * Builds the federation object. * @returns The federation object. */ build(options: FederationOptions<TContextData>): Promise<Federation<TContextData>>; } /** * Options for creating a {@link Federation} object. * @typeParam TContextData The context data to pass to the {@link Context}. * @since 1.6.0 */ interface FederationOptions<TContextData> { /** * The key–value store used for caching, outbox queues, and inbox idempotence. */ kv: KvStore; /** * Prefixes for namespacing keys in the Deno KV store. By default, all keys * are prefixed with `["_fedify"]`. */ kvPrefixes?: Partial<FederationKvPrefixes>; /** * The message queue for sending and receiving activities. If not provided, * activities will not be queued and will be processed immediately. * * If a `MessageQueue` is provided, both the `inbox` and `outbox` queues * will be set to the same queue. * * If a `FederationQueueOptions` object is provided, you can set the queues * separately (since Fedify 1.3.0). */ queue?: FederationQueueOptions | MessageQueue; /** * Whether to start the task queue manually or automatically. * * If `true`, the task queue will not start automatically and you need to * manually start it by calling the {@link Federation.startQueue} method. * * If `false`, the task queue will start automatically as soon as * the first task is enqueued. * * By default, the queue starts automatically. * * @since 0.12.0 */ manuallyStartQueue?: boolean; /** * The canonical base URL of the server. This is used for constructing * absolute URLs and fediverse handles. * @since 1.5.0 */ origin?: string | FederationOrigin; /** * A custom JSON-LD document loader factory. By default, this uses * the built-in cache-backed loader that fetches remote documents over * HTTP(S). * @since 1.4.0 */ documentLoaderFactory?: DocumentLoaderFactory; /** * A custom JSON-LD context loader factory. By default, this uses the same * loader as the document loader. * @since 1.4.0 */ contextLoaderFactory?: DocumentLoaderFactory; /** * A custom JSON-LD document loader. By default, this uses the built-in * cache-backed loader that fetches remote documents over HTTP(S). * @deprecated Use {@link documentLoaderFactory} instead. */ documentLoader?: DocumentLoader; /** * A custom JSON-LD context loader. By default, this uses the same loader * as the document loader. * @deprecated Use {@link contextLoaderFactory} instead. */ contextLoader?: DocumentLoader; /** * A factory function that creates an authenticated document loader for a * given identity. This is used for fetching documents that require * authentication. */ authenticatedDocumentLoaderFactory?: AuthenticatedDocumentLoaderFactory; /** * Whether to allow fetching private network addresses in the document loader. * * If turned on, {@link CreateFederationOptions.documentLoader}, * {@link CreateFederationOptions.contextLoader}, and * {@link CreateFederationOptions.authenticatedDocumentLoaderFactory} * cannot be configured. * * Mostly useful for testing purposes. *Do not use in production.* * * Turned off by default. * @since 0.15.0 */ allowPrivateAddress?: boolean; /** * Options for making `User-Agent` strings for HTTP requests. * If a string is provided, it is used as the `User-Agent` header. * If an object is provided, it is passed to the {@link getUserAgent} * function. * @since 1.3.0 */ userAgent?: GetUserAgentOptions | string; /** * A callback that handles errors during outbox processing. Note that this * callback can be called multiple times for the same activity, because * the delivery is retried according to the backoff schedule until it * succeeds or reaches the maximum retry count. * * If any errors are thrown in this callback, they are ignored. */ onOutboxError?: OutboxErrorHandler; /** * The time window for verifying HTTP Signatures of incoming requests. If the * request is older or newer than this window, it is rejected. Or if it is * `false`, the request's timestamp is not checked at all. * * By default, the window is an hour. */ signatureTimeWindow?: Temporal.Duration | Temporal.DurationLike | false; /** * Whether to skip HTTP Signatures verification for incoming activities. * This is useful for testing purposes, but should not be used in production. * * By default, this is `false` (i.e., signatures are verified). * @since 0.13.0 */ skipSignatureVerification?: boolean; /** * The HTTP Signatures specification to use for the first signature * attempt when communicating with unknown servers. This option affects * the "double-knocking" mechanism as described in the ActivityPub HTTP * Signature documentation. * * When making HTTP requests to servers that haven't been encountered before, * Fedify will first attempt to sign the request using the specified * signature specification. If the request fails, it will retry with the * alternative specification. * * Defaults to `"rfc9421"` (HTTP Message Signatures). * * @see {@link https://swicg.github.io/activitypub-http-signature/#how-to-upgrade-supported-versions} * @default `"rfc9421"` * @since 1.7.0 */ firstKnock?: HttpMessageSignaturesSpec; /** * The retry policy for sending activities to recipients' inboxes. * By default, this uses an exponential backoff strategy with a maximum of * 10 attempts and a maximum delay of 12 hours. * @since 0.12.0 */ outboxRetryPolicy?: RetryPolicy; /** * The retry policy for processing incoming activities. By default, this * uses an exponential backoff strategy with a maximum of 10 attempts and a * maximum delay of 12 hours. * @since 0.12.0 */ inboxRetryPolicy?: RetryPolicy; /** * Activity transformers that are applied to outgoing activities. It is * useful for adjusting outgoing activities to satisfy some ActivityPub * implementations. * * By default, {@link defaultActivityTransformers} are applied. * @since 1.4.0 */ activityTransformers?: readonly ActivityTransformer<TContextData>[]; /** * Whether the router should be insensitive to trailing slashes in the URL * paths. For example, if this option is `true`, `/foo` and `/foo/` are * treated as the same path. Turned off by default. * @since 0.12.0 */ trailingSlashInsensitive?: boolean; /** * The OpenTelemetry tracer provider for tracing operations. If not provided, * the default global tracer provider is used. * @since 1.3.0 */ tracerProvider?: TracerProvider; } /** * Additional settings for the actor dispatcher. * * ``` typescript * const federation = createFederation<void>({ ... }); * federation * .setActorDispatcher("/users/{identifier}", async (ctx, identifier) => { * // ... * }) * .setKeyPairsDispatcher(async (ctxData, identifier) => { * // ... * }); * ``` */ interface ActorCallbackSetters<TContextData> { /** * Sets the key pairs dispatcher for actors. * @param dispatcher A callback that returns the key pairs for an actor. * @returns The setters object so that settings can be chained. * @since 0.10.0 */ setKeyPairsDispatcher(dispatcher: ActorKeyPairsDispatcher<TContextData>): ActorCallbackSetters<TContextData>; /** * Sets the callback function that maps a WebFinger username to * the corresponding actor's identifier. If it's omitted, the identifier * is assumed to be the same as the WebFinger username, which makes your * actors have the immutable handles. If you want to let your actors change * their fediverse handles, you should set this dispatcher. * @param mapper A callback that maps a WebFinger username to * the corresponding actor's identifier. * @returns The setters object so that settings can be chained. * @since 0.15.0 */ mapHandle(mapper: ActorHandleMapper<TContextData>): ActorCallbackSetters<TContextData>; /** * Sets the callback function that maps a WebFinger query to the corresponding * actor's identifier or username. If it's omitted, the WebFinger handler * only supports the actor URIs and `acct:` URIs. If you want to support * other queries, you should set this dispatcher. * @param mapper A callback that maps a WebFinger query to the corresponding * actor's identifier or username. * @returns The setters object so that settings can be chained. * @since 1.4.0 */ mapAlias(mapper: ActorAliasMapper<TContextData>): ActorCallbackSetters<TContextData>; /** * Specifies the conditions under which requests are authorized. * @param predicate A callback that returns whether a request is authorized. * @returns The setters object so that settings can be chained. * @since 0.7.0 */ authorize(predicate: AuthorizePredicate<TContextData>): ActorCallbackSetters<TContextData>; } /** * Additional settings for an object dispatcher. */ interface ObjectCallbackSetters<TContextData, TObject extends Object$1, TParam extends string> { /** * Specifies the conditions under which requests are authorized. * @param predicate A callback that returns whether a request is authorized. * @returns The setters object so that settings can be chained. * @since 0.7.0 */ authorize(predicate: ObjectAuthorizePredicate<TContextData, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; } /** * Additional settings for a collection dispatcher. * * @typeParam TContext The type of the context. {@link Context} or * {@link RequestContext}. * @typeParam TContextData The contex