refactor(federation): ♻️ Rewrite federation SDK

This commit is contained in:
Jesse Wierzbinski 2025-04-08 16:01:10 +02:00
parent ad1dc13a51
commit d638610361
No known key found for this signature in database
72 changed files with 2137 additions and 738 deletions

View file

@ -0,0 +1,25 @@
/**
* Custom emojis extension.
* @module federation/schemas/extensions/custom_emojis
* @see module:federation/schemas/base
* @see https://versia.pub/extensions/custom-emojis
*/
import { z } from "zod";
import { emojiRegex } from "../../regex.ts";
import { ImageContentFormatSchema } from "../contentformat.ts";
export const CustomEmojiExtensionSchema = z.strictObject({
emojis: z.array(
z.strictObject({
name: z
.string()
.min(1)
.max(256)
.regex(
emojiRegex,
"Emoji name must be alphanumeric, underscores, or dashes, and surrounded by identifiers",
),
url: ImageContentFormatSchema,
}),
),
});

View file

@ -0,0 +1,41 @@
import { z } from "zod";
import { url } from "../common.ts";
import { TextContentFormatSchema } from "../contentformat.ts";
import { EntitySchema } from "../entity.ts";
export const GroupSchema = EntitySchema.extend({
type: z.literal("pub.versia:groups/Group"),
name: TextContentFormatSchema.nullish(),
description: TextContentFormatSchema.nullish(),
open: z.boolean().nullish(),
members: url,
notes: url.nullish(),
});
export const GroupSubscribeSchema = EntitySchema.extend({
type: z.literal("pub.versia:groups/Subscribe"),
uri: z.null().optional(),
subscriber: url,
group: url,
});
export const GroupUnsubscribeSchema = EntitySchema.extend({
type: z.literal("pub.versia:groups/Unsubscribe"),
uri: z.null().optional(),
subscriber: url,
group: url,
});
export const GroupSubscribeAcceptSchema = EntitySchema.extend({
type: z.literal("pub.versia:groups/SubscribeAccept"),
uri: z.null().optional(),
subscriber: url,
group: url,
});
export const GroupSubscribeRejectSchema = EntitySchema.extend({
type: z.literal("pub.versia:groups/SubscribeReject"),
uri: z.null().optional(),
subscriber: url,
group: url,
});

View file

@ -0,0 +1,15 @@
import { z } from "zod";
import { url } from "../common.ts";
import { EntitySchema } from "../entity.ts";
export const LikeSchema = EntitySchema.extend({
type: z.literal("pub.versia:likes/Like"),
author: url,
liked: url,
});
export const DislikeSchema = EntitySchema.extend({
type: z.literal("pub.versia:likes/Dislike"),
author: url,
disliked: url,
});

View file

@ -0,0 +1,15 @@
import { z } from "zod";
import { url } from "../common.ts";
import { EntitySchema } from "../entity.ts";
export const MigrationSchema = EntitySchema.extend({
type: z.literal("pub.versia:migration/Migration"),
uri: z.null().optional(),
author: url,
destination: url,
});
export const MigrationExtensionSchema = z.strictObject({
previous: url,
new: url.nullish(),
});

View file

@ -0,0 +1,22 @@
import { z } from "zod";
import { isISOString } from "../../regex.ts";
import { url, u64 } from "../common.ts";
import { TextContentFormatSchema } from "../contentformat.ts";
import { EntitySchema } from "../entity.ts";
export const VoteSchema = EntitySchema.extend({
type: z.literal("pub.versia:polls/Vote"),
author: url,
poll: url,
option: u64,
});
export const PollExtensionSchema = z.strictObject({
options: z.array(TextContentFormatSchema),
votes: z.array(u64),
multiple_choice: z.boolean(),
expires_at: z
.string()
.refine((v) => isISOString(v), "must be a valid ISO8601 datetime")
.nullish(),
});

View file

@ -0,0 +1,10 @@
import { z } from "zod";
import { url } from "../common.ts";
import { EntitySchema } from "../entity.ts";
export const ReactionSchema = EntitySchema.extend({
type: z.literal("pub.versia:reactions/Reaction"),
author: url,
object: url,
content: z.string().min(1).max(256),
});

View file

@ -0,0 +1,15 @@
import { z } from "zod";
import { url } from "../common.ts";
import { EntitySchema } from "../entity.ts";
export const ReportSchema = EntitySchema.extend({
type: z.literal("pub.versia:reports/Report"),
uri: z.null().optional(),
author: url.nullish(),
reported: z.array(url),
tags: z.array(z.string()),
comment: z
.string()
.max(2 ** 16)
.nullish(),
});

View file

@ -0,0 +1,9 @@
import { z } from "zod";
import { url } from "../common.ts";
import { EntitySchema } from "../entity.ts";
export const ShareSchema = EntitySchema.extend({
type: z.literal("pub.versia:share/Share"),
author: url,
shared: url,
});

View file

@ -0,0 +1,46 @@
/**
* Vanity extension schema.
* @module federation/schemas/extensions/vanity
* @see module:federation/schemas/base
* @see https://versia.pub/extensions/vanity
*/
import { z } from "zod";
import { ianaTimezoneRegex, isISOString } from "../../regex.ts";
import { url } from "../common.ts";
import {
AudioContentFormatSchema,
ImageContentFormatSchema,
} from "../contentformat.ts";
export const VanityExtensionSchema = z.strictObject({
avatar_overlays: z.array(ImageContentFormatSchema).nullish(),
avatar_mask: ImageContentFormatSchema.nullish(),
background: ImageContentFormatSchema.nullish(),
audio: AudioContentFormatSchema.nullish(),
pronouns: z.record(
z.string(),
z.array(
z.union([
z.strictObject({
subject: z.string(),
object: z.string(),
dependent_possessive: z.string(),
independent_possessive: z.string(),
reflexive: z.string(),
}),
z.string(),
]),
),
),
birthday: z
.string()
.refine((v) => isISOString(v), "must be a valid ISO8601 datetime")
.nullish(),
location: z.string().nullish(),
aliases: z.array(url).nullish(),
timezone: z
.string()
.regex(ianaTimezoneRegex, "must be a valid IANA timezone")
.nullish(),
});