refactor(api): ♻️ Move from @hono/zod-openapi to hono-openapi

hono-openapi is easier to work with and generates better OpenAPI definitions
This commit is contained in:
Jesse Wierzbinski 2025-03-29 03:30:06 +01:00
parent 0576aff972
commit 58342e86e1
No known key found for this signature in database
240 changed files with 9494 additions and 9575 deletions

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Account } from "./account.ts";
import { Appeal } from "./appeal.ts";
import { Id } from "./common.ts";
@ -49,9 +49,10 @@ export const AccountWarning = z
example: "2025-01-04T14:11:00Z",
}),
})
.openapi("AccountWarning", {
.openapi({
description: "Moderation warning against a particular account.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/AccountWarning",
},
ref: "AccountWarning",
});

View file

@ -1,5 +1,5 @@
import { userAddressValidator } from "@/api.ts";
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { iso631, zBoolean } from "./common.ts";
import { CustomEmoji } from "./emoji.ts";
@ -44,7 +44,7 @@ export const Field = z
},
}),
})
.openapi("AccountField");
.openapi({ ref: "AccountField" });
export const Source = z
.object({
@ -109,12 +109,13 @@ export const Source = z
description: "Metadata about the account.",
}),
})
.openapi("AccountSource", {
.openapi({
description:
"An extra attribute that contains source values to be used with API methods that verify credentials and update credentials.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Account/#source",
},
ref: "AccountSource",
});
// Because Account has some recursive references, we need to define it like this
@ -421,7 +422,7 @@ const BaseAccount = z
example: "2025-03-01T14:00:00.000Z",
}),
})
.openapi("BaseAccount");
.openapi({ ref: "BaseAccount" });
export const Account = BaseAccount.extend({
moved: BaseAccount.nullable()
@ -434,4 +435,4 @@ export const Account = BaseAccount.extend({
url: "https://docs.joinmastodon.org/entities/Account/#moved",
},
}),
}).openapi("Account");
}).openapi({ ref: "Account" });

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const Appeal = z
.object({
@ -13,9 +13,10 @@ export const Appeal = z
example: "pending",
}),
})
.openapi("Appeal", {
.openapi({
description: "Appeal against a moderation action.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Appeal",
},
ref: "Appeal",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const Application = z
.object({
@ -61,7 +61,9 @@ export const Application = z
},
}),
})
.openapi("Application");
.openapi({
ref: "Application",
});
export const CredentialApplication = Application.extend({
client_id: z.string().openapi({
@ -83,4 +85,6 @@ export const CredentialApplication = Application.extend({
url: "https://docs.joinmastodon.org/entities/CredentialApplication/#client_secret_expires_at",
},
}),
}).openapi("CredentialApplication");
}).openapi({
ref: "CredentialApplication",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { Id } from "./common.ts";
@ -67,10 +67,11 @@ export const Attachment = z
example: "UFBWY:8_0Jxv4mx]t8t64.%M-:IUWGWAt6M}",
}),
})
.openapi("Attachment", {
.openapi({
description:
"Represents a file or media attachment that can be added to a status.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Attachment",
},
ref: "Attachment",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Account } from "./account.ts";
export const PreviewCardAuthor = z
@ -27,7 +27,9 @@ export const PreviewCardAuthor = z
},
}),
})
.openapi("PreviewCardAuthor");
.openapi({
ref: "PreviewCardAuthor",
});
export const PreviewCard = z
.object({
@ -152,10 +154,11 @@ export const PreviewCard = z
},
}),
})
.openapi("PreviewCard", {
.openapi({
description:
"Represents a rich preview card that is generated using OpenGraph tags from a URL.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/PreviewCard",
},
ref: "PreviewCard",
});

View file

@ -1,13 +1,21 @@
import { z } from "@hono/zod-openapi";
import ISO6391 from "iso-639-1";
import { z } from "zod";
export const Id = z.string().uuid();
export const iso631 = z
.enum(ISO6391.getAllCodes() as [string, ...string[]])
.openapi("ISO631");
.openapi({
description: "ISO 639-1 language code",
example: "en",
externalDocs: {
url: "https://en.wikipedia.org/wiki/List_of_ISO_639-1_language_codes",
},
ref: "ISO631",
});
export const zBoolean = z
.string()
.transform((v) => ["true", "1", "on"].includes(v.toLowerCase()))
.openapi({ type: "boolean" })
.or(z.boolean());

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Status } from "./status.ts";
export const Context = z
@ -16,10 +16,11 @@ export const Context = z
},
}),
})
.openapi("Context", {
.openapi({
description:
"Represents the tree around a given status. Used for reconstructing threads of statuses.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Context/#context",
},
ref: "Context",
});

View file

@ -1,5 +1,5 @@
import { emojiValidator } from "@/api.ts";
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { Id, zBoolean } from "./common.ts";
@ -87,9 +87,10 @@ export const CustomEmoji = z
},
}),
})
.openapi("CustomEmoji", {
.openapi({
description: "Represents a custom emoji.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/CustomEmoji",
},
ref: "CustomEmoji",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const ExtendedDescription = z
.object({
@ -22,10 +22,11 @@ export const ExtendedDescription = z
},
}),
})
.openapi("ExtendedDescription", {
.openapi({
description:
"Represents an extended description for the instance, to be shown on its about page.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/ExtendedDescription",
},
ref: "ExtendedDescription",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Account } from "./account.ts";
export const FamiliarFollowers = z
@ -17,10 +17,11 @@ export const FamiliarFollowers = z
},
}),
})
.openapi("FamiliarFollowers", {
.openapi({
description:
"Represents a subset of your follows who also follow some other user.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/FamiliarFollowers",
},
ref: "FamiliarFollowers",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Id, zBoolean } from "./common.ts";
export const FilterStatus = z
@ -18,12 +18,13 @@ export const FilterStatus = z
},
}),
})
.openapi("FilterStatus", {
.openapi({
description:
"Represents a status ID that, if matched, should cause the filter action to be taken.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/FilterStatus",
},
ref: "FilterStatus",
});
export const FilterKeyword = z
@ -51,12 +52,13 @@ export const FilterKeyword = z
},
}),
})
.openapi("FilterKeyword", {
.openapi({
description:
"Represents a keyword that, if matched, should cause the filter action to be taken.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/FilterKeyword",
},
ref: "FilterKeyword",
});
export const Filter = z
@ -133,12 +135,13 @@ export const Filter = z
},
}),
})
.openapi("Filter", {
.openapi({
description:
"Represents a user-defined filter for determining which statuses should not be shown to the user.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Filter",
},
ref: "Filter",
});
export const FilterResult = z
@ -171,10 +174,11 @@ export const FilterResult = z
},
}),
})
.openapi("FilterResult", {
.openapi({
description:
"Represents a filter whose keywords matched a given status.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/FilterResult",
},
ref: "FilterResult",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Instance } from "./instance.ts";
import { SSOConfig } from "./versia.ts";
@ -132,10 +132,11 @@ export const InstanceV1 = z
/* Versia Server API extension */
sso: SSOConfig,
})
.openapi("InstanceV1", {
.openapi({
description:
"Represents the software instance of Versia Server running on this domain.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/V1_Instance",
},
ref: "InstanceV1",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import pkg from "~/package.json";
import { Account } from "./account.ts";
import { iso631 } from "./common.ts";
@ -18,10 +18,11 @@ const InstanceIcon = z
example: "36x36",
}),
})
.openapi("InstanceIcon", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/InstanceIcon",
},
ref: "InstanceIcon",
});
export const Instance = z
@ -375,8 +376,9 @@ export const Instance = z
/* Versia Server API extension */
sso: SSOConfig,
})
.openapi("Instance", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Instance",
},
ref: "Instance",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Id } from "./common.ts";
export const Marker = z
@ -17,10 +17,11 @@ export const Marker = z
example: "2025-01-12T13:11:00Z",
}),
})
.openapi("Marker", {
.openapi({
description:
"Represents the last read position within a user's timelines.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Marker",
},
ref: "Marker",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { AccountWarning } from "./account-warning.ts";
import { Account } from "./account.ts";
import { Id } from "./common.ts";
@ -62,10 +62,11 @@ export const Notification = z
"Moderation warning that caused the notification. Attached when type of the notification is moderation_warning.",
}),
})
.openapi("Notification", {
.openapi({
description:
"Represents a notification of an event relevant to the user.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Notification",
},
ref: "Notification",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { Id } from "./common.ts";
import { CustomEmoji } from "./emoji.ts";
@ -31,10 +31,11 @@ export const PollOption = z
},
}),
})
.openapi("PollOption", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Poll/#Option",
},
ref: "PollOption",
});
export const Poll = z
@ -130,9 +131,10 @@ export const Poll = z
},
}),
})
.openapi("Poll", {
.openapi({
description: "Represents a poll attached to a status.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Poll",
},
ref: "Poll",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Source } from "./account.ts";
export const Preferences = z
@ -42,9 +42,10 @@ export const Preferences = z
},
}),
})
.openapi("Preferences", {
.openapi({
description: "Represents a user's preferences.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Preferences",
},
ref: "Preferences",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const PrivacyPolicy = z
.object({
@ -21,9 +21,10 @@ export const PrivacyPolicy = z
},
}),
})
.openapi("PrivacyPolicy", {
.openapi({
description: "Represents the privacy policy of the instance.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/PrivacyPolicy",
},
ref: "PrivacyPolicy",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Id } from "./common.ts";
export const WebPushSubscription = z
@ -80,7 +80,7 @@ export const WebPushSubscription = z
description: "The streaming servers VAPID key.",
}),
})
.openapi("WebPushSubscription");
.openapi({ ref: "WebPushSubscription" });
export const WebPushSubscriptionInput = z
.object({

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Id, iso631 } from "./common.ts";
export const Relationship = z
@ -65,10 +65,11 @@ export const Relationship = z
example: "they also like Kerbal Space Program",
}),
})
.openapi("Relationship", {
.openapi({
description:
"Represents the relationship between accounts, such as following / blocking / muting / etc.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Relationship",
},
ref: "Relationship",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Account } from "./account.ts";
import { Id } from "./common.ts";
@ -50,10 +50,11 @@ export const Report = z
description: "The account that was reported.",
}),
})
.openapi("Report", {
.openapi({
description:
"Reports filed against users and/or statuses, to be taken action on by moderators.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Report",
},
ref: "Report",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const Rule = z
.object({
@ -15,9 +15,10 @@ export const Rule = z
example: "Please, we beg you.",
}),
})
.openapi("Rule", {
.openapi({
description: "Represents a rule that server users should follow.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Rule",
},
ref: "Rule",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { Account } from "./account.ts";
import { Status } from "./status.ts";
import { Tag } from "./tag.ts";
@ -15,9 +15,10 @@ export const Search = z
description: "Hashtags which match the given query",
}),
})
.openapi("Search", {
.openapi({
description: "Represents the results of a search.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Search",
},
ref: "Search",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { Account } from "./account.ts";
import { Attachment } from "./attachment.ts";
@ -42,10 +42,11 @@ export const Mention = z
},
}),
})
.openapi("Mention", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Status/#Mention",
},
ref: "Mention",
});
export const StatusSource = z
@ -75,10 +76,11 @@ export const StatusSource = z
example: "",
}),
})
.openapi("StatusSource", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/StatusSource",
},
ref: "StatusSource",
});
// Because Status has some recursive references, we need to define it like this
@ -356,7 +358,9 @@ const BaseStatus = z
},
}),
})
.openapi("BaseStatus");
.openapi({
ref: "BaseStatus",
});
export const Status = BaseStatus.extend({
reblog: BaseStatus.nullable().openapi({
@ -366,7 +370,9 @@ export const Status = BaseStatus.extend({
},
}),
quote: BaseStatus.nullable(),
}).openapi("Status");
}).openapi({
ref: "Status",
});
export const ScheduledStatus = z
.object({
@ -414,4 +420,6 @@ export const ScheduledStatus = z
}),
}),
})
.openapi("ScheduledStatus");
.openapi({
ref: "ScheduledStatus",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const Tag = z
.object({
@ -24,8 +24,9 @@ export const Tag = z
},
}),
})
.openapi("Tag", {
.openapi({
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Status/#Tag",
},
ref: "Tag",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const Token = z
.object({
@ -20,10 +20,11 @@ export const Token = z
example: 1573979017,
}),
})
.openapi("Token", {
.openapi({
description:
"Represents an OAuth token used for authenticating with the API and performing actions.",
externalDocs: {
url: "https://docs.joinmastodon.org/entities/Token",
},
ref: "Token",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
export const TermsOfService = z
.object({
@ -11,6 +11,7 @@ export const TermsOfService = z
example: "<p><h1>ToS</h1><p>None, have fun.</p></p>",
}),
})
.openapi("TermsOfService", {
.openapi({
description: "Represents the ToS of the instance.",
ref: "TermsOfService",
});

View file

@ -1,4 +1,4 @@
import { z } from "@hono/zod-openapi";
import { z } from "zod";
import { config } from "~/config.ts";
import { Id } from "./common.ts";
import { RolePermission } from "./permissions.ts";
@ -6,7 +6,7 @@ import { RolePermission } from "./permissions.ts";
/* Versia Server API extension */
export const Role = z
.object({
id: Id.openapi({}).openapi({
id: Id.openapi({
description: "The role ID in the database.",
example: "b4a7e0f0-8f6a-479b-910b-9265c070d5bd",
}),
@ -27,6 +27,7 @@ export const Role = z
RolePermission.ManageEmojis,
RolePermission.ManageAccounts,
],
type: "array",
}),
priority: z.number().int().default(0).openapi({
description:
@ -45,9 +46,10 @@ export const Role = z
example: "https://example.com/role-icon.png",
}),
})
.openapi("Role", {
.openapi({
description:
"Information about a role in the system, as well as its permissions.",
ref: "Role",
});
/* Versia Server API extension */
@ -72,8 +74,9 @@ export const NoteReaction = z
example: true,
}),
})
.openapi("NoteReaction", {
.openapi({
description: "Information about a reaction to a note.",
ref: "NoteReaction",
});
/* Versia Server API extension */
@ -134,6 +137,7 @@ export const Challenge = z
example: "1234567890",
}),
})
.openapi("Challenge", {
.openapi({
description: "A cryptographic challenge to solve. Used for Captchas.",
ref: "Challenge",
});