import type { EntityValidator } from "../validator/index"; type MaybePromise = T | Promise; type ParserCallbacks = { note: (note: typeof EntityValidator.$Note) => MaybePromise; follow: (follow: typeof EntityValidator.$Follow) => MaybePromise; followAccept: ( followAccept: typeof EntityValidator.$FollowAccept, ) => MaybePromise; followReject: ( followReject: typeof EntityValidator.$FollowReject, ) => MaybePromise; user: (user: typeof EntityValidator.$User) => MaybePromise; like: (like: typeof EntityValidator.$Like) => MaybePromise; dislike: (dislike: typeof EntityValidator.$Dislike) => MaybePromise; undo: (undo: typeof EntityValidator.$Undo) => MaybePromise; serverMetadata: ( serverMetadata: typeof EntityValidator.$ServerMetadata, ) => MaybePromise; extension: ( extension: typeof EntityValidator.$Extension, ) => MaybePromise; patch: (patch: typeof EntityValidator.$Patch) => MaybePromise; }; /** * A class to parse the body of a request and call the appropriate callback. * @example * const parser = new RequestParserHandler(body, validator); * * await parser.parseBody({ * note: (note) => { * console.log(note); * }, * follow: (follow) => { * console.log(follow); * }, * ... * }); */ export class RequestParserHandler { constructor( private readonly body: Record< string, string | number | object | boolean | null >, private readonly validator: EntityValidator, ) {} /** * Parse the body of the request and call the appropriate callback. * To change the return type, edit the ReturnType generic parameter. * const parser = new RequestParserHandler(body, validator); * @param callbacks The callbacks to call when a specific entity is found. * @returns A promise that resolves when the body has been parsed, and the callbacks have finished executing. * @throws If the type field is missing or invalid * @example * await parser.parseBody({ * note: (note) => { * console.log(note); * }, * follow: (follow) => { * console.log(follow); * }, * ... * }); */ public async parseBody( callbacks: Partial>, ): Promise { if (!this.body.type) throw new Error("Missing type field in body"); switch (this.body.type) { case "Note": { const note = await this.validator.Note(this.body); if (callbacks.note) return await callbacks.note(note); break; } case "Patch": { const patch = await this.validator.Patch(this.body); if (callbacks.patch) return await callbacks.patch(patch); break; } case "Follow": { const follow = await this.validator.Follow(this.body); if (callbacks.follow) return await callbacks.follow(follow); break; } case "FollowAccept": { const followAccept = await this.validator.FollowAccept( this.body, ); if (callbacks.followAccept) return await callbacks.followAccept(followAccept); break; } case "FollowReject": { const followReject = await this.validator.FollowReject( this.body, ); if (callbacks.followReject) return await callbacks.followReject(followReject); break; } case "User": { const user = await this.validator.User(this.body); if (callbacks.user) return await callbacks.user(user); break; } case "Like": { const like = await this.validator.Like(this.body); if (callbacks.like) return await callbacks.like(like); break; } case "Dislike": { const dislike = await this.validator.Dislike(this.body); if (callbacks.dislike) return await callbacks.dislike(dislike); break; } case "Undo": { const undo = await this.validator.Undo(this.body); if (callbacks.undo) return await callbacks.undo(undo); break; } case "ServerMetadata": { const serverMetadata = await this.validator.ServerMetadata( this.body, ); if (callbacks.serverMetadata) return await callbacks.serverMetadata(serverMetadata); break; } case "Extension": { const extension = await this.validator.Extension(this.body); if (callbacks.extension) return await callbacks.extension(extension); break; } default: throw new Error( `Invalid type field in body: ${this.body.type}`, ); } throw new Error(`Invalid type field in body: ${this.body.type}`); } }