@fedify/fedify
Version:
An ActivityPub server framework
1,202 lines (1,201 loc) • 81.3 kB
TypeScript
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