Loading federation/handler.ts +39 −17 Original line number Diff line number Diff line Loading @@ -5,9 +5,6 @@ import { CollectionCursor, CollectionDispatcher, InboxListener, OutboxCounter, OutboxCursor, OutboxDispatcher, } from "./callback.ts"; import { RequestContext } from "./context.ts"; import { verify } from "../httpsig/mod.ts"; Loading Loading @@ -75,14 +72,36 @@ export async function handleActor<TContextData>( }); } /** * Callbacks for handling a collection. */ export interface CollectionCallbacks<TItem, TContextData> { /** * A callback that dispatches a collection. */ dispatcher: CollectionDispatcher<TItem, TContextData>; /** * A callback that counts the number of items in a collection. */ counter?: CollectionCounter<TContextData>; /** * A callback that returns the first cursor for a collection. */ firstCursor?: CollectionCursor<TContextData>; /** * A callback that returns the last cursor for a collection. */ lastCursor?: CollectionCursor<TContextData>; } export interface CollectionHandlerParameters<TItem, TContextData> { handle: string; context: RequestContext<TContextData>; documentLoader: DocumentLoader; collectionDispatcher?: CollectionDispatcher<TItem, TContextData>; collectionCounter?: CollectionCounter<TContextData>; collectionFirstCursor?: CollectionCursor<TContextData>; collectionLastCursor?: CollectionCursor<TContextData>; collectionCallbacks?: CollectionCallbacks<TItem, TContextData>; onNotFound(request: Request): Response | Promise<Response>; onNotAcceptable(request: Request): Response | Promise<Response>; } Loading @@ -96,15 +115,12 @@ export async function handleCollection< handle, context, documentLoader, collectionDispatcher, collectionCounter, collectionFirstCursor, collectionLastCursor, collectionCallbacks, onNotFound, onNotAcceptable, }: CollectionHandlerParameters<TItem, TContextData>, ): Promise<Response> { if (collectionDispatcher == null) { if (collectionCallbacks == null) { const response = onNotFound(request); return response instanceof Promise ? await response : response; } Loading @@ -116,16 +132,19 @@ export async function handleCollection< const cursor = url.searchParams.get("cursor"); let collection: OrderedCollection | OrderedCollectionPage; if (cursor == null) { const firstCursorPromise = collectionFirstCursor?.(context, handle); const firstCursorPromise = collectionCallbacks.firstCursor?.( context, handle, ); const firstCursor = firstCursorPromise instanceof Promise ? await firstCursorPromise : firstCursorPromise; const totalItemsPromise = collectionCounter?.(context, handle); const totalItemsPromise = collectionCallbacks.counter?.(context, handle); const totalItems = totalItemsPromise instanceof Promise ? await totalItemsPromise : totalItemsPromise; if (firstCursor == null) { const pagePromise = collectionDispatcher(context, handle, null); const pagePromise = collectionCallbacks.dispatcher(context, handle, null); const page = pagePromise instanceof Promise ? await pagePromise : pagePromise; Loading @@ -139,7 +158,10 @@ export async function handleCollection< items, }); } else { const lastCursorPromise = collectionLastCursor?.(context, handle); const lastCursorPromise = collectionCallbacks.lastCursor?.( context, handle, ); const lastCursor = lastCursorPromise instanceof Promise ? await lastCursorPromise : lastCursorPromise; Loading @@ -157,7 +179,7 @@ export async function handleCollection< }); } } else { const pagePromise = collectionDispatcher(context, handle, cursor); const pagePromise = collectionCallbacks.dispatcher(context, handle, cursor); const page = pagePromise instanceof Promise ? await pagePromise : pagePromise; Loading federation/middleware.ts +24 −22 Original line number Diff line number Diff line Loading @@ -16,7 +16,12 @@ import { InboxListener, } from "./callback.ts"; import { Context, RequestContext } from "./context.ts"; import { handleActor, handleCollection, handleInbox } from "./handler.ts"; import { CollectionCallbacks, handleActor, handleCollection, handleInbox, } from "./handler.ts"; import { OutboxMessage } from "./queue.ts"; import { Router, RouterError } from "./router.ts"; import { extractInboxes, sendActivity } from "./send.ts"; Loading Loading @@ -280,7 +285,8 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @param dispatcher An actor dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. * @returns An object with methods to set other actor dispatcher callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setActorDispatcher( path: string, Loading Loading @@ -358,7 +364,9 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @param dispatcher A following collection callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. * @returns An object with methods to set other following collection * callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setFollowingDispatcher( path: string, Loading Loading @@ -401,6 +409,8 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @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( Loading Loading @@ -437,6 +447,14 @@ export class Federation<TContextData> { return setters; } /** * Assigns the URL patth for the inbox and starts setting inbox listeners. * @param path 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: `{handle}`. * @returns An object to register inbox listeners. * @throws {RouteError} Thrown if the path pattern is invalid. */ setInboxListeners(path: string): InboxListenerSetter<TContextData> { if (this.#router.has("inbox")) { throw new RouterError("Inbox already set."); Loading Loading @@ -548,10 +566,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#outboxCallbacks?.dispatcher, collectionCounter: this.#outboxCallbacks?.counter, collectionFirstCursor: this.#outboxCallbacks?.firstCursor, collectionLastCursor: this.#outboxCallbacks?.lastCursor, collectionCallbacks: this.#outboxCallbacks, onNotFound, onNotAcceptable, }); Loading @@ -572,10 +587,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#followingCallbacks?.dispatcher, collectionCounter: this.#followingCallbacks?.counter, collectionFirstCursor: this.#followingCallbacks?.firstCursor, collectionLastCursor: this.#followingCallbacks?.lastCursor, collectionCallbacks: this.#followingCallbacks, onNotFound, onNotAcceptable, }); Loading @@ -584,10 +596,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#followersCallbacks?.dispatcher, collectionCounter: this.#followersCallbacks?.counter, collectionFirstCursor: this.#followersCallbacks?.firstCursor, collectionLastCursor: this.#followersCallbacks?.lastCursor, collectionCallbacks: this.#followersCallbacks, onNotFound, onNotAcceptable, }); Loading Loading @@ -634,13 +643,6 @@ export interface ActorCallbackSetters<TContextData> { ): ActorCallbackSetters<TContextData>; } interface CollectionCallbacks<TItem, TContextData> { dispatcher: CollectionDispatcher<TItem, TContextData>; counter?: CollectionCounter<TContextData>; firstCursor?: CollectionCursor<TContextData>; lastCursor?: CollectionCursor<TContextData>; } /** * Additional settings for a collection dispatcher. */ Loading httpsig/mod.ts +1 −1 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ export async function verify( } if (!matched) return null; } const date: Temporal.Instant = new Date(dateHeader).toTemporalInstant(); const date = Temporal.Instant.from(new Date(dateHeader).toISOString()); const now = Temporal.Now.instant(); if (Temporal.Instant.compare(date, now.add({ seconds: 30 })) > 0) { // Too far in the future Loading Loading
federation/handler.ts +39 −17 Original line number Diff line number Diff line Loading @@ -5,9 +5,6 @@ import { CollectionCursor, CollectionDispatcher, InboxListener, OutboxCounter, OutboxCursor, OutboxDispatcher, } from "./callback.ts"; import { RequestContext } from "./context.ts"; import { verify } from "../httpsig/mod.ts"; Loading Loading @@ -75,14 +72,36 @@ export async function handleActor<TContextData>( }); } /** * Callbacks for handling a collection. */ export interface CollectionCallbacks<TItem, TContextData> { /** * A callback that dispatches a collection. */ dispatcher: CollectionDispatcher<TItem, TContextData>; /** * A callback that counts the number of items in a collection. */ counter?: CollectionCounter<TContextData>; /** * A callback that returns the first cursor for a collection. */ firstCursor?: CollectionCursor<TContextData>; /** * A callback that returns the last cursor for a collection. */ lastCursor?: CollectionCursor<TContextData>; } export interface CollectionHandlerParameters<TItem, TContextData> { handle: string; context: RequestContext<TContextData>; documentLoader: DocumentLoader; collectionDispatcher?: CollectionDispatcher<TItem, TContextData>; collectionCounter?: CollectionCounter<TContextData>; collectionFirstCursor?: CollectionCursor<TContextData>; collectionLastCursor?: CollectionCursor<TContextData>; collectionCallbacks?: CollectionCallbacks<TItem, TContextData>; onNotFound(request: Request): Response | Promise<Response>; onNotAcceptable(request: Request): Response | Promise<Response>; } Loading @@ -96,15 +115,12 @@ export async function handleCollection< handle, context, documentLoader, collectionDispatcher, collectionCounter, collectionFirstCursor, collectionLastCursor, collectionCallbacks, onNotFound, onNotAcceptable, }: CollectionHandlerParameters<TItem, TContextData>, ): Promise<Response> { if (collectionDispatcher == null) { if (collectionCallbacks == null) { const response = onNotFound(request); return response instanceof Promise ? await response : response; } Loading @@ -116,16 +132,19 @@ export async function handleCollection< const cursor = url.searchParams.get("cursor"); let collection: OrderedCollection | OrderedCollectionPage; if (cursor == null) { const firstCursorPromise = collectionFirstCursor?.(context, handle); const firstCursorPromise = collectionCallbacks.firstCursor?.( context, handle, ); const firstCursor = firstCursorPromise instanceof Promise ? await firstCursorPromise : firstCursorPromise; const totalItemsPromise = collectionCounter?.(context, handle); const totalItemsPromise = collectionCallbacks.counter?.(context, handle); const totalItems = totalItemsPromise instanceof Promise ? await totalItemsPromise : totalItemsPromise; if (firstCursor == null) { const pagePromise = collectionDispatcher(context, handle, null); const pagePromise = collectionCallbacks.dispatcher(context, handle, null); const page = pagePromise instanceof Promise ? await pagePromise : pagePromise; Loading @@ -139,7 +158,10 @@ export async function handleCollection< items, }); } else { const lastCursorPromise = collectionLastCursor?.(context, handle); const lastCursorPromise = collectionCallbacks.lastCursor?.( context, handle, ); const lastCursor = lastCursorPromise instanceof Promise ? await lastCursorPromise : lastCursorPromise; Loading @@ -157,7 +179,7 @@ export async function handleCollection< }); } } else { const pagePromise = collectionDispatcher(context, handle, cursor); const pagePromise = collectionCallbacks.dispatcher(context, handle, cursor); const page = pagePromise instanceof Promise ? await pagePromise : pagePromise; Loading
federation/middleware.ts +24 −22 Original line number Diff line number Diff line Loading @@ -16,7 +16,12 @@ import { InboxListener, } from "./callback.ts"; import { Context, RequestContext } from "./context.ts"; import { handleActor, handleCollection, handleInbox } from "./handler.ts"; import { CollectionCallbacks, handleActor, handleCollection, handleInbox, } from "./handler.ts"; import { OutboxMessage } from "./queue.ts"; import { Router, RouterError } from "./router.ts"; import { extractInboxes, sendActivity } from "./send.ts"; Loading Loading @@ -280,7 +285,8 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @param dispatcher An actor dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. * @returns An object with methods to set other actor dispatcher callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setActorDispatcher( path: string, Loading Loading @@ -358,7 +364,9 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @param dispatcher A following collection callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. * @returns An object with methods to set other following collection * callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setFollowingDispatcher( path: string, Loading Loading @@ -401,6 +409,8 @@ export class Federation<TContextData> { * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{handle}`. * @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( Loading Loading @@ -437,6 +447,14 @@ export class Federation<TContextData> { return setters; } /** * Assigns the URL patth for the inbox and starts setting inbox listeners. * @param path 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: `{handle}`. * @returns An object to register inbox listeners. * @throws {RouteError} Thrown if the path pattern is invalid. */ setInboxListeners(path: string): InboxListenerSetter<TContextData> { if (this.#router.has("inbox")) { throw new RouterError("Inbox already set."); Loading Loading @@ -548,10 +566,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#outboxCallbacks?.dispatcher, collectionCounter: this.#outboxCallbacks?.counter, collectionFirstCursor: this.#outboxCallbacks?.firstCursor, collectionLastCursor: this.#outboxCallbacks?.lastCursor, collectionCallbacks: this.#outboxCallbacks, onNotFound, onNotAcceptable, }); Loading @@ -572,10 +587,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#followingCallbacks?.dispatcher, collectionCounter: this.#followingCallbacks?.counter, collectionFirstCursor: this.#followingCallbacks?.firstCursor, collectionLastCursor: this.#followingCallbacks?.lastCursor, collectionCallbacks: this.#followingCallbacks, onNotFound, onNotAcceptable, }); Loading @@ -584,10 +596,7 @@ export class Federation<TContextData> { handle: route.values.handle, context, documentLoader: this.#documentLoader, collectionDispatcher: this.#followersCallbacks?.dispatcher, collectionCounter: this.#followersCallbacks?.counter, collectionFirstCursor: this.#followersCallbacks?.firstCursor, collectionLastCursor: this.#followersCallbacks?.lastCursor, collectionCallbacks: this.#followersCallbacks, onNotFound, onNotAcceptable, }); Loading Loading @@ -634,13 +643,6 @@ export interface ActorCallbackSetters<TContextData> { ): ActorCallbackSetters<TContextData>; } interface CollectionCallbacks<TItem, TContextData> { dispatcher: CollectionDispatcher<TItem, TContextData>; counter?: CollectionCounter<TContextData>; firstCursor?: CollectionCursor<TContextData>; lastCursor?: CollectionCursor<TContextData>; } /** * Additional settings for a collection dispatcher. */ Loading
httpsig/mod.ts +1 −1 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ export async function verify( } if (!matched) return null; } const date: Temporal.Instant = new Date(dateHeader).toTemporalInstant(); const date = Temporal.Instant.from(new Date(dateHeader).toISOString()); const now = Temporal.Now.instant(); if (Temporal.Instant.compare(date, now.add({ seconds: 30 })) > 0) { // Too far in the future Loading