From 13e7027c378e85eb746e03bc6c673cabe2e29a7a Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Tue, 16 Jul 2024 20:01:07 +0200 Subject: [PATCH] feat(federation): :recycle: Make all optional fields also nullable --- federation/schemas/base.ts | 61 ++++++++++++++----------- federation/schemas/content_format.ts | 16 +++---- federation/schemas/extensions.ts | 3 +- federation/schemas/extensions/polls.ts | 2 +- federation/schemas/extensions/vanity.ts | 14 +++--- 5 files changed, 52 insertions(+), 44 deletions(-) diff --git a/federation/schemas/base.ts b/federation/schemas/base.ts index 693928c..b907fca 100644 --- a/federation/schemas/base.ts +++ b/federation/schemas/base.ts @@ -10,7 +10,7 @@ const EntitySchema = z.object({ created_at: z.string(), uri: z.string().url(), type: z.string(), - extensions: ExtensionPropertySchema.optional(), + extensions: ExtensionPropertySchema.optional().nullable().nullable(), }); const VisibilitySchema = z.enum(["public", "unlisted", "private", "direct"]); @@ -18,31 +18,35 @@ const VisibilitySchema = z.enum(["public", "unlisted", "private", "direct"]); const PublicationSchema = EntitySchema.extend({ type: z.enum(["Note", "Patch"]), author: z.string().url(), - content: ContentFormatSchema.optional(), - attachments: z.array(ContentFormatSchema).optional(), - replies_to: z.string().url().optional(), - quotes: z.string().url().optional(), - mentions: z.array(z.string().url()).optional(), - subject: z.string().optional(), - is_sensitive: z.boolean().optional(), + content: ContentFormatSchema.optional().nullable(), + attachments: z.array(ContentFormatSchema).optional().nullable(), + replies_to: z.string().url().optional().nullable(), + quotes: z.string().url().optional().nullable(), + mentions: z.array(z.string().url()).optional().nullable(), + subject: z.string().optional().nullable(), + is_sensitive: z.boolean().optional().nullable(), visibility: VisibilitySchema, extensions: ExtensionPropertySchema.extend({ "org.lysand:reactions": z .object({ reactions: z.string(), }) - .optional(), + .optional() + .nullable(), "org.lysand:polls": z .object({ poll: z.object({ options: z.array(ContentFormatSchema), votes: z.array(z.number().int().nonnegative()), - multiple_choice: z.boolean().optional(), + multiple_choice: z.boolean().optional().nullable(), expires_at: z.string(), }), }) - .optional(), - }).optional(), + .optional() + .nullable(), + }) + .optional() + .nullable(), }); const NoteSchema = PublicationSchema.extend({ @@ -62,13 +66,13 @@ const ActorPublicKeyDataSchema = z.object({ const UserSchema = EntitySchema.extend({ type: z.literal("User"), - display_name: z.string().optional(), + display_name: z.string().optional().nullable(), username: z.string(), - avatar: ContentFormatSchema.optional(), - header: ContentFormatSchema.optional(), + avatar: ContentFormatSchema.optional().nullable(), + header: ContentFormatSchema.optional().nullable(), indexable: z.boolean(), public_key: ActorPublicKeyDataSchema, - bio: ContentFormatSchema.optional(), + bio: ContentFormatSchema.optional().nullable(), fields: z .array( z.object({ @@ -76,7 +80,8 @@ const UserSchema = EntitySchema.extend({ value: ContentFormatSchema, }), ) - .optional(), + .optional() + .nullable(), featured: z.string().url(), followers: z.string().url(), following: z.string().url(), @@ -85,8 +90,10 @@ const UserSchema = EntitySchema.extend({ inbox: z.string().url(), outbox: z.string().url(), extensions: ExtensionPropertySchema.extend({ - "org.lysand:vanity": VanityExtensionSchema.optional(), - }).optional(), + "org.lysand:vanity": VanityExtensionSchema.optional().nullable(), + }) + .optional() + .nullable(), }); const ActionSchema = EntitySchema.extend({ @@ -146,7 +153,7 @@ const ReportSchema = ExtensionSchema.extend({ extension_type: z.literal("org.lysand:reports/Report"), objects: z.array(z.string().url()), reason: z.string(), - comment: z.string().optional(), + comment: z.string().optional().nullable(), }); const ServerMetadataSchema = EntitySchema.omit({ @@ -157,14 +164,14 @@ const ServerMetadataSchema = EntitySchema.omit({ type: z.literal("ServerMetadata"), name: z.string(), version: z.string(), - description: z.string().optional(), - website: z.string().optional(), - moderators: z.array(z.string()).optional(), - admins: z.array(z.string()).optional(), - logo: ContentFormatSchema.optional(), - banner: ContentFormatSchema.optional(), + description: z.string().optional().nullable(), + website: z.string().optional().nullable(), + moderators: z.array(z.string()).optional().nullable(), + admins: z.array(z.string()).optional().nullable(), + logo: ContentFormatSchema.optional().nullable(), + banner: ContentFormatSchema.optional().nullable(), supported_extensions: z.array(z.string()), - extensions: z.record(z.string(), z.any()).optional(), + extensions: z.record(z.string(), z.any()).optional().nullable(), }); export { diff --git a/federation/schemas/content_format.ts b/federation/schemas/content_format.ts index 0f740f1..3d2a5c6 100644 --- a/federation/schemas/content_format.ts +++ b/federation/schemas/content_format.ts @@ -5,13 +5,13 @@ export const ContentFormatSchema = z.record( z.enum(Object.values(types) as [string, ...string[]]), z.object({ content: z.string(), - description: z.string().optional(), - size: z.number().int().nonnegative().optional(), - hash: z.record(z.string(), z.string()).optional(), - blurhash: z.string().optional(), - fps: z.number().int().nonnegative().optional(), - width: z.number().int().nonnegative().optional(), - height: z.number().int().nonnegative().optional(), - duration: z.number().nonnegative().optional(), + description: z.string().optional().nullable(), + size: z.number().int().nonnegative().optional().nullable(), + hash: z.record(z.string(), z.string()).optional().nullable(), + blurhash: z.string().optional().nullable(), + fps: z.number().int().nonnegative().optional().nullable(), + width: z.number().int().nonnegative().optional().nullable(), + height: z.number().int().nonnegative().optional().nullable(), + duration: z.number().nonnegative().optional().nullable(), }), ); diff --git a/federation/schemas/extensions.ts b/federation/schemas/extensions.ts index 2da03aa..7078bde 100644 --- a/federation/schemas/extensions.ts +++ b/federation/schemas/extensions.ts @@ -2,5 +2,6 @@ import { z } from "zod"; import { CustomEmojiExtensionSchema } from "./extensions/custom_emojis"; export const ExtensionPropertySchema = z.object({ - "org.lysand:custom_emojis": CustomEmojiExtensionSchema.optional(), + "org.lysand:custom_emojis": + CustomEmojiExtensionSchema.optional().nullable(), }); diff --git a/federation/schemas/extensions/polls.ts b/federation/schemas/extensions/polls.ts index 534e767..7d5c7b3 100644 --- a/federation/schemas/extensions/polls.ts +++ b/federation/schemas/extensions/polls.ts @@ -47,7 +47,7 @@ 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(), + multiple_choice: z.boolean().optional().nullable(), expires_at: z.string(), }); diff --git a/federation/schemas/extensions/vanity.ts b/federation/schemas/extensions/vanity.ts index e44d048..059de6d 100644 --- a/federation/schemas/extensions/vanity.ts +++ b/federation/schemas/extensions/vanity.ts @@ -68,10 +68,10 @@ import { ContentFormatSchema } from "../content_format"; * } */ export const VanityExtensionSchema = z.object({ - avatar_overlay: ContentFormatSchema.optional(), - avatar_mask: ContentFormatSchema.optional(), - background: ContentFormatSchema.optional(), - audio: ContentFormatSchema.optional(), + 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( @@ -87,7 +87,7 @@ export const VanityExtensionSchema = z.object({ ]), ), ), - birthday: z.string().optional(), - location: z.string().optional(), - activitypub: z.string().optional(), + birthday: z.string().optional().nullable(), + location: z.string().optional().nullable(), + activitypub: z.string().optional().nullable(), });