mirror of
https://github.com/versia-pub/api.git
synced 2026-03-13 04:09:15 +01:00
refactor(federation): 👽 Update all schemas to Working Draft 4
This commit is contained in:
parent
b462718dc0
commit
4a470f5f3c
13 changed files with 540 additions and 448 deletions
|
|
@ -5,7 +5,7 @@
|
|||
* @see https://versia.pub/extensions/custom-emojis
|
||||
*/
|
||||
import { z } from "zod";
|
||||
import { ContentFormatSchema } from "../content_format";
|
||||
import { ImageOnlyContentFormatSchema } from "../content_format";
|
||||
import { emojiRegex } from "../regex";
|
||||
|
||||
/**
|
||||
|
|
@ -15,14 +15,14 @@ import { emojiRegex } from "../regex";
|
|||
* {
|
||||
* // ...
|
||||
* "extensions": {
|
||||
* "org.lysand:custom_emojis": {
|
||||
* "pub.versia:custom_emojis": {
|
||||
* "emojis": [
|
||||
* {
|
||||
* "name": "happy_face",
|
||||
* "name": ":happy_face:",
|
||||
* "url": {
|
||||
* "image/png": {
|
||||
* "content": "https://cdn.example.com/emojis/happy_face.png",
|
||||
* "content_type": "image/png"
|
||||
* "remote": true
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
|
|
@ -35,16 +35,18 @@ import { emojiRegex } from "../regex";
|
|||
*/
|
||||
export const CustomEmojiExtensionSchema = z.object({
|
||||
emojis: z.array(
|
||||
z.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(256)
|
||||
.regex(
|
||||
emojiRegex,
|
||||
"Emoji name must be alphanumeric, underscores, or dashes.",
|
||||
),
|
||||
url: ContentFormatSchema,
|
||||
}),
|
||||
z
|
||||
.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(256)
|
||||
.regex(
|
||||
emojiRegex,
|
||||
"Emoji name must be alphanumeric, underscores, or dashes, and surrounded by identifiers",
|
||||
),
|
||||
url: ImageOnlyContentFormatSchema,
|
||||
})
|
||||
.strict(),
|
||||
),
|
||||
});
|
||||
|
|
|
|||
40
federation/schemas/extensions/likes.ts
Normal file
40
federation/schemas/extensions/likes.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { z } from "zod";
|
||||
import { EntitySchema } from "../base";
|
||||
|
||||
/**
|
||||
* @description Like entity
|
||||
* @see https://versia.pub/extensions/likes
|
||||
* @example
|
||||
* {
|
||||
* "id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "type": "pub.versia:likes/Like",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||
* "uri": "https://example.com/likes/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "liked": "https://otherexample.org/notes/fmKZ763jzIU8"
|
||||
* }
|
||||
*/
|
||||
export const LikeSchema = EntitySchema.extend({
|
||||
type: z.literal("pub.versia:likes/Like"),
|
||||
author: z.string().url(),
|
||||
liked: z.string().url(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @description Dislike entity
|
||||
* @see https://versia.pub/extensions/likes
|
||||
* @example
|
||||
* {
|
||||
* "id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "type": "pub.versia:likes/Dislike",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||
* "uri": "https://example.com/dislikes/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "disliked": "https://otherexample.org/notes/fmKZ763jzIU8"
|
||||
* }
|
||||
*/
|
||||
export const DislikeSchema = EntitySchema.extend({
|
||||
type: z.literal("pub.versia:likes/Dislike"),
|
||||
author: z.string().url(),
|
||||
disliked: z.string().url(),
|
||||
});
|
||||
|
|
@ -5,88 +5,29 @@
|
|||
* @see https://versia.pub/extensions/polls
|
||||
*/
|
||||
import { z } from "zod";
|
||||
import { ExtensionSchema } from "../base";
|
||||
import { ContentFormatSchema } from "../content_format";
|
||||
|
||||
/**
|
||||
* @description Poll extension entity
|
||||
* @see https://versia.pub/extensions/polls
|
||||
* @example
|
||||
* {
|
||||
* "type": "Extension",
|
||||
* "id": "d6eb84ea-cd13-43f9-9c54-01244da8e5e3",
|
||||
* "extension_type": "org.lysand:polls/Poll",
|
||||
* "uri": "https://example.com/polls/d6eb84ea-cd13-43f9-9c54-01244da8e5e3",
|
||||
* "options": [
|
||||
* {
|
||||
* "text/plain": {
|
||||
* "content": "Red"
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* "text/plain": {
|
||||
* "content": "Blue"
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* "text/plain": {
|
||||
* "content": "Green"
|
||||
* }
|
||||
* }
|
||||
* ],
|
||||
* "votes": [
|
||||
* 9,
|
||||
* 5,
|
||||
* 0
|
||||
* ],
|
||||
* "multiple_choice": false,
|
||||
* "expires_at": "2021-01-04T00:00:00.000Z"
|
||||
* }
|
||||
*/
|
||||
export const PollSchema = ExtensionSchema.extend({
|
||||
extension_type: z.literal("org.lysand:polls/Poll"),
|
||||
options: z.array(ContentFormatSchema),
|
||||
votes: z.array(z.number().int().nonnegative()),
|
||||
multiple_choice: z.boolean().optional().nullable(),
|
||||
expires_at: z.string(),
|
||||
});
|
||||
import { EntitySchema } from "../base";
|
||||
|
||||
/**
|
||||
* @description Vote extension entity
|
||||
* @see https://versia.pub/extensions/polls
|
||||
* @example
|
||||
* {
|
||||
* "type": "Extension",
|
||||
* "id": "31c4de70-e266-4f61-b0f7-3767d3ccf565",
|
||||
* "id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||
* "type": "pub.versia:polls/Vote",
|
||||
* "uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "uri": "https://example.com/votes/31c4de70-e266-4f61-b0f7-3767d3ccf565",
|
||||
* "extension_type": "org.lysand:polls/Vote",
|
||||
* "poll": "https://example.com/polls/31c4de70-e266-4f61-b0f7-3767d3ccf565",
|
||||
* "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||
* "poll": "https://example.com/notes/f08a124e-fe90-439e-8be4-15a428a72a19",
|
||||
* "option": 1
|
||||
* }
|
||||
*/
|
||||
export const VoteSchema = ExtensionSchema.extend({
|
||||
extension_type: z.literal("org.lysand:polls/Vote"),
|
||||
export const VoteSchema = EntitySchema.extend({
|
||||
type: z.literal("pub.versia:polls/Vote"),
|
||||
author: z.string().url(),
|
||||
poll: z.string().url(),
|
||||
option: z.number(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @description Vote result extension entity
|
||||
* @see https://versia.pub/extensions/polls
|
||||
* @example
|
||||
* {
|
||||
* "type": "Extension",
|
||||
* "id": "c6d5755b-f42c-418f-ab53-2ee3705d6628",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "uri": "https://example.com/polls/c6d5755b-f42c-418f-ab53-2ee3705d6628/result",
|
||||
* "extension_type": "org.lysand:polls/VoteResult",
|
||||
* "poll": "https://example.com/polls/c6d5755b-f42c-418f-ab53-2ee3705d6628",
|
||||
* "votes": [9, 5, 0]
|
||||
* }
|
||||
*/
|
||||
export const VoteResultSchema = ExtensionSchema.extend({
|
||||
extension_type: z.literal("org.lysand:polls/VoteResult"),
|
||||
poll: z.string().url(),
|
||||
votes: z.array(z.number().int().nonnegative()),
|
||||
option: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.max(2 ** 64 - 1),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,24 +5,25 @@
|
|||
* @see https://versia.pub/extensions/reactions
|
||||
*/
|
||||
import { z } from "zod";
|
||||
import { ExtensionSchema } from "../base";
|
||||
import { EntitySchema } from "../base";
|
||||
|
||||
/**
|
||||
* @description Reaction extension entity
|
||||
* @see https://versia.pub/extensions/reactions
|
||||
* @example
|
||||
* {
|
||||
* "type": "Extension",
|
||||
* "id": "d6eb84ea-cd13-43f9-9c54-01244da8e5e3",
|
||||
* "id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||
* "type": "pub.versia:reactions/Reaction",
|
||||
* "uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "uri": "https://example.com/reactions/d6eb84ea-cd13-43f9-9c54-01244da8e5e3",
|
||||
* "extension_type": "org.lysand:reactions/Reaction",
|
||||
* "object": "https://example.com/posts/d6eb84ea-cd13-43f9-9c54-01244da8e5e3",
|
||||
* "content": "👍"
|
||||
* "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||
* "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19",
|
||||
* "content": "😀",
|
||||
* }
|
||||
*/
|
||||
export const ReactionSchema = ExtensionSchema.extend({
|
||||
extension_type: z.literal("org.lysand:reactions/Reaction"),
|
||||
export const ReactionSchema = EntitySchema.extend({
|
||||
type: z.literal("pub.versia:reactions/Reaction"),
|
||||
author: z.string().url(),
|
||||
object: z.string().url(),
|
||||
content: z.string(),
|
||||
content: z.string().min(1).max(256),
|
||||
});
|
||||
|
|
|
|||
21
federation/schemas/extensions/share.ts
Normal file
21
federation/schemas/extensions/share.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { z } from "zod";
|
||||
import { EntitySchema } from "../base";
|
||||
|
||||
/**
|
||||
* @description Share entity
|
||||
* @see https://versia.pub/extensions/share
|
||||
* @example
|
||||
* {
|
||||
* "id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "type": "pub.versia:share/Share",
|
||||
* "created_at": "2021-01-01T00:00:00.000Z",
|
||||
* "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||
* "uri": "https://example.com/shares/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||
* "shared": "https://otherexample.org/notes/fmKZ763jzIU8"
|
||||
* }
|
||||
*/
|
||||
export const ShareSchema = EntitySchema.extend({
|
||||
type: z.literal("pub.versia:share/Share"),
|
||||
author: z.string().url(),
|
||||
shared: z.string().url(),
|
||||
});
|
||||
|
|
@ -6,7 +6,11 @@
|
|||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import { ContentFormatSchema } from "../content_format";
|
||||
import {
|
||||
AudioOnlyContentFormatSchema,
|
||||
ImageOnlyContentFormatSchema,
|
||||
} from "../content_format";
|
||||
import { isISOString } from "../regex";
|
||||
|
||||
/**
|
||||
* @description Vanity extension entity
|
||||
|
|
@ -17,29 +21,31 @@ import { ContentFormatSchema } from "../content_format";
|
|||
* "type": "User",
|
||||
* // ...
|
||||
* "extensions": {
|
||||
* "org.lysand:vanity": {
|
||||
* "avatar_overlay": {
|
||||
* "image/png": {
|
||||
* "content": "https://cdn.example.com/ab5081cf-b11f-408f-92c2-7c246f290593/cat_ears.png",
|
||||
* "content_type": "image/png"
|
||||
* "pub.versia:vanity": {
|
||||
* "avatar_overlays": [
|
||||
* {
|
||||
* "image/png": {
|
||||
* "content": "https://cdn.example.com/ab5081cf-b11f-408f-92c2-7c246f290593/cat_ears.png",
|
||||
* "remote": true,
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* ],
|
||||
* "avatar_mask": {
|
||||
* "image/png": {
|
||||
* "content": "https://cdn.example.com/d8c42be1-d0f7-43ef-b4ab-5f614e1beba4/rounded_square.jpeg",
|
||||
* "content_type": "image/jpeg"
|
||||
* "remote": true,
|
||||
* }
|
||||
* },
|
||||
* "background": {
|
||||
* "image/png": {
|
||||
* "content": "https://cdn.example.com/6492ddcd-311e-4921-9567-41b497762b09/untitled-file-0019822.png",
|
||||
* "content_type": "image/png"
|
||||
* "remote": true,
|
||||
* }
|
||||
* },
|
||||
* "audio": {
|
||||
* "audio/mpeg": {
|
||||
* "content": "https://cdn.example.com/4da2f0d4-4728-4819-83e4-d614e4c5bebc/michael-jackson-thriller.mp3",
|
||||
* "content_type": "audio/mpeg"
|
||||
* "remote": true,
|
||||
* }
|
||||
* },
|
||||
* "pronouns": {
|
||||
|
|
@ -56,38 +62,46 @@ import { ContentFormatSchema } from "../content_format";
|
|||
* },
|
||||
* "birthday": "1998-04-12",
|
||||
* "location": "+40.6894-074.0447/",
|
||||
* "activitypub": [
|
||||
* "@erikuden@mastodon.de"
|
||||
* ],
|
||||
* "aliases": [
|
||||
* "https://burger.social/accounts/349ee237-c672-41c1-aadc-677e185f795a",
|
||||
* "https://social.lysand.org/users/f565ef02-035d-4974-ba5e-f62a8558331d"
|
||||
* "https://versia.social/users/f565ef02-035d-4974-ba5e-f62a8558331d"
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export const VanityExtensionSchema = z.object({
|
||||
avatar_overlay: ContentFormatSchema.optional().nullable(),
|
||||
avatar_mask: ContentFormatSchema.optional().nullable(),
|
||||
background: ContentFormatSchema.optional().nullable(),
|
||||
audio: ContentFormatSchema.optional().nullable(),
|
||||
pronouns: z.record(
|
||||
z.string(),
|
||||
z.array(
|
||||
z.union([
|
||||
z.object({
|
||||
subject: z.string(),
|
||||
object: z.string(),
|
||||
dependent_possessive: z.string(),
|
||||
independent_possessive: z.string(),
|
||||
reflexive: z.string(),
|
||||
}),
|
||||
z.string(),
|
||||
]),
|
||||
export const VanityExtensionSchema = z
|
||||
.object({
|
||||
avatar_overlays: z
|
||||
.array(ImageOnlyContentFormatSchema)
|
||||
.optional()
|
||||
.nullable(),
|
||||
avatar_mask: ImageOnlyContentFormatSchema.optional().nullable(),
|
||||
background: ImageOnlyContentFormatSchema.optional().nullable(),
|
||||
audio: AudioOnlyContentFormatSchema.optional().nullable(),
|
||||
pronouns: z.record(
|
||||
z.string(),
|
||||
z.array(
|
||||
z.union([
|
||||
z
|
||||
.object({
|
||||
subject: z.string(),
|
||||
object: z.string(),
|
||||
dependent_possessive: z.string(),
|
||||
independent_possessive: z.string(),
|
||||
reflexive: z.string(),
|
||||
})
|
||||
.strict(),
|
||||
z.string(),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
birthday: z.string().optional().nullable(),
|
||||
location: z.string().optional().nullable(),
|
||||
activitypub: z.string().optional().nullable(),
|
||||
});
|
||||
birthday: z
|
||||
.string()
|
||||
.refine((v) => isISOString(v), "must be a valid ISO8601 datetime")
|
||||
.optional()
|
||||
.nullable(),
|
||||
location: z.string().optional().nullable(),
|
||||
aliases: z.array(z.string().url()).optional().nullable(),
|
||||
})
|
||||
.strict();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue