refactor(federation): 👽 Update rest of federation code to Working Draft 4

This commit is contained in:
Jesse Wierzbinski 2024-08-25 16:01:06 +02:00
parent 4a470f5f3c
commit d422e28943
No known key found for this signature in database
4 changed files with 182 additions and 40 deletions

View file

@ -79,7 +79,7 @@ describe("RequestParserHandler", () => {
expect(noteCallback).not.toHaveBeenCalled(); expect(noteCallback).not.toHaveBeenCalled();
}); });
test("Throw on incorrect body type property", async () => { test("Correctly handle unknown body type property", async () => {
const handler = new RequestParserHandler( const handler = new RequestParserHandler(
{ {
type: "DoesntExist", type: "DoesntExist",
@ -89,9 +89,7 @@ describe("RequestParserHandler", () => {
); );
const noteCallback = jest.fn(); const noteCallback = jest.fn();
await expect( await handler.parseBody({ unknown: noteCallback });
handler.parseBody({ note: noteCallback }), expect(noteCallback).toHaveBeenCalled();
).rejects.toThrow();
expect(noteCallback).not.toHaveBeenCalled();
}); });
}); });

View file

@ -1,15 +1,18 @@
import type { import type {
Delete,
Dislike, Dislike,
Extension,
Follow, Follow,
FollowAccept, FollowAccept,
FollowReject, FollowReject,
Group,
InstanceMetadata,
Like, Like,
Note, Note,
Patch, Reaction,
ServerMetadata, Share,
Undo, Unfollow,
User, User,
Vote,
} from "./schemas"; } from "./schemas";
import type { EntityValidator } from "./validator"; import type { EntityValidator } from "./validator";
@ -23,10 +26,14 @@ type ParserCallbacks<T> = {
user: (user: User) => MaybePromise<T>; user: (user: User) => MaybePromise<T>;
like: (like: Like) => MaybePromise<T>; like: (like: Like) => MaybePromise<T>;
dislike: (dislike: Dislike) => MaybePromise<T>; dislike: (dislike: Dislike) => MaybePromise<T>;
undo: (undo: Undo) => MaybePromise<T>; delete: (undo: Delete) => MaybePromise<T>;
serverMetadata: (serverMetadata: ServerMetadata) => MaybePromise<T>; instanceMetadata: (instanceMetadata: InstanceMetadata) => MaybePromise<T>;
extension: (extension: Extension) => MaybePromise<T>; group: (group: Group) => MaybePromise<T>;
patch: (patch: Patch) => MaybePromise<T>; reaction: (reaction: Reaction) => MaybePromise<T>;
share: (share: Share) => MaybePromise<T>;
vote: (vote: Vote) => MaybePromise<T>;
unfollow: (unfollow: Unfollow) => MaybePromise<T>;
unknown: (data: unknown) => MaybePromise<T>;
}; };
/** /**
@ -92,15 +99,6 @@ export class RequestParserHandler {
break; break;
} }
case "Patch": {
const patch = await this.validator.Patch(this.body);
if (callbacks.patch) {
return await callbacks.patch(patch);
}
break;
}
case "Follow": { case "Follow": {
const follow = await this.validator.Follow(this.body); const follow = await this.validator.Follow(this.body);
@ -159,41 +157,79 @@ export class RequestParserHandler {
break; break;
} }
case "Undo": { case "Delete": {
const undo = await this.validator.Undo(this.body); // "delete" isn't an allowed variable name
const delete_ = await this.validator.Delete(this.body);
if (callbacks.undo) { if (callbacks.delete) {
return await callbacks.undo(undo); return await callbacks.delete(delete_);
} }
break; break;
} }
case "ServerMetadata": { case "InstanceMetadata": {
const serverMetadata = await this.validator.ServerMetadata( const instanceMetadata = await this.validator.InstanceMetadata(
this.body, this.body,
); );
if (callbacks.serverMetadata) { if (callbacks.instanceMetadata) {
return await callbacks.serverMetadata(serverMetadata); return await callbacks.instanceMetadata(instanceMetadata);
} }
break; break;
} }
case "Extension": { case "Group": {
const extension = await this.validator.Extension(this.body); const group = await this.validator.Group(this.body);
if (callbacks.extension) { if (callbacks.group) {
return await callbacks.extension(extension); return await callbacks.group(group);
} }
break; break;
} }
default: case "Reaction": {
throw new Error( const reaction = await this.validator.Reaction(this.body);
`Invalid type field in body: ${this.body.type}`,
); if (callbacks.reaction) {
return await callbacks.reaction(reaction);
}
break;
}
case "Share": {
const share = await this.validator.Share(this.body);
if (callbacks.share) {
return await callbacks.share(share);
}
break;
}
case "Vote": {
const vote = await this.validator.Vote(this.body);
if (callbacks.vote) {
return await callbacks.vote(vote);
}
break;
}
case "Unfollow": {
const unfollow = await this.validator.Unfollow(this.body);
if (callbacks.unfollow) {
return await callbacks.unfollow(unfollow);
}
break;
}
default: {
if (callbacks.unknown) {
return await callbacks.unknown(this.body);
}
}
} }
throw new Error(`Invalid type field in body: ${this.body.type}`); return undefined as ReturnType;
} }
} }

View file

@ -17,9 +17,18 @@ import type {
UnfollowSchema, UnfollowSchema,
UserSchema, UserSchema,
} from "./schemas/base"; } from "./schemas/base";
import type { ContentFormatSchema } from "./schemas/content_format"; import type {
AudioOnlyContentFormatSchema,
ContentFormatSchema,
ImageOnlyContentFormatSchema,
TextOnlyContentFormatSchema,
} from "./schemas/content_format";
import type { ExtensionPropertySchema } from "./schemas/extensions"; import type { ExtensionPropertySchema } from "./schemas/extensions";
import type { CustomEmojiExtensionSchema } from "./schemas/extensions/custom_emojis"; import type { CustomEmojiExtensionSchema } from "./schemas/extensions/custom_emojis";
import type { LikeSchema } from "./schemas/extensions/likes";
import type { VoteSchema } from "./schemas/extensions/polls";
import type { ReactionSchema } from "./schemas/extensions/reactions";
import type { ShareSchema } from "./schemas/extensions/share";
import type { VanityExtensionSchema } from "./schemas/extensions/vanity"; import type { VanityExtensionSchema } from "./schemas/extensions/vanity";
// biome-ignore lint/suspicious/noExplicitAny: Used only as a base type // biome-ignore lint/suspicious/noExplicitAny: Used only as a base type
@ -36,9 +45,17 @@ export type Follow = InferType<typeof FollowSchema>;
export type FollowAccept = InferType<typeof FollowAcceptSchema>; export type FollowAccept = InferType<typeof FollowAcceptSchema>;
export type FollowReject = InferType<typeof FollowRejectSchema>; export type FollowReject = InferType<typeof FollowRejectSchema>;
export type ContentFormat = InferType<typeof ContentFormatSchema>; export type ContentFormat = InferType<typeof ContentFormatSchema>;
export type ImageContentFormat = InferType<typeof ImageOnlyContentFormatSchema>;
export type TextContentFormat = InferType<typeof TextOnlyContentFormatSchema>;
export type AudioContentFormat = InferType<typeof AudioOnlyContentFormatSchema>;
export type CustomEmojiExtension = InferType<typeof CustomEmojiExtensionSchema>; export type CustomEmojiExtension = InferType<typeof CustomEmojiExtensionSchema>;
export type Entity = InferType<typeof EntitySchema>; export type Entity = InferType<typeof EntitySchema>;
export type Delete = InferType<typeof DeleteSchema>; export type Delete = InferType<typeof DeleteSchema>;
export type Group = InferType<typeof GroupSchema>; export type Group = InferType<typeof GroupSchema>;
export type InstanceMetadata = InferType<typeof InstanceMetadataSchema>; export type InstanceMetadata = InferType<typeof InstanceMetadataSchema>;
export type Unfollow = InferType<typeof UnfollowSchema>; export type Unfollow = InferType<typeof UnfollowSchema>;
export type Like = InferType<typeof LikeSchema>;
export type Dislike = InferType<typeof LikeSchema>;
export type Vote = InferType<typeof VoteSchema>;
export type Reaction = InferType<typeof ReactionSchema>;
export type Share = InferType<typeof ShareSchema>;

View file

@ -1,17 +1,25 @@
import type { z } from "zod"; import type { z } from "zod";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { import {
DeleteSchema,
EntitySchema, EntitySchema,
FollowAcceptSchema, FollowAcceptSchema,
FollowRejectSchema, FollowRejectSchema,
FollowSchema, FollowSchema,
GroupSchema,
InstanceMetadataSchema,
NoteSchema, NoteSchema,
PublicKeyDataSchema, PublicKeyDataSchema,
UnfollowSchema,
UserSchema, UserSchema,
} from "./schemas/base"; } from "./schemas/base";
import { ContentFormatSchema } from "./schemas/content_format"; import { ContentFormatSchema } from "./schemas/content_format";
import { ExtensionPropertySchema } from "./schemas/extensions"; import { ExtensionPropertySchema } from "./schemas/extensions";
import { CustomEmojiExtensionSchema } from "./schemas/extensions/custom_emojis"; import { CustomEmojiExtensionSchema } from "./schemas/extensions/custom_emojis";
import { LikeSchema } from "./schemas/extensions/likes";
import { VoteSchema } from "./schemas/extensions/polls";
import { ReactionSchema } from "./schemas/extensions/reactions";
import { ShareSchema } from "./schemas/extensions/share";
import { VanityExtensionSchema } from "./schemas/extensions/vanity"; import { VanityExtensionSchema } from "./schemas/extensions/vanity";
// biome-ignore lint/suspicious/noExplicitAny: Used only as a base type // biome-ignore lint/suspicious/noExplicitAny: Used only as a base type
@ -174,4 +182,87 @@ export class EntityValidator {
): Promise<InferType<typeof ExtensionPropertySchema>> { ): Promise<InferType<typeof ExtensionPropertySchema>> {
return this.validate(ExtensionPropertySchema, data); return this.validate(ExtensionPropertySchema, data);
} }
/**
* Validates a Delete entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Delete(data: unknown): Promise<InferType<typeof DeleteSchema>> {
return this.validate(DeleteSchema, data);
}
/**
* Validates a Group entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Group(data: unknown): Promise<InferType<typeof GroupSchema>> {
return this.validate(GroupSchema, data);
}
/**
* Validates an InstanceMetadata entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public InstanceMetadata(
data: unknown,
): Promise<InferType<typeof InstanceMetadataSchema>> {
return this.validate(InstanceMetadataSchema, data);
}
/**
* Validates an Unfollow entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Unfollow(data: unknown): Promise<InferType<typeof UnfollowSchema>> {
return this.validate(UnfollowSchema, data);
}
/**
* Validates a Like entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Like(data: unknown): Promise<InferType<typeof LikeSchema>> {
return this.validate(LikeSchema, data);
}
/**
* Validates a Dislike entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Dislike(data: unknown): Promise<InferType<typeof LikeSchema>> {
return this.validate(LikeSchema, data);
}
/**
* Validates a Vote entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Vote(data: unknown): Promise<InferType<typeof VoteSchema>> {
return this.validate(VoteSchema, data);
}
/**
* Validates a Reaction entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Reaction(data: unknown): Promise<InferType<typeof ReactionSchema>> {
return this.validate(ReactionSchema, data);
}
/**
* Validates a Share entity.
* @param data - The data to validate
* @returns A promise that resolves to the validated data.
*/
public Share(data: unknown): Promise<InferType<typeof ShareSchema>> {
return this.validate(ShareSchema, data);
}
} }