diff --git a/packages/pl-api/lib/client.ts b/packages/pl-api/lib/client.ts index 6b20c4ba0..13cc6dd53 100644 --- a/packages/pl-api/lib/client.ts +++ b/packages/pl-api/lib/client.ts @@ -1,4 +1,4 @@ -import z from 'zod'; +import * as v from 'valibot'; import { accountSchema, @@ -227,14 +227,14 @@ class PlApiClient { } } - #paginatedGet = async (input: URL | RequestInfo, body: RequestBody, schema: T): Promise>> => { + #paginatedGet = async >(input: URL | RequestInfo, body: RequestBody, schema: T): Promise>> => { const getMore = (input: string | null) => input ? async () => { const response = await this.request(input); return { previous: getMore(getPrevLink(response)), next: getMore(getNextLink(response)), - items: filteredArray(schema).parse(response.json), + items: v.parse(filteredArray(schema), response.json), partial: response.status === 206, }; } : null; @@ -244,7 +244,7 @@ class PlApiClient { return { previous: getMore(getPrevLink(response)), next: getMore(getNextLink(response)), - items: filteredArray(schema).parse(response.json), + items: v.parse(filteredArray(schema), response.json), partial: response.status === 206, }; }; @@ -266,7 +266,7 @@ class PlApiClient { next: response.json?.count > (params.page_size * ((params.page || 1) - 1) + response.json?.users?.length) ? () => this.#paginatedPleromaAccounts({ ...params, page: (params.page || 0) + 1 }) : null, - items: filteredArray(adminAccountSchema).parse(response.json?.users), + items: v.parse(filteredArray(adminAccountSchema), response.json?.users), partial: response.status === 206, total: response.json?.total, }; @@ -285,7 +285,7 @@ class PlApiClient { next: response.json?.total > (params.page_size * ((params.page || 1) - 1) + response.json?.reports?.length) ? () => this.#paginatedPleromaReports({ ...params, page: (params.page || 0) + 1 }) : null, - items: filteredArray(adminReportSchema).parse(response.json?.reports), + items: v.parse(filteredArray(adminReportSchema), response.json?.reports), partial: response.status === 206, total: response.json?.total, }; @@ -305,7 +305,7 @@ class PlApiClient { next: response.json?.length ? () => this.#paginatedPleromaStatuses({ ...params, page: (params.page || 0) + 1 }) : null, - items: filteredArray(statusSchema).parse(response.json), + items: v.parse(filteredArray(statusSchema), response.json), partial: response.status === 206, }; }; @@ -320,7 +320,7 @@ class PlApiClient { createApplication: async (params: CreateApplicationParams) => { const response = await this.request('/api/v1/apps', { method: 'POST', body: params }); - return applicationSchema.parse(response.json); + return v.parse(applicationSchema, response.json); }, /** @@ -331,7 +331,7 @@ class PlApiClient { verifyApplication: async () => { const response = await this.request('/api/v1/apps/verify_credentials'); - return applicationSchema.parse(response.json); + return v.parse(applicationSchema, response.json); }, }; @@ -344,7 +344,7 @@ class PlApiClient { authorize: async (params: OauthAuthorizeParams) => { const response = await this.request('/oauth/authorize', { params }); - return z.string().parse(response.json); + return v.parse(v.string(), response.json); }, /** @@ -355,7 +355,7 @@ class PlApiClient { getToken: async (params: GetTokenParams) => { const response = await this.request('/oauth/token', { method: 'POST', body: params }); - return tokenSchema.parse(response.json); + return v.parse(tokenSchema, response.json); }, /** @@ -378,15 +378,15 @@ class PlApiClient { getCaptcha: async () => { const response = await this.request('/api/pleroma/captcha'); - return z.intersection(z.object({ - type: z.string(), - }), z.record(z.any())).parse(response.json); + return v.parse(v.intersect([v.object({ + type: v.string(), + }), z.record(v.any())]), response.json); }, mfaChallenge: async (params: MfaChallengeParams) => { const response = await this.request('/oauth/mfa/challenge', { method: 'POST', body: params }); - return tokenSchema.parse(response.json); + return v.parse(tokenSchema, response.json); }, }; @@ -407,7 +407,7 @@ class PlApiClient { getAccount: async (accountId: string, params?: GetAccountParams) => { const response = await this.request(`/api/v1/accounts/${accountId}`, { params }); - return accountSchema.parse(response.json); + return v.parse(accountSchema, response.json); }, /** @@ -420,7 +420,7 @@ class PlApiClient { getAccounts: async (accountId: string[]) => { const response = await this.request('/api/v1/accounts', { params: { id: accountId } }); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -455,7 +455,7 @@ class PlApiClient { getAccountFeaturedTags: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/featured_tags`); - return filteredArray(featuredTagSchema).parse(response.json); + return v.parse(filteredArray(featuredTagSchema), response.json); }, /** @@ -466,7 +466,7 @@ class PlApiClient { getAccountLists: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/lists`); - return filteredArray(listSchema).parse(response.json); + return v.parse(filteredArray(listSchema), response.json); }, /** @@ -477,7 +477,7 @@ class PlApiClient { followAccount: async (accountId: string, params?: FollowAccountParams) => { const response = await this.request(`/api/v1/accounts/${accountId}/follow`, { method: 'POST', body: params }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -488,7 +488,7 @@ class PlApiClient { unfollowAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/unfollow`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -499,7 +499,7 @@ class PlApiClient { removeAccountFromFollowers: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/remove_from_followers`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -510,7 +510,7 @@ class PlApiClient { pinAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/pin`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -521,7 +521,7 @@ class PlApiClient { unpinAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/unpin`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -532,7 +532,7 @@ class PlApiClient { updateAccountNote: async (accountId: string, comment: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/note`, { method: 'POST', body: { comment } }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -543,7 +543,7 @@ class PlApiClient { getRelationships: async (accountIds: string[], params?: GetRelationshipsParams) => { const response = await this.request('/api/v1/accounts/relationships', { params: { ...params, id: accountIds } }); - return filteredArray(relationshipSchema).parse(response.json); + return v.parse(filteredArray(relationshipSchema), response.json); }, /** @@ -556,7 +556,7 @@ class PlApiClient { getFamiliarFollowers: async (accountIds: string[]) => { const response = await this.request('/api/v1/accounts/familiar_followers', { params: { id: accountIds } }); - return filteredArray(familiarFollowersSchema).parse(response.json); + return v.parse(filteredArray(familiarFollowersSchema), response.json); }, /** @@ -567,7 +567,7 @@ class PlApiClient { searchAccounts: async (q: string, params?: SearchAccountParams, meta?: RequestMeta) => { const response = await this.request('/api/v1/accounts/search', { ...meta, params: { ...params, q } }); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -578,7 +578,7 @@ class PlApiClient { lookupAccount: async (acct: string, meta?: RequestMeta) => { const response = await this.request('/api/v1/accounts/lookup', { ...meta, params: { acct } }); - return accountSchema.parse(response.json); + return v.parse(accountSchema, response.json); }, /** @@ -591,7 +591,7 @@ class PlApiClient { body: { ...params, account_id: accountId }, }); - return reportSchema.parse(response.json); + return v.parse(reportSchema, response.json); }, /** @@ -604,7 +604,7 @@ class PlApiClient { getAccountEndorsements: async (accountId: string, params?: GetAccountEndorsementsParams) => { const response = await this.request(`/api/v1/pleroma/accounts/${accountId}/endorsements`, { params }); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -616,7 +616,7 @@ class PlApiClient { getBirthdays: async (day: number, month: number) => { const response = await this.request('/api/v1/pleroma/birthdays', { params: { day, month } }); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -641,9 +641,9 @@ class PlApiClient { if (response.json?.error) throw response.json.error; - return z.object({ - url: z.string(), - }).parse(response.json); + return v.parse(v.object({ + url: v.string(), + }), response.json); }, /** @@ -678,7 +678,7 @@ class PlApiClient { const response = await this.request('/api/v1/pleroma/scrobble', { body: params }); - return scrobbleSchema.parse(response.json); + return v.parse(scrobbleSchema, response.json); }, }; @@ -713,7 +713,7 @@ class PlApiClient { acceptFollowRequest: async (accountId: string) => { const response = await this.request(`/api/v1/follow_requests/${accountId}/authorize`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -723,7 +723,7 @@ class PlApiClient { rejectFollowRequest: async (accountId: string) => { const response = await this.request(`/api/v1/follow_requests/${accountId}/reject`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -742,7 +742,7 @@ class PlApiClient { getFeaturedTags: async () => { const response = await this.request('/api/v1/featured_tags'); - return filteredArray(featuredTagSchema).parse(response.json); + return v.parse(filteredArray(featuredTagSchema), response.json); }, /** @@ -756,7 +756,7 @@ class PlApiClient { body: { name }, }); - return filteredArray(featuredTagSchema).parse(response.json); + return v.parse(filteredArray(featuredTagSchema), response.json); }, /** @@ -781,7 +781,7 @@ class PlApiClient { getFeaturedTagsSuggestions: async () => { const response = await this.request('/api/v1/featured_tags/suggestions'); - return filteredArray(tagSchema).parse(response.json); + return v.parse(filteredArray(tagSchema), response.json); }, /** @@ -802,7 +802,7 @@ class PlApiClient { getTag: async (tagId: string) => { const response = await this.request(`/api/v1/tags/${tagId}`); - return tagSchema.parse(response.json); + return v.parse(tagSchema, response.json); }, /** @@ -813,7 +813,7 @@ class PlApiClient { followTag: async (tagId: string) => { const response = await this.request(`/api/v1/tags/${tagId}/follow`, { method: 'POST' }); - return tagSchema.parse(response.json); + return v.parse(tagSchema, response.json); }, /** @@ -824,7 +824,7 @@ class PlApiClient { unfollowTag: async (tagId: string) => { const response = await this.request(`/api/v1/tags/${tagId}/unfollow`, { method: 'POST' }); - return tagSchema.parse(response.json); + return v.parse(tagSchema, response.json); }, /** @@ -840,7 +840,7 @@ class PlApiClient { { params: { limit } }, ); - return filteredArray(suggestionSchema).parse(response.json); + return v.parse(filteredArray(suggestionSchema), response.json); }, /** @@ -865,7 +865,7 @@ class PlApiClient { getBookmarkFolders: async () => { const response = await this.request('/api/v1/pleroma/bookmark_folders'); - return filteredArray(bookmarkFolderSchema).parse(response.json); + return v.parse(filteredArray(bookmarkFolderSchema), response.json); }, /** @@ -877,7 +877,7 @@ class PlApiClient { createBookmarkFolder: async (params: CreateBookmarkFolderParams) => { const response = await this.request('/api/v1/pleroma/bookmark_folders', { method: 'POST', body: params }); - return bookmarkFolderSchema.parse(response.json); + return v.parse(bookmarkFolderSchema, response.json); }, /** @@ -889,7 +889,7 @@ class PlApiClient { updateBookmarkFolder: async (bookmarkFolderId: string, params: UpdateBookmarkFolderParams) => { const response = await this.request(`/api/v1/pleroma/bookmark_folders/${bookmarkFolderId}`, { method: 'PATCH', body: params }); - return bookmarkFolderSchema.parse(response.json); + return v.parse(bookmarkFolderSchema, response.json); }, /** @@ -901,7 +901,7 @@ class PlApiClient { deleteBookmarkFolder: async (bookmarkFolderId: string) => { const response = await this.request(`/api/v1/pleroma/bookmark_folders/${bookmarkFolderId}`, { method: 'DELETE' }); - return bookmarkFolderSchema.parse(response.json); + return v.parse(bookmarkFolderSchema, response.json); }, }; @@ -919,7 +919,7 @@ class PlApiClient { body: { language: params.locale, ...params }, }); - return tokenSchema.parse(response.json); + return v.parse(tokenSchema, response.json); }, /** @@ -930,7 +930,7 @@ class PlApiClient { verifyCredentials: async () => { const response = await this.request('/api/v1/accounts/verify_credentials'); - return credentialAccountSchema.parse(response.json); + return v.parse(credentialAccountSchema, response.json); }, /** @@ -955,7 +955,7 @@ class PlApiClient { body: params, }); - return credentialAccountSchema.parse(response.json); + return v.parse(credentialAccountSchema, response.json); }, /** @@ -966,7 +966,7 @@ class PlApiClient { deleteAvatar: async () => { const response = await this.request('/api/v1/profile/avatar', { method: 'DELETE' }); - return credentialAccountSchema.parse(response.json); + return v.parse(credentialAccountSchema, response.json); }, /** @@ -977,7 +977,7 @@ class PlApiClient { deleteHeader: async () => { const response = await this.request('/api/v1/profile/header', { method: 'DELETE' }); - return credentialAccountSchema.parse(response.json); + return v.parse(credentialAccountSchema, response.json); }, /** @@ -999,7 +999,7 @@ class PlApiClient { createBackup: async () => { const response = await this.request('/api/v1/pleroma/backups', { method: 'POST' }); - return backupSchema.parse(response.json); + return v.parse(backupSchema, response.json); }, /** @@ -1010,7 +1010,7 @@ class PlApiClient { getBackups: async () => { const response = await this.request('/api/v1/pleroma/backups'); - return filteredArray(backupSchema).parse(response.json); + return v.parse(filteredArray(backupSchema), response.json); }, /** @@ -1022,7 +1022,7 @@ class PlApiClient { getAccountAliases: async () => { const response = await this.request('/api/v1/pleroma/aliases'); - return z.object({ aliases: filteredArray(z.string()) }).parse(response.json); + return v.parse(v.object({ aliases: filteredArray(v.string()) }), response.json); }, /** @@ -1035,7 +1035,7 @@ class PlApiClient { addAccountAlias: async (alias: string) => { const response = await this.request('/api/v1/pleroma/aliases', { method: 'PUT', body: { alias } }); - return z.object({ status: z.literal('success') }).parse(response.json); + return v.parse(v.object({ status: v.literal('success') }), response.json); }, /** @@ -1048,7 +1048,7 @@ class PlApiClient { deleteAccountAlias: async (alias: string) => { const response = await this.request('/api/v1/pleroma/aliases', { method: 'DELETE', body: { alias } }); - return z.object({ status: z.literal('success') }).parse(response.json); + return v.parse(v.object({ status: v.literal('success') }), response.json); }, /** @@ -1060,7 +1060,7 @@ class PlApiClient { getOauthTokens: async () => { const response = await this.request('/api/oauth_tokens'); - return filteredArray(oauthTokenSchema).parse(response.json); + return v.parse(filteredArray(oauthTokenSchema), response.json); }, /** @@ -1221,12 +1221,12 @@ class PlApiClient { getMfaSettings: async () => { const response = await this.request('/api/pleroma/accounts/mfa'); - return z.object({ - settings: z.object({ - enabled: z.boolean(), - totp: z.boolean(), + return v.parse(v.object({ + settings: v.object({ + enabled: v.boolean(), + totp: v.boolean(), }), - }).parse(response.json); + }), response.json); }, /** @@ -1235,9 +1235,9 @@ class PlApiClient { getMfaBackupCodes: async () => { const response = await this.request('/api/pleroma/accounts/mfa/backup_codes'); - return z.object({ - codes: z.array(z.string()), - }).parse(response.json); + return v.parse(v.object({ + codes: v.array(v.string()), + }), response.json); }, /** @@ -1246,10 +1246,10 @@ class PlApiClient { getMfaSetup: async (method: 'totp') => { const response = await this.request(`/api/pleroma/accounts/mfa/setup/${method}`); - return z.object({ - key: z.string(), - provisioning_uri: z.string(), - }).parse(response.json); + return v.parse(v.object({ + key: v.string(), + provisioning_uri: v.string(), + }), response.json); }, /** @@ -1366,7 +1366,7 @@ class PlApiClient { if (response.json?.error) throw response.json.error; - return z.object({ status: z.string() }).parse(response.json); + return v.parse(v.object({ status: v.string() }), response.json); }, /** @@ -1378,7 +1378,7 @@ class PlApiClient { getInteractionPolicies: async () => { const response = await this.request('/api/v1/interaction_policies/defaults'); - return interactionPoliciesSchema.parse(response.json); + return v.parse(interactionPoliciesSchema, response.json); }, /** @@ -1390,7 +1390,7 @@ class PlApiClient { updateInteractionPolicies: async (params: UpdateInteractionPoliciesParams) => { const response = await this.request('/api/v1/interaction_policies/defaults', { method: 'PATCH', body: params }); - return interactionPoliciesSchema.parse(response.json); + return v.parse(interactionPoliciesSchema, response.json); }, /** @@ -1401,7 +1401,7 @@ class PlApiClient { getAvailableFrontends: async () => { const response = await this.request('/api/v1/akkoma/preferred_frontend/available'); - return z.array(z.string()).parse(response.json); + return v.parse(v.array(v.string()), response.json); }, /** @@ -1414,7 +1414,7 @@ class PlApiClient { setPreferredFrontend: async (frontendName: string) => { const response = await this.request('/api/v1/akkoma/preferred_frontend', { method: 'PUT', body: { frontend_name: frontendName } }); - return z.object({ frontend_name: z.string() }).parse(response.json); + return v.parse(v.object({ frontend_name: v.string() }), response.json); }, }; @@ -1427,7 +1427,7 @@ class PlApiClient { blockAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/block`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -1438,7 +1438,7 @@ class PlApiClient { unblockAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/unblock`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -1451,7 +1451,7 @@ class PlApiClient { muteAccount: async (accountId: string, params?: MuteAccountParams) => { const response = await this.request(`/api/v1/accounts/${accountId}/mute`, { method: 'POST', body: params }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -1464,7 +1464,7 @@ class PlApiClient { unmuteAccount: async (accountId: string) => { const response = await this.request(`/api/v1/accounts/${accountId}/unmute`, { method: 'POST' }); - return relationshipSchema.parse(response.json); + return v.parse(relationshipSchema, response.json); }, /** @@ -1490,7 +1490,7 @@ class PlApiClient { * @see {@link https://docs.joinmastodon.org/methods/domain_blocks/#get} */ getDomainBlocks: async (params?: GetDomainBlocksParams) => - this.#paginatedGet('/api/v1/domain_blocks', { params }, z.string()), + this.#paginatedGet('/api/v1/domain_blocks', { params }, v.string()), /** * Block a domain @@ -1531,7 +1531,7 @@ class PlApiClient { getFilters: async () => { const response = await this.request(this.features.filtersV2 ? '/api/v2/filters' : '/api/v1/filters'); - return filteredArray(filterSchema).parse(response.json); + return v.parse(filteredArray(filterSchema), response.json); }, /** @@ -1548,7 +1548,7 @@ class PlApiClient { : `/api/v1/filters/${filterId}`, ); - return filterSchema.parse(response.json); + return v.parse(filterSchema, response.json); }, /** @@ -1574,7 +1574,7 @@ class PlApiClient { }, ); - return filterSchema.parse(response.json); + return v.parse(filterSchema, response.json); }, /** @@ -1600,7 +1600,7 @@ class PlApiClient { }, ); - return filterSchema.parse(response.json); + return v.parse(filterSchema, response.json); }, /** @@ -1631,7 +1631,7 @@ class PlApiClient { getFilterKeywords: async (filterId: string) => { const response = await this.request(`/api/v2/filters/${filterId}/keywords`); - return filteredArray(filterKeywordSchema).parse(response.json); + return v.parse(filteredArray(filterKeywordSchema), response.json); }, /** @@ -1647,7 +1647,7 @@ class PlApiClient { body: { keyword, whole_word }, }); - return filterKeywordSchema.parse(response.json); + return v.parse(filterKeywordSchema, response.json); }, /** @@ -1660,7 +1660,7 @@ class PlApiClient { getFilterKeyword: async (filterId: string) => { const response = await this.request(`/api/v2/filters/keywords/${filterId}`); - return filterKeywordSchema.parse(response.json); + return v.parse(filterKeywordSchema, response.json); }, /** @@ -1676,7 +1676,7 @@ class PlApiClient { body: { keyword, whole_word }, }); - return filterKeywordSchema.parse(response.json); + return v.parse(filterKeywordSchema, response.json); }, /** @@ -1702,7 +1702,7 @@ class PlApiClient { getFilterStatuses: async (filterId: string) => { const response = await this.request(`/api/v2/filters/${filterId}/statuses`); - return filteredArray(filterStatusSchema).parse(response.json); + return v.parse(filteredArray(filterStatusSchema), response.json); }, /** @@ -1718,7 +1718,7 @@ class PlApiClient { body: { status_id: statusId }, }); - return filterStatusSchema.parse(response.json); + return v.parse(filterStatusSchema, response.json); }, /** @@ -1731,7 +1731,7 @@ class PlApiClient { getFilterStatus: async (statusId: string) => { const response = await this.request(`/api/v2/filters/statuses/${statusId}`); - return filterStatusSchema.parse(response.json); + return v.parse(filterStatusSchema, response.json); }, /** @@ -1761,8 +1761,8 @@ class PlApiClient { body: params, }); - if (response.json?.scheduled_at) return scheduledStatusSchema.parse(response.json); - return statusSchema.parse(response.json); + if (response.json?.scheduled_at) return v.parse(scheduledStatusSchema, response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1773,7 +1773,7 @@ class PlApiClient { getStatus: async (statusId: string, params?: GetStatusParams) => { const response = await this.request(`/api/v1/statuses/${statusId}`, { params }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1786,7 +1786,7 @@ class PlApiClient { getStatuses: async (statusIds: string[], params?: GetStatusesParams) => { const response = await this.request('/api/v1/statuses', { params: { ...params, id: statusIds } }); - return filteredArray(statusSchema).parse(response.json); + return v.parse(filteredArray(statusSchema), response.json); }, /** @@ -1797,7 +1797,7 @@ class PlApiClient { deleteStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}`, { method: 'DELETE' }); - return statusSourceSchema.parse(response.json); + return v.parse(statusSourceSchema, response.json); }, /** @@ -1808,7 +1808,7 @@ class PlApiClient { getContext: async (statusId: string, params?: GetStatusContextParams) => { const response = await this.request(`/api/v1/statuses/${statusId}/context`, { params }); - return contextSchema.parse(response.json); + return v.parse(contextSchema, response.json); }, /** @@ -1825,7 +1825,7 @@ class PlApiClient { response = await this.request(`/api/v1/statuses/${statusId}/translate`, { method: 'POST', body: { lang } }); } - return translationSchema.parse(response.json); + return v.parse(translationSchema, response.json); }, /** @@ -1836,7 +1836,7 @@ class PlApiClient { translateStatuses: async (statusIds: Array, lang: string) => { const response = await this.request('/api/v1/pl/statuses/translate', { method: 'POST', body: { ids: statusIds, lang } }); - return filteredArray(translationSchema).parse(response.json); + return v.parse(filteredArray(translationSchema), response.json); }, /** @@ -1863,7 +1863,7 @@ class PlApiClient { favouriteStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/favourite`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1874,7 +1874,7 @@ class PlApiClient { unfavouriteStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/unfavourite`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1885,7 +1885,7 @@ class PlApiClient { reblogStatus: async (statusId: string, visibility?: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/reblog`, { method: 'POST', body: { visibility } }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1896,7 +1896,7 @@ class PlApiClient { unreblogStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/unreblog`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1907,7 +1907,7 @@ class PlApiClient { bookmarkStatus: async (statusId: string, folderId?: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/bookmark`, { method: 'POST', body: { folder_id: folderId } }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1918,7 +1918,7 @@ class PlApiClient { unbookmarkStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/unbookmark`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1929,7 +1929,7 @@ class PlApiClient { muteStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/mute`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1940,7 +1940,7 @@ class PlApiClient { unmuteStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/unmute`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1951,7 +1951,7 @@ class PlApiClient { pinStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/pin`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1962,7 +1962,7 @@ class PlApiClient { unpinStatus: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/unpin`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1973,7 +1973,7 @@ class PlApiClient { editStatus: async (statusId: string, params: EditStatusParams) => { const response = await this.request(`/api/v1/statuses/${statusId}`, { method: 'PUT', body: params }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -1984,7 +1984,7 @@ class PlApiClient { getStatusHistory: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/history`); - return filteredArray(statusEditSchema).parse(response.json); + return v.parse(filteredArray(statusEditSchema), response.json); }, /** @@ -1995,7 +1995,7 @@ class PlApiClient { getStatusSource: async (statusId: string) => { const response = await this.request(`/api/v1/statuses/${statusId}/source`); - return statusSourceSchema.parse(response.json); + return v.parse(statusSourceSchema, response.json); }, /** @@ -2028,7 +2028,7 @@ class PlApiClient { }, []); } - return filteredArray(emojiReactionSchema).parse(response?.json || []); + return v.parse(filteredArray(emojiReactionSchema), response?.json || []); }, /** @@ -2048,7 +2048,7 @@ class PlApiClient { response = await this.request(`/api/v1/statuses/${statusId}/react/${encodeURIComponent(emoji)}`, { method: 'POST' }); } - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -2067,7 +2067,7 @@ class PlApiClient { response = await this.request(`/api/v1/statuses/${statusId}/unreact/${encodeURIComponent(emoji)}`, { method: 'POST' }); } - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -2087,7 +2087,7 @@ class PlApiClient { getDislikedBy: async (statusId: string) => { const response = await this.request(`/api/friendica/statuses/${statusId}/disliked_by`); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -2097,7 +2097,7 @@ class PlApiClient { dislikeStatus: async (statusId: string) => { const response = await this.request(`/api/friendica/statuses/${statusId}/dislike`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -2107,7 +2107,7 @@ class PlApiClient { undislikeStatus: async (statusId: string) => { const response = await this.request(`/api/friendica/statuses/${statusId}/undislike`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, }; @@ -2123,7 +2123,7 @@ class PlApiClient { { ...meta, method: 'POST', body: params, contentType: '' }, ); - return mediaAttachmentSchema.parse(response.json); + return v.parse(mediaAttachmentSchema, response.json); }, /** @@ -2134,7 +2134,7 @@ class PlApiClient { getMedia: async (attachmentId: string) => { const response = await this.request(`/api/v1/media/${attachmentId}`); - return mediaAttachmentSchema.parse(response.json); + return v.parse(mediaAttachmentSchema, response.json); }, /** @@ -2148,7 +2148,7 @@ class PlApiClient { body: params, contentType: params.thumbnail ? '' : undefined, }); - return mediaAttachmentSchema.parse(response.json); + return v.parse(mediaAttachmentSchema, response.json); }, }; @@ -2161,7 +2161,7 @@ class PlApiClient { getPoll: async (pollId: string) => { const response = await this.request(`/api/v1/polls/${pollId}`); - return pollSchema.parse(response.json); + return v.parse(pollSchema, response.json); }, /** @@ -2172,7 +2172,7 @@ class PlApiClient { vote: async (pollId: string, choices: number[]) => { const response = await this.request(`/api/v1/polls/${pollId}/votes`, { method: 'POST', body: { choices } }); - return pollSchema.parse(response.json); + return v.parse(pollSchema, response.json); }, }; @@ -2191,7 +2191,7 @@ class PlApiClient { getScheduledStatus: async (scheduledStatusId: string) => { const response = await this.request(`/api/v1/scheduled_statuses/${scheduledStatusId}`); - return scheduledStatusSchema.parse(response.json); + return v.parse(scheduledStatusSchema, response.json); }, /** @@ -2204,7 +2204,7 @@ class PlApiClient { body: { scheduled_at }, }); - return scheduledStatusSchema.parse(response.json); + return v.parse(scheduledStatusSchema, response.json); }, /** @@ -2284,7 +2284,7 @@ class PlApiClient { markConversationRead: async (conversationId: string) => { const response = await this.request(`/api/v1/conversations/${conversationId}/read`, { method: 'POST' }); - return conversationSchema.parse(response.json); + return v.parse(conversationSchema, response.json); }, /** @@ -2295,7 +2295,7 @@ class PlApiClient { getMarkers: async (timelines?: string[]) => { const response = await this.request('/api/v1/markers', { params: { timeline: timelines } }); - return markersSchema.parse(response.json); + return v.parse(markersSchema, response.json); }, /** @@ -2306,7 +2306,7 @@ class PlApiClient { saveMarkers: async (params: SaveMarkersParams) => { const response = await this.request('/api/v1/markers', { method: 'POST', body: params }); - return markersSchema.parse(response.json); + return v.parse(markersSchema, response.json); }, /** @@ -2331,7 +2331,7 @@ class PlApiClient { getLists: async () => { const response = await this.request('/api/v1/lists'); - return filteredArray(listSchema).parse(response.json); + return v.parse(filteredArray(listSchema), response.json); }, /** @@ -2342,7 +2342,7 @@ class PlApiClient { getList: async (listId: string) => { const response = await this.request(`/api/v1/lists/${listId}`); - return listSchema.parse(response.json); + return v.parse(listSchema, response.json); }, /** @@ -2353,7 +2353,7 @@ class PlApiClient { createList: async (params: CreateListParams) => { const response = await this.request('/api/v1/lists', { method: 'POST', body: params }); - return listSchema.parse(response.json); + return v.parse(listSchema, response.json); }, /** @@ -2364,7 +2364,7 @@ class PlApiClient { updateList: async (listId: string, params: UpdateListParams) => { const response = await this.request(`/api/v1/lists/${listId}`, { method: 'PUT', body: params }); - return listSchema.parse(response.json); + return v.parse(listSchema, response.json); }, /** @@ -2420,7 +2420,7 @@ class PlApiClient { health: async () => { const response = await this.request('/api/v1/streaming/health'); - return z.literal('OK').parse(response.json); + return v.parse(v.literal('OK'), response.json); }, /** @@ -2499,7 +2499,7 @@ class PlApiClient { getNotification: async (notificationId: string) => { const response = await this.request(`/api/v1/notifications/${notificationId}`); - return notificationSchema.parse(response.json); + return v.parse(notificationSchema, response.json); }, /** @@ -2532,7 +2532,7 @@ class PlApiClient { getNotificationPolicy: async () => { const response = await this.request('/api/v1/notifications/policy'); - return notificationPolicySchema.parse(response.json); + return v.parse(notificationPolicySchema, response.json); }, /** @@ -2543,7 +2543,7 @@ class PlApiClient { updateNotificationPolicy: async (params: UpdateNotificationPolicyRequest) => { const response = await this.request('/api/v1/notifications/policy', { method: 'POST', body: params }); - return notificationPolicySchema.parse(response.json); + return v.parse(notificationPolicySchema, response.json); }, /** @@ -2562,7 +2562,7 @@ class PlApiClient { getNotificationRequest: async (notificationRequestId: string) => { const response = await this.request(`/api/v1/notifications/requests/${notificationRequestId}`); - return notificationRequestSchema.parse(response.json); + return v.parse(notificationRequestSchema, response.json); }, /** @@ -2612,7 +2612,7 @@ class PlApiClient { createSubscription: async (params: CreatePushNotificationsSubscriptionParams) => { const response = await this.request('/api/v1/push/subscription', { method: 'POST', body: params }); - return webPushSubscriptionSchema.parse(response.json); + return v.parse(webPushSubscriptionSchema, response.json); }, /** @@ -2623,7 +2623,7 @@ class PlApiClient { getSubscription: async () => { const response = await this.request('/api/v1/push/subscription'); - return webPushSubscriptionSchema.parse(response.json); + return v.parse(webPushSubscriptionSchema, response.json); }, /** @@ -2634,7 +2634,7 @@ class PlApiClient { updateSubscription: async (params: UpdatePushNotificationsSubscriptionParams) => { const response = await this.request('/api/v1/push/subscription', { method: 'PUT', body: params }); - return webPushSubscriptionSchema.parse(response.json); + return v.parse(webPushSubscriptionSchema, response.json); }, /** @@ -2657,7 +2657,7 @@ class PlApiClient { search: async (q: string, params?: SearchParams, meta?: RequestMeta) => { const response = await this.request('/api/v2/search', { ...meta, params: { ...params, q } }); - return searchSchema.parse(response.json); + return v.parse(searchSchema, response.json); }, /** @@ -2669,7 +2669,7 @@ class PlApiClient { searchLocation: async (q: string, meta?: RequestMeta) => { const response = await this.request('/api/v1/pleroma/search/location', { ...meta, params: { q } }); - return filteredArray(locationSchema).parse(response.json); + return v.parse(filteredArray(locationSchema), response.json); }, }; @@ -2687,7 +2687,7 @@ class PlApiClient { response = await this.request('/api/v1/instance'); } - const instance = instanceSchema.readonly().parse(response.json); + const instance = v.parse(instanceSchema.readonly(), response.json); this.#setInstance(instance); return instance; @@ -2701,7 +2701,7 @@ class PlApiClient { getInstancePeers: async () => { const response = await this.request('/api/v1/instance/peers'); - return z.array(z.string()).parse(response.json); + return v.parse(v.array(v.string()), response.json); }, /** @@ -2712,12 +2712,12 @@ class PlApiClient { getInstanceActivity: async () => { const response = await this.request('/api/v1/instance/activity'); - return z.array(z.object({ - week: z.string(), + return v.parse(v.array(v.object({ + week: v.string(), statuses: z.coerce.string(), logins: z.coerce.string(), registrations: z.coerce.string(), - })).parse(response.json); + })), response.json); }, /** @@ -2728,7 +2728,7 @@ class PlApiClient { getInstanceRules: async () => { const response = await this.request('/api/v1/instance/rules'); - return filteredArray(ruleSchema).parse(response.json); + return v.parse(filteredArray(ruleSchema), response.json); }, /** @@ -2739,7 +2739,7 @@ class PlApiClient { getInstanceDomainBlocks: async () => { const response = await this.request('/api/v1/instance/rules'); - return filteredArray(domainBlockSchema).parse(response.json); + return v.parse(filteredArray(domainBlockSchema), response.json); }, /** @@ -2750,7 +2750,7 @@ class PlApiClient { getInstanceExtendedDescription: async () => { const response = await this.request('/api/v1/instance/extended_description'); - return extendedDescriptionSchema.parse(response.json); + return v.parse(extendedDescriptionSchema, response.json); }, /** @@ -2773,7 +2773,7 @@ class PlApiClient { const response = await this.request('/api/v1/instance/translation_languages'); - return z.record(z.array(z.string())).parse(response.json); + return v.parse(z.record(v.array(v.string())), response.json); }, /** @@ -2784,7 +2784,7 @@ class PlApiClient { profileDirectory: async (params?: ProfileDirectoryParams) => { const response = await this.request('/api/v1/directory', { params }); - return filteredArray(accountSchema).parse(response.json); + return v.parse(filteredArray(accountSchema), response.json); }, /** @@ -2795,7 +2795,7 @@ class PlApiClient { getCustomEmojis: async () => { const response = await this.request('/api/v1/custom_emojis'); - return filteredArray(customEmojiSchema).parse(response.json); + return v.parse(filteredArray(customEmojiSchema), response.json); }, /** @@ -2806,7 +2806,7 @@ class PlApiClient { getFrontendConfigurations: async () => { const response = await this.request('/api/pleroma/frontend_configurations'); - return z.record(z.record(z.any())).catch({}).parse(response.json); + return v.parse(z.record(z.record(v.any())).catch({}), response.json); }, }; @@ -2819,7 +2819,7 @@ class PlApiClient { getTrendingTags: async (params?: GetTrendingTags) => { const response = await this.request('/api/v1/trends/tags', { params }); - return filteredArray(tagSchema).parse(response.json); + return v.parse(filteredArray(tagSchema), response.json); }, /** @@ -2830,7 +2830,7 @@ class PlApiClient { getTrendingStatuses: async (params?: GetTrendingStatuses) => { const response = await this.request('/api/v1/trends/statuses', { params }); - return filteredArray(statusSchema).parse(response.json); + return v.parse(filteredArray(statusSchema), response.json); }, /** @@ -2841,7 +2841,7 @@ class PlApiClient { getTrendingLinks: async (params?: GetTrendingLinks) => { const response = await this.request('/api/v1/trends/links', { params }); - return filteredArray(trendsLinkSchema).parse(response.json); + return v.parse(filteredArray(trendsLinkSchema), response.json); }, }; @@ -2854,7 +2854,7 @@ class PlApiClient { getAnnouncements: async () => { const response = await this.request('/api/v1/announcements'); - return filteredArray(announcementSchema).parse(response.json); + return v.parse(filteredArray(announcementSchema), response.json); }, /** @@ -2935,7 +2935,7 @@ class PlApiClient { response = await this.request(`/api/v1/admin/users/${accountId}`); } - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -2955,7 +2955,7 @@ class PlApiClient { response.json = response.json?.users?.[0]; } - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -2977,7 +2977,7 @@ class PlApiClient { } }); } - return adminAccountSchema.safeParse(response.json).data || {}; + return v.safeParse(adminAccountSchema, response.json).output || {}; }, /** @@ -2988,7 +2988,7 @@ class PlApiClient { deleteAccount: async (accountId: string) => { const response = await this.request(`/api/v1/admin/accounts/${accountId}`, { method: 'DELETE' }); - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -3036,7 +3036,7 @@ class PlApiClient { response.json = response.json?.users?.[0]; } - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -3047,7 +3047,7 @@ class PlApiClient { unsilenceAccount: async (accountId: string) => { const response = await this.request(`/api/v1/admin/accounts/${accountId}/unsilence`, { method: 'POST' }); - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -3067,7 +3067,7 @@ class PlApiClient { response.json = response.json?.users?.[0]; } - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -3078,7 +3078,7 @@ class PlApiClient { unsensitiveAccount: async (accountId: string) => { const response = await this.request(`/api/v1/admin/accounts/${accountId}/unsensitive`, { method: 'POST' }); - return adminAccountSchema.parse(response.json); + return v.parse(adminAccountSchema, response.json); }, /** @@ -3218,7 +3218,7 @@ class PlApiClient { getDomainBlock: async (domainBlockId: string) => { const response = await this.request(`/api/v1/admin/domain_blocks/${domainBlockId}`); - return adminDomainBlockSchema.parse(response.json); + return v.parse(adminDomainBlockSchema, response.json); }, /** @@ -3232,7 +3232,7 @@ class PlApiClient { body: { ...params, domain }, }); - return adminDomainBlockSchema.parse(response.json); + return v.parse(adminDomainBlockSchema, response.json); }, /** @@ -3246,7 +3246,7 @@ class PlApiClient { body: params, }); - return adminDomainBlockSchema.parse(response.json); + return v.parse(adminDomainBlockSchema, response.json); }, /** @@ -3293,7 +3293,7 @@ class PlApiClient { response = await this.request(`/api/v1/pleroma/admin/reports/${reportId}`); } - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, /** @@ -3304,7 +3304,7 @@ class PlApiClient { updateReport: async (reportId: string, params: AdminUpdateReportParams) => { const response = await this.request(`/api/v1/admin/reports/${reportId}`, { method: 'PUT', body: params }); - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, /** @@ -3315,7 +3315,7 @@ class PlApiClient { assignReportToSelf: async (reportId: string) => { const response = await this.request(`/api/v1/admin/reports/${reportId}/assign_to_self`, { method: 'POST' }); - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, /** @@ -3326,7 +3326,7 @@ class PlApiClient { unassignReport: async (reportId: string) => { const response = await this.request(`/api/v1/admin/reports/${reportId}/unassign`, { method: 'POST' }); - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, /** @@ -3345,7 +3345,7 @@ class PlApiClient { }); } - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, /** @@ -3364,7 +3364,7 @@ class PlApiClient { }); } - return adminReportSchema.parse(response.json); + return v.parse(adminReportSchema, response.json); }, }, @@ -3394,7 +3394,7 @@ class PlApiClient { getStatus: async (statusId: string) => { const response = await this.request(`/api/v1/pleroma/admin/statuses/${statusId}`); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -3406,7 +3406,7 @@ class PlApiClient { updateStatus: async (statusId: string, params: AdminUpdateStatusParams) => { const response = await this.request(`/api/v1/pleroma/admin/statuses/${statusId}`, { method: 'PUT', body: params }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -3431,7 +3431,7 @@ class PlApiClient { getTrendingLinks: async () => { const response = await this.request('/api/v1/admin/trends/links'); - return filteredArray(trendsLinkSchema).parse(response.json); + return v.parse(filteredArray(trendsLinkSchema), response.json); }, /** @@ -3442,7 +3442,7 @@ class PlApiClient { getTrendingStatuses: async () => { const response = await this.request('/api/v1/admin/trends/statuses'); - return filteredArray(statusSchema).parse(response.json); + return v.parse(filteredArray(statusSchema), response.json); }, /** @@ -3453,7 +3453,7 @@ class PlApiClient { getTrendingTags: async () => { const response = await this.request('/api/v1/admin/trends/links'); - return filteredArray(adminTagSchema).parse(response.json); + return v.parse(filteredArray(adminTagSchema), response.json); }, }, @@ -3473,7 +3473,7 @@ class PlApiClient { getCanonicalEmailBlock: async (canonicalEmailBlockId: string) => { const response = await this.request(`/api/v1/admin/canonical_email_blocks/${canonicalEmailBlockId}`); - return adminCanonicalEmailBlockSchema.parse(response.json); + return v.parse(adminCanonicalEmailBlockSchema, response.json); }, /** @@ -3484,7 +3484,7 @@ class PlApiClient { testCanonicalEmailBlock: async (email: string) => { const response = await this.request('/api/v1/admin/canonical_email_blocks/test', { method: 'POST', body: { email } }); - return filteredArray(adminCanonicalEmailBlockSchema).parse(response.json); + return v.parse(filteredArray(adminCanonicalEmailBlockSchema), response.json); }, /** @@ -3494,7 +3494,7 @@ class PlApiClient { createCanonicalEmailBlock: async (email: string, canonical_email_hash?: string) => { const response = await this.request('/api/v1/admin/canonical_email_blocks', { method: 'POST', body: { email, canonical_email_hash } }); - return filteredArray(adminCanonicalEmailBlockSchema).parse(response.json); + return v.parse(filteredArray(adminCanonicalEmailBlockSchema), response.json); }, /** @@ -3518,7 +3518,7 @@ class PlApiClient { getDimensions: async (keys: AdminDimensionKey[], params?: AdminGetDimensionsParams) => { const response = await this.request('/api/v1/admin/dimensions', { params: { ...params, keys } }); - return filteredArray(adminDimensionSchema).parse(response.json); + return v.parse(filteredArray(adminDimensionSchema), response.json); }, }, @@ -3540,7 +3540,7 @@ class PlApiClient { getDomainAllow: async (domainAllowId: string) => { const response = await this.request(`/api/v1/admin/domain_allows/${domainAllowId}`); - return adminDomainAllowSchema.parse(response.json); + return v.parse(adminDomainAllowSchema, response.json); }, /** @@ -3551,7 +3551,7 @@ class PlApiClient { createDomainAllow: async (domain: string) => { const response = await this.request('/api/v1/admin/domain_allows', { method: 'POST', body: { domain } }); - return adminDomainAllowSchema.parse(response.json); + return v.parse(adminDomainAllowSchema, response.json); }, /** @@ -3584,7 +3584,7 @@ class PlApiClient { getEmailDomainBlock: async (emailDomainBlockId: string) => { const response = await this.request(`/api/v1/admin/email_domain_blocks/${emailDomainBlockId}`); - return adminEmailDomainBlockSchema.parse(response.json); + return v.parse(adminEmailDomainBlockSchema, response.json); }, /** @@ -3595,7 +3595,7 @@ class PlApiClient { createEmailDomainBlock: async (domain: string) => { const response = await this.request('/api/v1/admin/email_domain_blocks', { method: 'POST', body: { domain } }); - return adminEmailDomainBlockSchema.parse(response.json); + return v.parse(adminEmailDomainBlockSchema, response.json); }, /** @@ -3628,7 +3628,7 @@ class PlApiClient { getIpBlock: async (ipBlockId: string) => { const response = await this.request(`/api/v1/admin/ip_blocks/${ipBlockId}`); - return adminIpBlockSchema.parse(response.json); + return v.parse(adminIpBlockSchema, response.json); }, /** @@ -3639,7 +3639,7 @@ class PlApiClient { createIpBlock: async (params: AdminCreateIpBlockParams) => { const response = await this.request('/api/v1/admin/ip_blocks', { method: 'POST', body: params }); - return adminIpBlockSchema.parse(response.json); + return v.parse(adminIpBlockSchema, response.json); }, /** @@ -3650,7 +3650,7 @@ class PlApiClient { updateIpBlock: async (ipBlockId: string, params: AdminCreateIpBlockParams) => { const response = await this.request(`/api/v1/admin/ip_blocks/${ipBlockId}`, { method: 'POST', body: params }); - return adminIpBlockSchema.parse(response.json); + return v.parse(adminIpBlockSchema, response.json); }, /** @@ -3675,7 +3675,7 @@ class PlApiClient { getMeasures: async (keys: AdminMeasureKey[], start_at: string, end_at: string, params?: AdminGetMeasuresParams) => { const response = await this.request('/api/v1/admin/measures', { params: { ...params, keys, start_at, end_at } }); - return filteredArray(adminMeasureSchema).parse(response.json); + return v.parse(filteredArray(adminMeasureSchema), response.json); }, }, @@ -3690,7 +3690,7 @@ class PlApiClient { getRetention: async (start_at: string, end_at: string, frequency: 'day' | 'month') => { const response = await this.request('/api/v1/admin/retention', { params: { start_at, end_at, frequency } }); - return adminCohortSchema.parse(response.json); + return v.parse(adminCohortSchema, response.json); }, }, @@ -3704,7 +3704,7 @@ class PlApiClient { getAnnouncements: async (params?: AdminGetAnnouncementsParams): Promise> => { const response = await this.request('/api/v1/pleroma/admin/announcements', { params }); - const items = filteredArray(adminAnnouncementSchema).parse(response.json); + const items = v.parse(filteredArray(adminAnnouncementSchema), response.json); return { previous: null, @@ -3723,7 +3723,7 @@ class PlApiClient { getAnnouncement: async (announcementId: string) => { const response = await this.request(`/api/v1/pleroma/admin/announcements/${announcementId}`); - return adminAnnouncementSchema.parse(response.json); + return v.parse(adminAnnouncementSchema, response.json); }, /** @@ -3735,7 +3735,7 @@ class PlApiClient { createAnnouncement: async (params: AdminCreateAnnouncementParams) => { const response = await this.request('/api/v1/pleroma/admin/announcements', { method: 'POST', body: params }); - return adminAnnouncementSchema.parse(response.json); + return v.parse(adminAnnouncementSchema, response.json); }, /** @@ -3747,7 +3747,7 @@ class PlApiClient { updateAnnouncement: async (announcementId: string, params: AdminUpdateAnnouncementParams) => { const response = await this.request(`/api/v1/pleroma/admin/announcements/${announcementId}`, { method: 'PATCH', body: params }); - return adminAnnouncementSchema.parse(response.json); + return v.parse(adminAnnouncementSchema, response.json); }, /** @@ -3772,7 +3772,7 @@ class PlApiClient { getDomains: async () => { const response = await this.request('/api/v1/pleroma/admin/domains'); - return filteredArray(adminDomainSchema).parse(response.json); + return v.parse(filteredArray(adminDomainSchema), response.json); }, /** @@ -3783,7 +3783,7 @@ class PlApiClient { createDomain: async (params: AdminCreateDomainParams) => { const response = await this.request('/api/v1/pleroma/admin/domains', { method: 'POST', body: params }); - return adminDomainSchema.parse(response.json); + return v.parse(adminDomainSchema, response.json); }, /** @@ -3794,7 +3794,7 @@ class PlApiClient { updateDomain: async (domainId: string, isPublic: boolean) => { const response = await this.request(`/api/v1/pleroma/admin/domains/${domainId}`, { method: 'PATCH', body: { public: isPublic } }); - return adminDomainSchema.parse(response.json); + return v.parse(adminDomainSchema, response.json); }, /** @@ -3819,7 +3819,7 @@ class PlApiClient { getModerationLog: async ({ limit, ...params }: AdminGetModerationLogParams = {}): Promise> => { const response = await this.request('/api/v1/pleroma/admin/moderation_log', { params: { page_size: limit, ...params } }); - const items = filteredArray(adminModerationLogEntrySchema).parse(response.json.items); + const items = v.parse(filteredArray(adminModerationLogEntrySchema), response.json.items); return { previous: (params.page && params.page > 1) ? () => this.admin.moderationLog.getModerationLog({ ...params, page: params.page! - 1 }) : null, @@ -3840,7 +3840,7 @@ class PlApiClient { getRelays: async () => { const response = await this.request('/api/v1/pleroma/admin/relay'); - return filteredArray(adminRelaySchema).parse(response.json); + return v.parse(filteredArray(adminRelaySchema), response.json); }, /** @@ -3852,7 +3852,7 @@ class PlApiClient { followRelay: async (relayUrl: string) => { const response = await this.request('/api/v1/pleroma/admin/relay', { method: 'POST', body: { relay_url: relayUrl } }); - return adminRelaySchema.parse(response.json); + return v.parse(adminRelaySchema, response.json); }, /** @@ -3864,7 +3864,7 @@ class PlApiClient { unfollowRelay: async (relayUrl: string, force = false) => { const response = await this.request('/api/v1/pleroma/admin/relay', { method: 'DELETE', body: { relay_url: relayUrl, force } }); - return adminRelaySchema.parse(response.json); + return v.parse(adminRelaySchema, response.json); }, }, @@ -3878,7 +3878,7 @@ class PlApiClient { getRules: async () => { const response = await this.request('/api/v1/pleroma/admin/rules'); - return filteredArray(adminRuleSchema).parse(response.json); + return v.parse(filteredArray(adminRuleSchema), response.json); }, /** @@ -3890,7 +3890,7 @@ class PlApiClient { createRule: async (params: AdminCreateRuleParams) => { const response = await this.request('/api/v1/pleroma/admin/rules', { method: 'POST', body: params }); - return adminRuleSchema.parse(response.json); + return v.parse(adminRuleSchema, response.json); }, /** @@ -3902,7 +3902,7 @@ class PlApiClient { updateRule: async (ruleId: string, params: AdminUpdateRuleParams) => { const response = await this.request(`/api/v1/pleroma/admin/rules/${ruleId}`, { method: 'PATCH', body: params }); - return adminRuleSchema.parse(response.json); + return v.parse(adminRuleSchema, response.json); }, /** @@ -3922,13 +3922,13 @@ class PlApiClient { getPleromaConfig: async () => { const response = await this.request('/api/v1/pleroma/admin/config'); - return pleromaConfigSchema.parse(response.json); + return v.parse(pleromaConfigSchema, response.json); }, updatePleromaConfig: async (params: PleromaConfig['configs']) => { const response = await this.request('/api/v1/pleroma/admin/config', { method: 'POST', body: { configs: params } }); - return pleromaConfigSchema.parse(response.json); + return v.parse(pleromaConfigSchema, response.json); }, }, }; @@ -3941,18 +3941,18 @@ class PlApiClient { getOembed: async (url: string, maxwidth?: number, maxheight?: number) => { const response = await this.request('/api/oembed', { params: { url, maxwidth, maxheight } }); - return z.object({ - type: z.string().catch('rich'), - version: z.string().catch(''), - author_name: z.string().catch(''), - author_url: z.string().catch('').catch(''), - provider_name: z.string().catch(''), - provider_url: z.string().catch(''), - cache_age: z.number(), - html: z.string(), - width: z.number().nullable().catch(null), - height: z.number().nullable().catch(null), - }).parse(response.json); + return v.parse(v.object({ + type: v.fallback(v.string(), 'rich'), + version: v.fallback(v.string(), ''), + author_name: v.fallback(v.string(), ''), + author_url: v.fallback(v.string(), ''), + provider_name: v.fallback(v.string(), ''), + provider_url: v.fallback(v.string(), ''), + cache_age: v.number(), + html: v.string(), + width: v.fallback(v.nullable(v.number()), null), + height: v.fallback(v.nullable(v.number()), null), + }), response.json); }, }; @@ -3965,7 +3965,7 @@ class PlApiClient { createChat: async (accountId: string) => { const response = await this.request(`/api/v1/pleroma/chats/by-account-id/${accountId}`, { method: 'POST' }); - return chatSchema.parse(response.json); + return v.parse(chatSchema, response.json); }, /** @@ -3974,7 +3974,7 @@ class PlApiClient { getChat: async (chatId: string) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}`); - return chatSchema.parse(response.json); + return v.parse(chatSchema, response.json); }, /** @@ -3985,7 +3985,7 @@ class PlApiClient { markChatAsRead: async (chatId: string, last_read_id: string) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}/read`, { method: 'POST', body: { last_read_id } }); - return chatSchema.parse(response.json); + return v.parse(chatSchema, response.json); }, /** @@ -3996,7 +3996,7 @@ class PlApiClient { markChatMessageAsRead: async (chatId: string, chatMessageId: string) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}/messages/${chatMessageId}/read`, { method: 'POST' }); - return chatSchema.parse(response.json); + return v.parse(chatSchema, response.json); }, /** @@ -4022,7 +4022,7 @@ class PlApiClient { createChatMessage: async (chatId: string, params: CreateChatMessageParams) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}/messages`, { method: 'POST', body: params }); - return chatMessageSchema.parse(response.json); + return v.parse(chatMessageSchema, response.json); }, /** @@ -4033,7 +4033,7 @@ class PlApiClient { deleteChatMessage: async (chatId: string, messageId: string) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}/messages/${messageId}`, { method: 'DELETE' }); - return chatMessageSchema.parse(response.json); + return v.parse(chatMessageSchema, response.json); }, /** @@ -4044,7 +4044,7 @@ class PlApiClient { deleteChat: async (chatId: string) => { const response = await this.request(`/api/v1/pleroma/chats/${chatId}`, { method: 'DELETE' }); - return chatSchema.parse(response.json); + return v.parse(chatSchema, response.json); }, }; @@ -4056,7 +4056,7 @@ class PlApiClient { createEvent: async (params: CreateEventParams) => { const response = await this.request('/api/v1/pleroma/events', { method: 'POST', body: params }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4066,7 +4066,7 @@ class PlApiClient { editEvent: async (statusId: string, params: EditEventParams) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}`, { method: 'PUT', body: params }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4088,9 +4088,9 @@ class PlApiClient { * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsidparticipation_requests} */ getEventParticipationRequests: async (statusId: string, params?: GetEventParticipationRequestsParams) => - this.#paginatedGet(`/api/v1/pleroma/events/${statusId}/participation_requests`, { params }, z.object({ + this.#paginatedGet(`/api/v1/pleroma/events/${statusId}/participation_requests`, { params }, v.object({ account: accountSchema, - participation_message: z.string().catch(''), + participation_message: v.fallback(v.string(), ''), })), /** @@ -4100,7 +4100,7 @@ class PlApiClient { acceptEventParticipationRequest: async (statusId: string, accountId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/participation_requests/${accountId}/authorize`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4110,7 +4110,7 @@ class PlApiClient { rejectEventParticipationRequest: async (statusId: string, accountId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/participation_requests/${accountId}/reject`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4120,7 +4120,7 @@ class PlApiClient { joinEvent: async (statusId: string, participation_message?: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/join`, { method: 'POST', body: { participation_message } }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4130,7 +4130,7 @@ class PlApiClient { leaveEvent: async (statusId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/leave`, { method: 'POST' }); - return statusSchema.parse(response.json); + return v.parse(statusSchema, response.json); }, /** @@ -4161,7 +4161,7 @@ class PlApiClient { getInteractionRequest: async (interactionRequestId: string) => { const response = await this.request(`/api/v1/interaction_requests/${interactionRequestId}`); - return interactionRequestSchema.parse(response.json); + return v.parse(interactionRequestSchema, response.json); }, /** @@ -4172,7 +4172,7 @@ class PlApiClient { authorizeInteractionRequest: async (interactionRequestId: string) => { const response = await this.request(`/api/v1/interaction_requests/${interactionRequestId}/authorize`, { method: 'POST' }); - return interactionRequestSchema.parse(response.json); + return v.parse(interactionRequestSchema, response.json); }, /** @@ -4183,7 +4183,7 @@ class PlApiClient { rejectInteractionRequest: async (interactionRequestId: string) => { const response = await this.request(`/api/v1/interaction_requests/${interactionRequestId}/authorize`, { method: 'POST' }); - return interactionRequestSchema.parse(response.json); + return v.parse(interactionRequestSchema, response.json); }, }; @@ -4196,35 +4196,35 @@ class PlApiClient { getGroups: async (params?: AdminGetGroupsParams) => { const response = await this.request('/api/v1/admin/groups', { params }); - return filteredArray(groupSchema).parse(response.json); + return v.parse(filteredArray(groupSchema), response.json); }, /** return basic group information */ getGroup: async (groupId: string) => { const response = await this.request(`/api/v1/admin/groups/${groupId}`); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** suspends a group */ suspendGroup: async (groupId: string) => { const response = await this.request(`/api/v1/admin/groups/${groupId}/suspend`, { method: 'POST' }); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** lift a suspension */ unsuspendGroup: async (groupId: string) => { const response = await this.request(`/api/v1/admin/groups/${groupId}/unsuspend`, { method: 'POST' }); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** deletes an already-suspended group */ deleteGroup: async (groupId: string) => { const response = await this.request(`/api/v1/admin/groups/${groupId}`, { method: 'DELETE' }); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, }, }, @@ -4235,7 +4235,7 @@ class PlApiClient { getGroups: async () => { const response = await this.request('/api/v1/groups'); - return filteredArray(groupSchema).parse(response.json); + return v.parse(filteredArray(groupSchema), response.json); }, /** create a group with the given attributes (`display_name`, `note`, `avatar` and `header`). Sets the user who made the request as group administrator */ @@ -4246,14 +4246,14 @@ class PlApiClient { contentType: params.avatar || params.header ? '' : undefined, }); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** returns the `Group` entity describing a given group */ getGroup: async (groupId: string) => { const response = await this.request(`/api/v1/groups/${groupId}`); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** update group attributes (`display_name`, `note`, `avatar` and `header`) */ @@ -4264,7 +4264,7 @@ class PlApiClient { contentType: params.avatar || params.header ? '' : undefined, }); - return groupSchema.parse(response.json); + return v.parse(groupSchema, response.json); }, /** irreversibly deletes the group */ @@ -4325,14 +4325,14 @@ class PlApiClient { joinGroup: async (groupId: string) => { const response = await this.request(`/api/v1/groups/${groupId}/join`, { method: 'POST' }); - return groupRelationshipSchema.parse(response.json); + return v.parse(groupRelationshipSchema, response.json); }, /** leaves a given group */ leaveGroup: async (groupId: string) => { const response = await this.request(`/api/v1/groups/${groupId}/leave`, { method: 'POST' }); - return groupRelationshipSchema.parse(response.json); + return v.parse(groupRelationshipSchema, response.json); }, /** kick one or more group members */ @@ -4346,20 +4346,20 @@ class PlApiClient { promoteGroupUsers: async (groupId: string, accountIds: string[], role: GroupRole) => { const response = await this.request(`/api/v1/groups/${groupId}/promote`, { method: 'POST', params: { account_ids: accountIds, role } }); - return filteredArray(groupMemberSchema).parse(response.json); + return v.parse(filteredArray(groupMemberSchema), response.json); }, /** demote one or more accounts to role `new_role`. Returns an error unless every of the target account has a strictly lower role than the user (you cannot demote someone with the same role as you), or if any target account already has a role lower than `new_role`. Valid roles are `admin`, `moderator` and `user`. */ demoteGroupUsers: async (groupId: string, accountIds: string[], role: GroupRole) => { const response = await this.request(`/api/v1/groups/${groupId}/demote`, { method: 'POST', params: { account_ids: accountIds, role } }); - return filteredArray(groupMemberSchema).parse(response.json); + return v.parse(filteredArray(groupMemberSchema), response.json); }, getGroupRelationships: async (groupIds: string[]) => { const response = await this.request('/api/v1/groups/relationships', { params: { id: groupIds } }); - return filteredArray(groupRelationshipSchema).parse(response.json); + return v.parse(filteredArray(groupRelationshipSchema), response.json); }, }, }; diff --git a/packages/pl-api/lib/entities/account-warning.ts b/packages/pl-api/lib/entities/account-warning.ts index 3a00a76c8..1065dbc38 100644 --- a/packages/pl-api/lib/entities/account-warning.ts +++ b/packages/pl-api/lib/entities/account-warning.ts @@ -1,25 +1,25 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { dateSchema } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/Appeal/} */ -const appealSchema = z.object({ - text: z.string(), - state: z.enum(['approved', 'rejected', 'pending']), +const appealSchema = v.object({ + text: v.string(), + state: v.picklist(['approved', 'rejected', 'pending']), }); /** @see {@link https://docs.joinmastodon.org/entities/AccountWarning/} */ -const accountWarningSchema = z.object({ - id: z.string(), - action: z.enum(['none', 'disable', 'mark_statuses_as_sensitive', 'delete_statuses', 'sensitive', 'silence', 'suspend']), - text: z.string().catch(''), - status_ids: z.array(z.string()).catch([]), +const accountWarningSchema = v.object({ + id: v.string(), + action: v.picklist(['none', 'disable', 'mark_statuses_as_sensitive', 'delete_statuses', 'sensitive', 'silence', 'suspend']), + text: v.fallback(v.string(), ''), + status_ids: v.fallback(v.array(v.string()), []), target_account: accountSchema, - appeal: appealSchema.nullable().catch(null), + appeal: v.fallback(v.nullable(appealSchema), null), created_at: dateSchema, }); -type AccountWarning = z.infer; +type AccountWarning = v.InferOutput; export { accountWarningSchema, type AccountWarning }; diff --git a/packages/pl-api/lib/entities/account.ts b/packages/pl-api/lib/entities/account.ts index e4a2c2b07..ee9a970e2 100644 --- a/packages/pl-api/lib/entities/account.ts +++ b/packages/pl-api/lib/entities/account.ts @@ -1,5 +1,5 @@ import pick from 'lodash.pick'; -import z from 'zod'; +import * as v from 'valibot'; import { customEmojiSchema } from './custom-emoji'; import { relationshipSchema } from './relationship'; @@ -61,64 +61,64 @@ const preprocessAccount = (account: any) => { }; }; -const fieldSchema = z.object({ - name: z.string(), - value: z.string(), +const fieldSchema = v.object({ + name: v.string(), + value: v.string(), verified_at: z.string().datetime({ offset: true }).nullable().catch(null), }); -const baseAccountSchema = z.object({ - id: z.string(), - username: z.string().catch(''), - acct: z.string().catch(''), +const baseAccountSchema = v.object({ + id: v.string(), + username: v.fallback(v.string(), ''), + acct: v.fallback(v.string(), ''), url: z.string().url(), - display_name: z.string().catch(''), - note: z.string().catch(''), - avatar: z.string().catch(''), + display_name: v.fallback(v.string(), ''), + note: v.fallback(v.string(), ''), + avatar: v.fallback(v.string(), ''), avatar_static: z.string().url().catch(''), header: z.string().url().catch(''), header_static: z.string().url().catch(''), - locked: z.boolean().catch(false), + locked: v.fallback(v.boolean(), false), fields: filteredArray(fieldSchema), emojis: filteredArray(customEmojiSchema), - bot: z.boolean().catch(false), - group: z.boolean().catch(false), - discoverable: z.boolean().catch(false), - noindex: z.boolean().nullable().catch(null), - suspended: z.boolean().optional().catch(undefined), - limited: z.boolean().optional().catch(undefined), + bot: v.fallback(v.boolean(), false), + group: v.fallback(v.boolean(), false), + discoverable: v.fallback(v.boolean(), false), + noindex: v.fallback(v.optional(v.nullable()), null), + suspended: v.fallback(v.optional(v.boolean()), undefined), + limited: v.fallback(v.optional(v.boolean()), undefined), created_at: z.string().datetime().catch(new Date().toUTCString()), last_status_at: z.string().date().nullable().catch(null), - statuses_count: z.number().catch(0), - followers_count: z.number().catch(0), - following_count: z.number().catch(0), + statuses_count: v.fallback(v.number(), 0), + followers_count: v.fallback(v.number(), 0), + following_count: v.fallback(v.number(), 0), roles: filteredArray(roleSchema), - fqn: z.string().nullable().catch(null), - ap_id: z.string().nullable().catch(null), - background_image: z.string().nullable().catch(null), + fqn: v.fallback(v.nullable(v.string()), null), + ap_id: v.fallback(v.nullable(v.string()), null), + background_image: v.fallback(v.nullable(v.string()), null), relationship: relationshipSchema.optional().catch(undefined), - is_moderator: z.boolean().optional().catch(undefined), - is_admin: z.boolean().optional().catch(undefined), - is_suggested: z.boolean().optional().catch(undefined), - hide_favorites: z.boolean().catch(true), - hide_followers: z.boolean().optional().catch(undefined), - hide_follows: z.boolean().optional().catch(undefined), - hide_followers_count: z.boolean().optional().catch(undefined), - hide_follows_count: z.boolean().optional().catch(undefined), - accepts_chat_messages: z.boolean().nullable().catch(null), - favicon: z.string().optional().catch(undefined), + is_moderator: v.fallback(v.optional(v.boolean()), undefined), + is_admin: v.fallback(v.optional(v.boolean()), undefined), + is_suggested: v.fallback(v.optional(v.boolean()), undefined), + hide_favorites: v.fallback(v.boolean(), true), + hide_followers: v.fallback(v.optional(v.boolean()), undefined), + hide_follows: v.fallback(v.optional(v.boolean()), undefined), + hide_followers_count: v.fallback(v.optional(v.boolean()), undefined), + hide_follows_count: v.fallback(v.optional(v.boolean()), undefined), + accepts_chat_messages: v.fallback(v.optional(v.nullable()), null), + favicon: v.fallback(v.optional(v.string()), undefined), birthday: z.string().date().optional().catch(undefined), - deactivated: z.boolean().optional().catch(undefined), + deactivated: v.fallback(v.optional(v.boolean()), undefined), - location: z.string().optional().catch(undefined), + location: v.fallback(v.optional(v.string()), undefined), local: z.boolean().optional().catch(false), - avatar_description: z.string().catch(''), - enable_rss: z.boolean().catch(false), - header_description: z.string().catch(''), + avatar_description: v.fallback(v.string(), ''), + enable_rss: v.fallback(v.boolean(), false), + header_description: v.fallback(v.string(), ''), - verified: z.boolean().optional().catch(undefined), + verified: v.fallback(v.optional(v.boolean()), undefined), __meta: coerceObject({ pleroma: z.any().optional().catch(undefined), @@ -137,47 +137,47 @@ type WithMoved = { moved: Account | null; }; -type Account = z.infer & WithMoved; +type Account = v.InferOutput & WithMoved; const accountSchema: z.ZodType = untypedAccountSchema as any; const untypedCredentialAccountSchema = z.preprocess(preprocessAccount, accountWithMovedAccountSchema.extend({ - source: z.object({ - note: z.string().catch(''), + source: v.object({ + note: v.fallback(v.string(), ''), fields: filteredArray(fieldSchema), privacy: z.enum(['public', 'unlisted', 'private', 'direct']), - sensitive: z.boolean().catch(false), - language: z.string().nullable().catch(null), + sensitive: v.fallback(v.boolean(), false), + language: v.fallback(v.nullable(v.string()), null), follow_requests_count: z.number().int().nonnegative().catch(0), show_role: z.boolean().optional().nullable().catch(undefined), no_rich_text: z.boolean().optional().nullable().catch(undefined), - discoverable: z.boolean().optional().catch(undefined), - actor_type: z.string().optional().catch(undefined), - show_birthday: z.boolean().optional().catch(undefined), + discoverable: v.fallback(v.optional(v.boolean()), undefined), + actor_type: v.fallback(v.optional(v.string()), undefined), + show_birthday: v.fallback(v.optional(v.boolean()), undefined), }).nullable().catch(null), - role: roleSchema.nullable().catch(null), + role: v.fallback(v.nullable(roleSchema), null), settings_store: z.record(z.any()).optional().catch(undefined), - chat_token: z.string().optional().catch(undefined), - allow_following_move: z.boolean().optional().catch(undefined), + chat_token: v.fallback(v.optional(v.string()), undefined), + allow_following_move: v.fallback(v.optional(v.boolean()), undefined), unread_conversation_count: z.number().optional().catch(undefined), unread_notifications_count: z.number().optional().catch(undefined), - notification_settings: z.object({ - block_from_strangers: z.boolean().catch(false), - hide_notification_contents: z.boolean().catch(false), + notification_settings: v.object({ + block_from_strangers: v.fallback(v.boolean(), false), + hide_notification_contents: v.fallback(v.boolean(), false), }).optional().catch(undefined), })); -type CredentialAccount = z.infer & WithMoved; +type CredentialAccount = v.InferOutput & WithMoved; const credentialAccountSchema: z.ZodType = untypedCredentialAccountSchema as any; const untypedMutedAccountSchema = z.preprocess(preprocessAccount, accountWithMovedAccountSchema.extend({ - mute_expires_at: dateSchema.nullable().catch(null), + mute_expires_at: v.fallback(v.nullable(dateSchema), null), })); -type MutedAccount = z.infer & WithMoved; +type MutedAccount = v.InferOutput & WithMoved; const mutedAccountSchema: z.ZodType = untypedMutedAccountSchema as any; diff --git a/packages/pl-api/lib/entities/admin/account.ts b/packages/pl-api/lib/entities/admin/account.ts index 3e25324aa..e142ccfe3 100644 --- a/packages/pl-api/lib/entities/admin/account.ts +++ b/packages/pl-api/lib/entities/admin/account.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from '../account'; import { roleSchema } from '../role'; @@ -36,32 +36,32 @@ const adminAccountSchema = z.preprocess((account: any) => { }; } return account; -}, z.object({ - id: z.string(), - username: z.string(), - domain: z.string().nullable().catch(null), +}, v.object({ + id: v.string(), + username: v.string(), + domain: v.fallback(v.nullable(v.string()), null), created_at: dateSchema, - email: z.string().nullable().catch(null), + email: v.fallback(v.nullable(v.string()), null), ip: z.string().ip().nullable().catch(null), ips: filteredArray(adminIpSchema), - locale: z.string().nullable().catch(null), - invite_request: z.string().nullable().catch(null), - role: roleSchema.nullable().catch(null), - confirmed: z.boolean().catch(false), - approved: z.boolean().catch(false), - disabled: z.boolean().catch(false), - silenced: z.boolean().catch(false), - suspended: z.boolean().catch(false), - account: accountSchema.nullable().catch(null), - created_by_application_id: z.string().optional().catch(undefined), - invited_by_account_id: z.string().optional().catch(undefined), + locale: v.fallback(v.nullable(v.string()), null), + invite_request: v.fallback(v.nullable(v.string()), null), + role: v.fallback(v.nullable(roleSchema), null), + confirmed: v.fallback(v.boolean(), false), + approved: v.fallback(v.boolean(), false), + disabled: v.fallback(v.boolean(), false), + silenced: v.fallback(v.boolean(), false), + suspended: v.fallback(v.boolean(), false), + account: v.fallback(v.nullable(accountSchema), null), + created_by_application_id: v.fallback(v.optional(v.string()), undefined), + invited_by_account_id: v.fallback(v.optional(v.string()), undefined), - actor_type: z.string().nullable().catch(null), - display_name: z.string().nullable().catch(null), - suggested: z.boolean().nullable().catch(null), + actor_type: v.fallback(v.nullable(v.string()), null), + display_name: v.fallback(v.nullable(v.string()), null), + suggested: v.fallback(v.optional(v.nullable()), null), })); -type AdminAccount = z.infer; +type AdminAccount = v.InferOutput; export { adminAccountSchema, diff --git a/packages/pl-api/lib/entities/admin/announcement.ts b/packages/pl-api/lib/entities/admin/announcement.ts index 365413d64..3a670a7f4 100644 --- a/packages/pl-api/lib/entities/admin/announcement.ts +++ b/packages/pl-api/lib/entities/admin/announcement.ts @@ -1,5 +1,5 @@ import pick from 'lodash.pick'; -import { z } from 'zod'; +import * as v from 'valibot'; import { announcementSchema } from '../announcement'; @@ -8,9 +8,9 @@ const adminAnnouncementSchema = z.preprocess((announcement: any) => ({ ...announcement, ...pick(announcement.pleroma, 'raw_content'), }), announcementSchema.extend({ - raw_content: z.string().catch(''), + raw_content: v.fallback(v.string(), ''), })); -type AdminAnnouncement = z.infer; +type AdminAnnouncement = v.InferOutput; export { adminAnnouncementSchema, type AdminAnnouncement }; diff --git a/packages/pl-api/lib/entities/admin/canonical-email-block.ts b/packages/pl-api/lib/entities/admin/canonical-email-block.ts index 817028c20..2394bb44b 100644 --- a/packages/pl-api/lib/entities/admin/canonical-email-block.ts +++ b/packages/pl-api/lib/entities/admin/canonical-email-block.ts @@ -1,12 +1,12 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_CanonicalEmailBlock/} */ -const adminCanonicalEmailBlockSchema = z.object({ - id: z.string(), - canonical_email_hash: z.string(), +const adminCanonicalEmailBlockSchema = v.object({ + id: v.string(), + canonical_email_hash: v.string(), }); -type AdminCanonicalEmailBlock = z.infer; +type AdminCanonicalEmailBlock = v.InferOutput; export { adminCanonicalEmailBlockSchema, diff --git a/packages/pl-api/lib/entities/admin/cohort.ts b/packages/pl-api/lib/entities/admin/cohort.ts index 5c3cb3ea8..72ae379d6 100644 --- a/packages/pl-api/lib/entities/admin/cohort.ts +++ b/packages/pl-api/lib/entities/admin/cohort.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_Cohort/} */ -const adminCohortSchema = z.object({ +const adminCohortSchema = v.object({ period: z.string().datetime({ offset: true }), frequency: z.enum(['day', 'month']), - data: z.array(z.object({ + data: z.array(v.object({ date: z.string().datetime({ offset: true }), rate: z.number(), value: z.number().int(), })), }); -type AdminCohort = z.infer; +type AdminCohort = v.InferOutput; export { adminCohortSchema, diff --git a/packages/pl-api/lib/entities/admin/dimension.ts b/packages/pl-api/lib/entities/admin/dimension.ts index 45105a2a7..b382da6a7 100644 --- a/packages/pl-api/lib/entities/admin/dimension.ts +++ b/packages/pl-api/lib/entities/admin/dimension.ts @@ -1,18 +1,18 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_Dimension/} */ -const adminDimensionSchema = z.object({ - key: z.string(), - data: z.object({ - key: z.string(), - human_key: z.string(), - value: z.string(), - unit: z.string().optional().catch(undefined), - human_value: z.string().optional().catch(undefined), +const adminDimensionSchema = v.object({ + key: v.string(), + data: v.object({ + key: v.string(), + human_key: v.string(), + value: v.string(), + unit: v.fallback(v.optional(v.string()), undefined), + human_value: v.fallback(v.optional(v.string()), undefined), }), }); -type AdminDimension = z.infer; +type AdminDimension = v.InferOutput; export { adminDimensionSchema, diff --git a/packages/pl-api/lib/entities/admin/domain-allow.ts b/packages/pl-api/lib/entities/admin/domain-allow.ts index a012938f0..be6c73078 100644 --- a/packages/pl-api/lib/entities/admin/domain-allow.ts +++ b/packages/pl-api/lib/entities/admin/domain-allow.ts @@ -1,15 +1,15 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from '../utils'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainAllow/} */ -const adminDomainAllowSchema = z.object({ - id: z.string(), - domain: z.string(), +const adminDomainAllowSchema = v.object({ + id: v.string(), + domain: v.string(), created_at: dateSchema, }); -type AdminDomainAllow = z.infer; +type AdminDomainAllow = v.InferOutput; export { adminDomainAllowSchema, diff --git a/packages/pl-api/lib/entities/admin/domain-block.ts b/packages/pl-api/lib/entities/admin/domain-block.ts index b1452c3ea..9d87e63a6 100644 --- a/packages/pl-api/lib/entities/admin/domain-block.ts +++ b/packages/pl-api/lib/entities/admin/domain-block.ts @@ -1,22 +1,22 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from '../utils'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainBlock/} */ -const adminDomainBlockSchema = z.object({ - id: z.string(), - domain: z.string(), - digest: z.string(), +const adminDomainBlockSchema = v.object({ + id: v.string(), + domain: v.string(), + digest: v.string(), created_at: dateSchema, severity: z.enum(['silence', 'suspend', 'noop']), - reject_media: z.boolean(), - reject_reports: z.boolean(), - private_comment: z.string().nullable().catch(null), - public_comment: z.string().nullable().catch(null), - obfuscate: z.boolean(), + reject_media: v.boolean(), + reject_reports: v.boolean(), + private_comment: v.fallback(v.nullable(v.string()), null), + public_comment: v.fallback(v.nullable(v.string()), null), + obfuscate: v.boolean(), }); -type AdminDomainBlock = z.infer; +type AdminDomainBlock = v.InferOutput; export { adminDomainBlockSchema, diff --git a/packages/pl-api/lib/entities/admin/domain.ts b/packages/pl-api/lib/entities/admin/domain.ts index 73c3a8f58..67d6253ad 100644 --- a/packages/pl-api/lib/entities/admin/domain.ts +++ b/packages/pl-api/lib/entities/admin/domain.ts @@ -1,13 +1,13 @@ -import z from 'zod'; +import * as v from 'valibot'; -const adminDomainSchema = z.object({ - domain: z.string().catch(''), +const adminDomainSchema = v.object({ + domain: v.fallback(v.string(), ''), id: z.coerce.string(), - public: z.boolean().catch(false), - resolves: z.boolean().catch(false), + public: v.fallback(v.boolean(), false), + resolves: v.fallback(v.boolean(), false), last_checked_at: z.string().datetime().catch(''), }); -type AdminDomain = z.infer +type AdminDomain = v.InferOutput export { adminDomainSchema, type AdminDomain }; diff --git a/packages/pl-api/lib/entities/admin/email-domain-block.ts b/packages/pl-api/lib/entities/admin/email-domain-block.ts index 093ee85f5..d3c57e179 100644 --- a/packages/pl-api/lib/entities/admin/email-domain-block.ts +++ b/packages/pl-api/lib/entities/admin/email-domain-block.ts @@ -1,20 +1,20 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from '../utils'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_EmailDomainBlock/} */ -const adminEmailDomainBlockSchema = z.object({ - id: z.string(), - domain: z.string(), +const adminEmailDomainBlockSchema = v.object({ + id: v.string(), + domain: v.string(), created_at: dateSchema, - history: z.array(z.object({ + history: v.array(v.object({ day: z.coerce.string(), accounts: z.coerce.string(), uses: z.coerce.string(), })), }); -type AdminEmailDomainBlock = z.infer; +type AdminEmailDomainBlock = v.InferOutput; export { adminEmailDomainBlockSchema, diff --git a/packages/pl-api/lib/entities/admin/ip-block.ts b/packages/pl-api/lib/entities/admin/ip-block.ts index f3cf6bfe3..580627a08 100644 --- a/packages/pl-api/lib/entities/admin/ip-block.ts +++ b/packages/pl-api/lib/entities/admin/ip-block.ts @@ -1,18 +1,18 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from '../utils'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_IpBlock/} */ -const adminIpBlockSchema = z.object({ - id: z.string(), +const adminIpBlockSchema = v.object({ + id: v.string(), ip: z.string().ip(), severity: z.enum(['sign_up_requires_approval', 'sign_up_block', 'no_access']), - comment: z.string().catch(''), + comment: v.fallback(v.string(), ''), created_at: dateSchema, expires_at: z.string().datetime({ offset: true }), }); -type AdminIpBlock = z.infer; +type AdminIpBlock = v.InferOutput; export { adminIpBlockSchema, diff --git a/packages/pl-api/lib/entities/admin/ip.ts b/packages/pl-api/lib/entities/admin/ip.ts index e27b30f30..83ebb5654 100644 --- a/packages/pl-api/lib/entities/admin/ip.ts +++ b/packages/pl-api/lib/entities/admin/ip.ts @@ -1,14 +1,14 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from '../utils'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_Ip/} */ -const adminIpSchema = z.object({ +const adminIpSchema = v.object({ ip: z.string().ip(), used_at: dateSchema, }); -type AdminIp = z.infer; +type AdminIp = v.InferOutput; export { adminIpSchema, diff --git a/packages/pl-api/lib/entities/admin/measure.ts b/packages/pl-api/lib/entities/admin/measure.ts index 5e1cda5da..f1c9cb8de 100644 --- a/packages/pl-api/lib/entities/admin/measure.ts +++ b/packages/pl-api/lib/entities/admin/measure.ts @@ -1,19 +1,19 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Admin_Measure/} */ -const adminMeasureSchema = z.object({ - key: z.string(), - unit: z.string().nullable().catch(null), +const adminMeasureSchema = v.object({ + key: v.string(), + unit: v.fallback(v.nullable(v.string()), null), total: z.coerce.number(), - human_value: z.string().optional().catch(undefined), + human_value: v.fallback(v.optional(v.string()), undefined), previous_total: z.coerce.string().optional().catch(undefined), - data: z.array(z.object({ + data: z.array(v.object({ date: z.string().datetime({ offset: true }), value: z.coerce.string(), })), }); -type AdminMeasure = z.infer; +type AdminMeasure = v.InferOutput; export { adminMeasureSchema, diff --git a/packages/pl-api/lib/entities/admin/moderation-log-entry.ts b/packages/pl-api/lib/entities/admin/moderation-log-entry.ts index 0bd93ef37..b901128a1 100644 --- a/packages/pl-api/lib/entities/admin/moderation-log-entry.ts +++ b/packages/pl-api/lib/entities/admin/moderation-log-entry.ts @@ -1,13 +1,13 @@ -import z from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminmoderation_log} */ -const adminModerationLogEntrySchema = z.object({ +const adminModerationLogEntrySchema = v.object({ id: z.coerce.string(), - data: z.record(z.string(), z.any()).catch({}), - time: z.number().catch(0), - message: z.string().catch(''), + data: z.record(v.string(), z.any()).catch({}), + time: v.fallback(v.number(), 0), + message: v.fallback(v.string(), ''), }); -type AdminModerationLogEntry = z.infer +type AdminModerationLogEntry = v.InferOutput export { adminModerationLogEntrySchema, type AdminModerationLogEntry }; diff --git a/packages/pl-api/lib/entities/admin/pleroma-config.ts b/packages/pl-api/lib/entities/admin/pleroma-config.ts index 8bb49e5f0..8fb09f5a3 100644 --- a/packages/pl-api/lib/entities/admin/pleroma-config.ts +++ b/packages/pl-api/lib/entities/admin/pleroma-config.ts @@ -1,14 +1,14 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const pleromaConfigSchema = z.object({ - configs: z.array(z.object({ +const pleromaConfigSchema = v.object({ + configs: z.array(v.object({ value: z.any(), - group: z.string(), - key: z.string(), + group: v.string(), + key: v.string(), })), - need_reboot: z.boolean(), + need_reboot: v.boolean(), }); -type PleromaConfig = z.infer +type PleromaConfig = v.InferOutput export { pleromaConfigSchema, type PleromaConfig }; diff --git a/packages/pl-api/lib/entities/admin/relay.ts b/packages/pl-api/lib/entities/admin/relay.ts index b084b2353..ce19ea3ca 100644 --- a/packages/pl-api/lib/entities/admin/relay.ts +++ b/packages/pl-api/lib/entities/admin/relay.ts @@ -1,11 +1,11 @@ -import z from 'zod'; +import * as v from 'valibot'; -const adminRelaySchema = z.preprocess((data: any) => ({ id: data.actor, ...data }), z.object({ - actor: z.string().catch(''), - id: z.string(), - followed_back: z.boolean().catch(false), +const adminRelaySchema = z.preprocess((data: any) => ({ id: data.actor, ...data }), v.object({ + actor: v.fallback(v.string(), ''), + id: v.string(), + followed_back: v.fallback(v.boolean(), false), })); -type AdminRelay = z.infer +type AdminRelay = v.InferOutput export { adminRelaySchema, type AdminRelay }; diff --git a/packages/pl-api/lib/entities/admin/report.ts b/packages/pl-api/lib/entities/admin/report.ts index a669517c4..7b64b0f67 100644 --- a/packages/pl-api/lib/entities/admin/report.ts +++ b/packages/pl-api/lib/entities/admin/report.ts @@ -1,5 +1,5 @@ import pick from 'lodash.pick'; -import { z } from 'zod'; +import * as v from 'valibot'; import { ruleSchema } from '../rule'; import { statusWithoutAccountSchema } from '../status'; @@ -24,23 +24,23 @@ const adminReportSchema = z.preprocess((report: any) => { }; } return report; -}, z.object({ - id: z.string(), - action_taken: z.boolean().optional().catch(undefined), - action_taken_at: dateSchema.nullable().catch(null), - category: z.string().optional().catch(undefined), - comment: z.string().optional().catch(undefined), - forwarded: z.boolean().optional().catch(undefined), +}, v.object({ + id: v.string(), + action_taken: v.fallback(v.optional(v.boolean()), undefined), + action_taken_at: v.fallback(v.nullable(dateSchema), null), + category: v.fallback(v.optional(v.string()), undefined), + comment: v.fallback(v.optional(v.string()), undefined), + forwarded: v.fallback(v.optional(v.boolean()), undefined), created_at: dateSchema.optional().catch(undefined), updated_at: dateSchema.optional().catch(undefined), account: adminAccountSchema, target_account: adminAccountSchema, - assigned_account: adminAccountSchema.nullable().catch(null), - action_taken_by_account: adminAccountSchema.nullable().catch(null), + assigned_account: v.fallback(v.nullable(adminAccountSchema), null), + action_taken_by_account: v.fallback(v.nullable(adminAccountSchema), null), statuses: filteredArray(statusWithoutAccountSchema), rules: filteredArray(ruleSchema), })); -type AdminReport = z.infer; +type AdminReport = v.InferOutput; export { adminReportSchema, type AdminReport }; diff --git a/packages/pl-api/lib/entities/admin/rule.ts b/packages/pl-api/lib/entities/admin/rule.ts index a3dc1d2ab..41838af6a 100644 --- a/packages/pl-api/lib/entities/admin/rule.ts +++ b/packages/pl-api/lib/entities/admin/rule.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminrules} */ -const adminRuleSchema = z.object({ - id: z.string(), - text: z.string().catch(''), - hint: z.string().catch(''), - priority: z.number().nullable().catch(null), +const adminRuleSchema = v.object({ + id: v.string(), + text: v.fallback(v.string(), ''), + hint: v.fallback(v.string(), ''), + priority: v.fallback(v.nullable(v.number()), null), }); -type AdminRule = z.infer; +type AdminRule = v.InferOutput; export { adminRuleSchema, type AdminRule }; diff --git a/packages/pl-api/lib/entities/admin/tag.ts b/packages/pl-api/lib/entities/admin/tag.ts index 467de653a..983a64538 100644 --- a/packages/pl-api/lib/entities/admin/tag.ts +++ b/packages/pl-api/lib/entities/admin/tag.ts @@ -1,16 +1,16 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { tagSchema } from '../tag'; /** @see {@link https://docs.joinmastodon.org/entities/Tag/#admin} */ const adminTagSchema = tagSchema.extend({ - id: z.string(), - trendable: z.boolean(), - usable: z.boolean(), - requires_review: z.boolean(), + id: v.string(), + trendable: v.boolean(), + usable: v.boolean(), + requires_review: v.boolean(), }); -type AdminTag = z.infer; +type AdminTag = v.InferOutput; export { adminTagSchema, diff --git a/packages/pl-api/lib/entities/announcement-reaction.ts b/packages/pl-api/lib/entities/announcement-reaction.ts index 8949dbd3e..9fb1a0da7 100644 --- a/packages/pl-api/lib/entities/announcement-reaction.ts +++ b/packages/pl-api/lib/entities/announcement-reaction.ts @@ -1,15 +1,15 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/announcement/} */ -const announcementReactionSchema = z.object({ - name: z.string().catch(''), +const announcementReactionSchema = v.object({ + name: v.fallback(v.string(), ''), count: z.number().int().nonnegative().catch(0), - me: z.boolean().catch(false), - url: z.string().nullable().catch(null), - static_url: z.string().nullable().catch(null), - announcement_id: z.string().catch(''), + me: v.fallback(v.boolean(), false), + url: v.fallback(v.nullable(v.string()), null), + static_url: v.fallback(v.nullable(v.string()), null), + announcement_id: v.fallback(v.string(), ''), }); -type AnnouncementReaction = z.infer; +type AnnouncementReaction = v.InferOutput; export { announcementReactionSchema, type AnnouncementReaction }; diff --git a/packages/pl-api/lib/entities/announcement.ts b/packages/pl-api/lib/entities/announcement.ts index 535fb954e..f161e97d0 100644 --- a/packages/pl-api/lib/entities/announcement.ts +++ b/packages/pl-api/lib/entities/announcement.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { announcementReactionSchema } from './announcement-reaction'; import { customEmojiSchema } from './custom-emoji'; @@ -7,20 +7,20 @@ import { tagSchema } from './tag'; import { dateSchema, filteredArray } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/announcement/} */ -const announcementSchema = z.object({ - id: z.string(), - content: z.string().catch(''), +const announcementSchema = v.object({ + id: v.string(), + content: v.fallback(v.string(), ''), starts_at: z.string().datetime().nullable().catch(null), ends_at: z.string().datetime().nullable().catch(null), - all_day: z.boolean().catch(false), - read: z.boolean().catch(false), + all_day: v.fallback(v.boolean(), false), + read: v.fallback(v.boolean(), false), published_at: dateSchema, reactions: filteredArray(announcementReactionSchema), statuses: z.preprocess( (statuses: any) => Array.isArray(statuses) ? Object.fromEntries(statuses.map((status: any) => [status.url, status.account?.acct]) || []) : statuses, - z.record(z.string(), z.string()), + z.record(v.string(), v.string()), ), mentions: filteredArray(mentionSchema), tags: filteredArray(tagSchema), @@ -28,6 +28,6 @@ const announcementSchema = z.object({ updated_at: dateSchema, }); -type Announcement = z.infer; +type Announcement = v.InferOutput; export { announcementSchema, type Announcement }; diff --git a/packages/pl-api/lib/entities/application.ts b/packages/pl-api/lib/entities/application.ts index 03377910b..6d3949378 100644 --- a/packages/pl-api/lib/entities/application.ts +++ b/packages/pl-api/lib/entities/application.ts @@ -1,19 +1,19 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Application/} */ -const applicationSchema = z.object({ - name: z.string().catch(''), - website: z.string().optional().catch(undefined), - client_id: z.string().optional().catch(undefined), - client_secret: z.string().optional().catch(undefined), - redirect_uri: z.string().optional().catch(undefined), +const applicationSchema = v.object({ + name: v.fallback(v.string(), ''), + website: v.fallback(v.optional(v.string()), undefined), + client_id: v.fallback(v.optional(v.string()), undefined), + client_secret: v.fallback(v.optional(v.string()), undefined), + redirect_uri: v.fallback(v.optional(v.string()), undefined), - id: z.string().optional().catch(undefined), + id: v.fallback(v.optional(v.string()), undefined), /** @deprecated */ - vapid_key: z.string().optional().catch(undefined), + vapid_key: v.fallback(v.optional(v.string()), undefined), }); -type Application = z.infer; +type Application = v.InferOutput; export { applicationSchema, type Application }; diff --git a/packages/pl-api/lib/entities/backup.ts b/packages/pl-api/lib/entities/backup.ts index b7429db37..9c4acc3d8 100644 --- a/packages/pl-api/lib/entities/backup.ts +++ b/packages/pl-api/lib/entities/backup.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema, mimeSchema } from './utils'; /** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#post-apiv1pleromabackups} */ -const backupSchema = z.object({ +const backupSchema = v.object({ id: z.coerce.string(), contentType: mimeSchema, - file_size: z.number().catch(0), + file_size: v.fallback(v.number(), 0), inserted_at: dateSchema, - processed: z.boolean().catch(false), - url: z.string().catch(''), + processed: v.fallback(v.boolean(), false), + url: v.fallback(v.string(), ''), }); -type Backup = z.infer; +type Backup = v.InferOutput; export { backupSchema, type Backup }; diff --git a/packages/pl-api/lib/entities/bookmark-folder.ts b/packages/pl-api/lib/entities/bookmark-folder.ts index 2f4da29cd..edd634cf8 100644 --- a/packages/pl-api/lib/entities/bookmark-folder.ts +++ b/packages/pl-api/lib/entities/bookmark-folder.ts @@ -1,12 +1,12 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const bookmarkFolderSchema = z.object({ +const bookmarkFolderSchema = v.object({ id: z.coerce.string(), - name: z.string().catch(''), - emoji: z.string().nullable().catch(null), - emoji_url: z.string().nullable().catch(null), + name: v.fallback(v.string(), ''), + emoji: v.fallback(v.nullable(v.string()), null), + emoji_url: v.fallback(v.nullable(v.string()), null), }); -type BookmarkFolder = z.infer; +type BookmarkFolder = v.InferOutput; export { bookmarkFolderSchema, type BookmarkFolder }; diff --git a/packages/pl-api/lib/entities/chat-message.ts b/packages/pl-api/lib/entities/chat-message.ts index 09a265c67..387e3bc8e 100644 --- a/packages/pl-api/lib/entities/chat-message.ts +++ b/packages/pl-api/lib/entities/chat-message.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { customEmojiSchema } from './custom-emoji'; import { mediaAttachmentSchema } from './media-attachment'; @@ -6,18 +6,18 @@ import { previewCardSchema } from './preview-card'; import { dateSchema, filteredArray } from './utils'; /** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-the-messages-for-a-chat} */ -const chatMessageSchema = z.object({ - id: z.string(), - content: z.string().catch(''), - chat_id: z.string(), - account_id: z.string(), +const chatMessageSchema = v.object({ + id: v.string(), + content: v.fallback(v.string(), ''), + chat_id: v.string(), + account_id: v.string(), created_at: dateSchema, emojis: filteredArray(customEmojiSchema), - attachment: mediaAttachmentSchema.nullable().catch(null), - unread: z.boolean(), - card: previewCardSchema.nullable().catch(null), + attachment: v.fallback(v.nullable(mediaAttachmentSchema), null), + unread: v.boolean(), + card: v.fallback(v.nullable(previewCardSchema), null), }); -type ChatMessage = z.infer; +type ChatMessage = v.InferOutput; export { chatMessageSchema, type ChatMessage }; diff --git a/packages/pl-api/lib/entities/chat.ts b/packages/pl-api/lib/entities/chat.ts index 1d2c1492e..2d4762e14 100644 --- a/packages/pl-api/lib/entities/chat.ts +++ b/packages/pl-api/lib/entities/chat.ts @@ -1,18 +1,18 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { chatMessageSchema } from './chat-message'; import { dateSchema } from './utils'; /** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-a-list-of-chats} */ -const chatSchema = z.object({ - id: z.string(), +const chatSchema = v.object({ + id: v.string(), account: accountSchema, unread: z.number().int(), - last_message: chatMessageSchema.nullable().catch(null), + last_message: v.fallback(v.nullable(chatMessageSchema), null), created_at: dateSchema, }); -type Chat = z.infer; +type Chat = v.InferOutput; export { chatSchema, type Chat }; diff --git a/packages/pl-api/lib/entities/context.ts b/packages/pl-api/lib/entities/context.ts index 8e7cd2e42..75c32d786 100644 --- a/packages/pl-api/lib/entities/context.ts +++ b/packages/pl-api/lib/entities/context.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { statusSchema } from './status'; /** @see {@link https://docs.joinmastodon.org/entities/Context/} */ -const contextSchema = z.object({ +const contextSchema = v.object({ ancestors: z.array(statusSchema), descendants: z.array(statusSchema), }); -type Context = z.infer; +type Context = v.InferOutput; export { contextSchema, type Context }; diff --git a/packages/pl-api/lib/entities/conversation.ts b/packages/pl-api/lib/entities/conversation.ts index 719d0c398..8bdb375f1 100644 --- a/packages/pl-api/lib/entities/conversation.ts +++ b/packages/pl-api/lib/entities/conversation.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { filteredArray } from './utils'; import { accountSchema, statusSchema } from '.'; /** @see {@link https://docs.joinmastodon.org/entities/Conversation} */ -const conversationSchema = z.object({ - id: z.string(), - unread: z.boolean().catch(false), +const conversationSchema = v.object({ + id: v.string(), + unread: v.fallback(v.boolean(), false), accounts: filteredArray(accountSchema), - last_status: statusSchema.nullable().catch(null), + last_status: v.fallback(v.nullable(statusSchema), null), }); -type Conversation = z.infer; +type Conversation = v.InferOutput; export { conversationSchema, type Conversation }; diff --git a/packages/pl-api/lib/entities/custom-emoji.ts b/packages/pl-api/lib/entities/custom-emoji.ts index 1b9f2313c..5723990a7 100644 --- a/packages/pl-api/lib/entities/custom-emoji.ts +++ b/packages/pl-api/lib/entities/custom-emoji.ts @@ -1,17 +1,17 @@ -import z from 'zod'; +import * as v from 'valibot'; /** * Represents a custom emoji. * @see {@link https://docs.joinmastodon.org/entities/CustomEmoji/} */ -const customEmojiSchema = z.object({ - shortcode: z.string(), - url: z.string(), - static_url: z.string().catch(''), - visible_in_picker: z.boolean().catch(true), - category: z.string().nullable().catch(null), +const customEmojiSchema = v.object({ + shortcode: v.string(), + url: v.string(), + static_url: v.fallback(v.string(), ''), + visible_in_picker: v.fallback(v.boolean(), true), + category: v.fallback(v.nullable(v.string()), null), }); -type CustomEmoji = z.infer; +type CustomEmoji = v.InferOutput; export { customEmojiSchema, type CustomEmoji }; diff --git a/packages/pl-api/lib/entities/directory/category.ts b/packages/pl-api/lib/entities/directory/category.ts index d40bf48df..19b35cdde 100644 --- a/packages/pl-api/lib/entities/directory/category.ts +++ b/packages/pl-api/lib/entities/directory/category.ts @@ -1,10 +1,10 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const directoryCategorySchema = z.object({ - category: z.string(), +const directoryCategorySchema = v.object({ + category: v.string(), servers_count: z.coerce.number().nullable().catch(null), }); -type DirectoryCategory = z.infer; +type DirectoryCategory = v.InferOutput; export { directoryCategorySchema, type DirectoryCategory }; diff --git a/packages/pl-api/lib/entities/directory/language.ts b/packages/pl-api/lib/entities/directory/language.ts index 4ac2e1071..e97b397d8 100644 --- a/packages/pl-api/lib/entities/directory/language.ts +++ b/packages/pl-api/lib/entities/directory/language.ts @@ -1,11 +1,11 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const directoryLanguageSchema = z.object({ - locale: z.string(), - language: z.string(), +const directoryLanguageSchema = v.object({ + locale: v.string(), + language: v.string(), servers_count: z.coerce.number().nullable().catch(null), }); -type DirectoryLanguage = z.infer; +type DirectoryLanguage = v.InferOutput; export { directoryLanguageSchema, type DirectoryLanguage }; diff --git a/packages/pl-api/lib/entities/directory/server.ts b/packages/pl-api/lib/entities/directory/server.ts index 7ed72c320..231cbff3e 100644 --- a/packages/pl-api/lib/entities/directory/server.ts +++ b/packages/pl-api/lib/entities/directory/server.ts @@ -1,21 +1,21 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const directoryServerSchema = z.object({ - domain: z.string(), - version: z.string(), - description: z.string(), - languages: z.array(z.string()), - region: z.string(), - categories: z.array(z.string()), +const directoryServerSchema = v.object({ + domain: v.string(), + version: v.string(), + description: v.string(), + languages: z.array(v.string()), + region: v.string(), + categories: z.array(v.string()), proxied_thumbnail: z.string().url().nullable().catch(null), - blurhash: z.string().nullable().catch(null), + blurhash: v.fallback(v.nullable(v.string()), null), total_users: z.coerce.number(), last_week_users: z.coerce.number(), - approval_required: z.boolean(), - language: z.string(), - category: z.string(), + approval_required: v.boolean(), + language: v.string(), + category: v.string(), }); -type DirectoryServer = z.infer; +type DirectoryServer = v.InferOutput; export { directoryServerSchema, type DirectoryServer }; diff --git a/packages/pl-api/lib/entities/directory/statistics-period.ts b/packages/pl-api/lib/entities/directory/statistics-period.ts index 7df181346..ab3086cab 100644 --- a/packages/pl-api/lib/entities/directory/statistics-period.ts +++ b/packages/pl-api/lib/entities/directory/statistics-period.ts @@ -1,12 +1,12 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const directoryStatisticsPeriodSchema = z.object({ +const directoryStatisticsPeriodSchema = v.object({ period: z.string().date(), server_count: z.coerce.number().nullable().catch(null), user_count: z.coerce.number().nullable().catch(null), active_user_count: z.coerce.number().nullable().catch(null), }); -type DirectoryStatisticsPeriod = z.infer; +type DirectoryStatisticsPeriod = v.InferOutput; export { directoryStatisticsPeriodSchema, type DirectoryStatisticsPeriod }; diff --git a/packages/pl-api/lib/entities/domain-block.ts b/packages/pl-api/lib/entities/domain-block.ts index 87f3fea0f..97063a7ed 100644 --- a/packages/pl-api/lib/entities/domain-block.ts +++ b/packages/pl-api/lib/entities/domain-block.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/DomainBlock} */ -const domainBlockSchema = z.object({ - domain: z.string(), - digest: z.string(), +const domainBlockSchema = v.object({ + domain: v.string(), + digest: v.string(), severity: z.enum(['silence', 'suspend']), - comment: z.string().optional().catch(undefined), + comment: v.fallback(v.optional(v.string()), undefined), }); -type DomainBlock = z.infer; +type DomainBlock = v.InferOutput; export { domainBlockSchema, type DomainBlock }; diff --git a/packages/pl-api/lib/entities/emoji-reaction.ts b/packages/pl-api/lib/entities/emoji-reaction.ts index 45e335bf8..917cdb0d2 100644 --- a/packages/pl-api/lib/entities/emoji-reaction.ts +++ b/packages/pl-api/lib/entities/emoji-reaction.ts @@ -1,20 +1,20 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { emojiSchema, filteredArray } from './utils'; -const baseEmojiReactionSchema = z.object({ - count: z.number().nullable().catch(null), - me: z.boolean().catch(false), +const baseEmojiReactionSchema = v.object({ + count: v.fallback(v.nullable(v.number()), null), + me: v.fallback(v.boolean(), false), name: emojiSchema, url: z.literal(undefined).catch(undefined), static_url: z.literal(undefined).catch(undefined), accounts: filteredArray(accountSchema), - account_ids: filteredArray(z.string()).catch([]), + account_ids: filteredArray(v.string()).catch([]), }); const customEmojiReactionSchema = baseEmojiReactionSchema.extend({ - name: z.string(), + name: v.string(), url: z.string().url(), static_url: z.string().url(), }); @@ -29,6 +29,6 @@ const emojiReactionSchema = z.preprocess((reaction: any) => reaction ? { ...reaction, } : null, baseEmojiReactionSchema.or(customEmojiReactionSchema)); -type EmojiReaction = z.infer; +type EmojiReaction = v.InferOutput; export { emojiReactionSchema, type EmojiReaction }; diff --git a/packages/pl-api/lib/entities/extended-description.ts b/packages/pl-api/lib/entities/extended-description.ts index 2594917ab..be7fb5ab6 100644 --- a/packages/pl-api/lib/entities/extended-description.ts +++ b/packages/pl-api/lib/entities/extended-description.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/ExtendedDescription} */ -const extendedDescriptionSchema = z.object({ +const extendedDescriptionSchema = v.object({ updated_at: dateSchema, - content: z.string(), + content: v.string(), }); -type ExtendedDescription = z.infer; +type ExtendedDescription = v.InferOutput; export { extendedDescriptionSchema, type ExtendedDescription }; diff --git a/packages/pl-api/lib/entities/familiar-followers.ts b/packages/pl-api/lib/entities/familiar-followers.ts index f61b1a01c..ddf1e5c91 100644 --- a/packages/pl-api/lib/entities/familiar-followers.ts +++ b/packages/pl-api/lib/entities/familiar-followers.ts @@ -1,14 +1,14 @@ -import z from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { filteredArray } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/FamiliarFollowers/} */ -const familiarFollowersSchema = z.object({ - id: z.string(), +const familiarFollowersSchema = v.object({ + id: v.string(), accounts: filteredArray(accountSchema), }); -type FamiliarFollowers = z.infer +type FamiliarFollowers = v.InferOutput export { familiarFollowersSchema, type FamiliarFollowers }; diff --git a/packages/pl-api/lib/entities/featured-tag.ts b/packages/pl-api/lib/entities/featured-tag.ts index 6aa8d90cb..dfd7781c6 100644 --- a/packages/pl-api/lib/entities/featured-tag.ts +++ b/packages/pl-api/lib/entities/featured-tag.ts @@ -1,14 +1,14 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/FeaturedTag/} */ -const featuredTagSchema = z.object({ - id: z.string(), - name: z.string(), - url: z.string().optional().catch(undefined), +const featuredTagSchema = v.object({ + id: v.string(), + name: v.string(), + url: v.fallback(v.optional(v.string()), undefined), statuses_count: z.number(), last_status_at: z.number(), }); -type FeaturedTag = z.infer; +type FeaturedTag = v.InferOutput; export { featuredTagSchema, type FeaturedTag }; diff --git a/packages/pl-api/lib/entities/filter-result.ts b/packages/pl-api/lib/entities/filter-result.ts index b995e6c46..36b7c1b42 100644 --- a/packages/pl-api/lib/entities/filter-result.ts +++ b/packages/pl-api/lib/entities/filter-result.ts @@ -1,14 +1,14 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { filterSchema } from './filter'; /** @see {@link https://docs.joinmastodon.org/entities/FilterResult/} */ -const filterResultSchema = z.object({ +const filterResultSchema = v.object({ filter: filterSchema, - keyword_matches: z.array(z.string()).nullable().catch(null), - status_matches: z.array(z.string()).nullable().catch(null), + keyword_matches: z.array(v.string()).nullable().catch(null), + status_matches: z.array(v.string()).nullable().catch(null), }); -type FilterResult = z.infer; +type FilterResult = v.InferOutput; export { filterResultSchema, type FilterResult }; diff --git a/packages/pl-api/lib/entities/filter.ts b/packages/pl-api/lib/entities/filter.ts index 1553d10e7..7e27850a4 100644 --- a/packages/pl-api/lib/entities/filter.ts +++ b/packages/pl-api/lib/entities/filter.ts @@ -1,18 +1,18 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { filteredArray } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/FilterKeyword/} */ -const filterKeywordSchema = z.object({ - id: z.string(), - keyword: z.string(), - whole_word: z.boolean(), +const filterKeywordSchema = v.object({ + id: v.string(), + keyword: v.string(), + whole_word: v.boolean(), }); /** @see {@link https://docs.joinmastodon.org/entities/FilterStatus/} */ -const filterStatusSchema = z.object({ - id: z.string(), - status_id: z.string(), +const filterStatusSchema = v.object({ + id: v.string(), + status_id: v.string(), }); /** @see {@link https://docs.joinmastodon.org/entities/Filter/} */ @@ -30,9 +30,9 @@ const filterSchema = z.preprocess((filter: any) => { }; } return filter; -}, z.object({ - id: z.string(), - title: z.string(), +}, v.object({ + id: v.string(), + title: v.string(), context: z.array(z.enum(['home', 'notifications', 'public', 'thread', 'account'])), expires_at: z.string().datetime({ offset: true }).nullable().catch(null), filter_action: z.enum(['warn', 'hide']).catch('warn'), @@ -40,6 +40,6 @@ const filterSchema = z.preprocess((filter: any) => { statuses: filteredArray(filterStatusSchema), })); -type Filter = z.infer; +type Filter = v.InferOutput; export { filterKeywordSchema, filterStatusSchema, filterSchema, type Filter }; diff --git a/packages/pl-api/lib/entities/group-member.ts b/packages/pl-api/lib/entities/group-member.ts index 37a736ca6..4eb249ea4 100644 --- a/packages/pl-api/lib/entities/group-member.ts +++ b/packages/pl-api/lib/entities/group-member.ts @@ -1,4 +1,4 @@ -import z from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; @@ -10,12 +10,12 @@ enum GroupRoles { type GroupRole =`${GroupRoles}`; -const groupMemberSchema = z.object({ - id: z.string(), +const groupMemberSchema = v.object({ + id: v.string(), account: accountSchema, role: z.nativeEnum(GroupRoles), }); -type GroupMember = z.infer; +type GroupMember = v.InferOutput; export { groupMemberSchema, type GroupMember, GroupRoles, type GroupRole }; diff --git a/packages/pl-api/lib/entities/group-relationship.ts b/packages/pl-api/lib/entities/group-relationship.ts index 18ad06748..79489787d 100644 --- a/packages/pl-api/lib/entities/group-relationship.ts +++ b/packages/pl-api/lib/entities/group-relationship.ts @@ -1,14 +1,14 @@ -import z from 'zod'; +import * as v from 'valibot'; import { GroupRoles } from './group-member'; -const groupRelationshipSchema = z.object({ - id: z.string(), - member: z.boolean().catch(false), +const groupRelationshipSchema = v.object({ + id: v.string(), + member: v.fallback(v.boolean(), false), role: z.nativeEnum(GroupRoles).catch(GroupRoles.USER), - requested: z.boolean().catch(false), + requested: v.fallback(v.boolean(), false), }); -type GroupRelationship = z.infer; +type GroupRelationship = v.InferOutput; export { groupRelationshipSchema, type GroupRelationship }; diff --git a/packages/pl-api/lib/entities/group.ts b/packages/pl-api/lib/entities/group.ts index fdf286946..31e5e60bf 100644 --- a/packages/pl-api/lib/entities/group.ts +++ b/packages/pl-api/lib/entities/group.ts @@ -1,33 +1,33 @@ -import z from 'zod'; +import * as v from 'valibot'; import { customEmojiSchema } from './custom-emoji'; import { groupRelationshipSchema } from './group-relationship'; import { filteredArray } from './utils'; -const groupSchema = z.object({ - avatar: z.string().catch(''), - avatar_static: z.string().catch(''), +const groupSchema = v.object({ + avatar: v.fallback(v.string(), ''), + avatar_static: v.fallback(v.string(), ''), created_at: z.string().datetime().catch(new Date().toUTCString()), - display_name: z.string().catch(''), - domain: z.string().catch(''), + display_name: v.fallback(v.string(), ''), + domain: v.fallback(v.string(), ''), emojis: filteredArray(customEmojiSchema), - header: z.string().catch(''), - header_static: z.string().catch(''), + header: v.fallback(v.string(), ''), + header_static: v.fallback(v.string(), ''), id: z.coerce.string(), - locked: z.boolean().catch(false), - membership_required: z.boolean().catch(false), - members_count: z.number().catch(0), - owner: z.object({ id: z.string() }).nullable().catch(null), + locked: v.fallback(v.boolean(), false), + membership_required: v.fallback(v.boolean(), false), + members_count: v.fallback(v.number(), 0), + owner: v.object({ id: z.string() }).nullable().catch(null), note: z.string().transform(note => note === '

' ? '' : note).catch(''), - relationship: groupRelationshipSchema.nullable().catch(null), // Dummy field to be overwritten later + relationship: v.fallback(v.nullable(groupRelationshipSchema), null), // Dummy field to be overwritten later statuses_visibility: z.string().catch('public'), - uri: z.string().catch(''), - url: z.string().catch(''), + uri: v.fallback(v.string(), ''), + url: v.fallback(v.string(), ''), - avatar_description: z.string().catch(''), - header_description: z.string().catch(''), + avatar_description: v.fallback(v.string(), ''), + header_description: v.fallback(v.string(), ''), }); -type Group = z.infer; +type Group = v.InferOutput; export { groupSchema, type Group }; diff --git a/packages/pl-api/lib/entities/instance.ts b/packages/pl-api/lib/entities/instance.ts index 52bec49e5..b6950f262 100644 --- a/packages/pl-api/lib/entities/instance.ts +++ b/packages/pl-api/lib/entities/instance.ts @@ -1,5 +1,5 @@ /* eslint sort-keys: "error" */ -import z from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { ruleSchema } from './rule'; @@ -108,8 +108,8 @@ const fixVersion = (version: string) => { }; const configurationSchema = coerceObject({ - accounts: z.object({ - allow_custom_css: z.boolean(), + accounts: v.object({ + allow_custom_css: v.boolean(), max_featured_tags: z.number().int(), max_profile_fields: z.number().int(), }).nullable().catch(null), @@ -136,7 +136,7 @@ const configurationSchema = coerceObject({ min_expiration: z.number().catch(300), }), reactions: coerceObject({ - max_reactions: z.number().catch(0), + max_reactions: v.fallback(v.number(), 0), }), statuses: coerceObject({ characters_reserved_per_url: z.number().optional().catch(undefined), @@ -145,13 +145,13 @@ const configurationSchema = coerceObject({ }), translation: coerceObject({ - enabled: z.boolean().catch(false), + enabled: v.fallback(v.boolean(), false), }), urls: coerceObject({ streaming: z.string().url().optional().catch(undefined), }), vapid: coerceObject({ - public_key: z.string().catch(''), + public_key: v.fallback(v.string(), ''), }), }); @@ -162,25 +162,25 @@ const contactSchema = coerceObject({ const pleromaSchema = coerceObject({ metadata: coerceObject({ - account_activation_required: z.boolean().catch(false), - birthday_min_age: z.number().catch(0), - birthday_required: z.boolean().catch(false), + account_activation_required: v.fallback(v.boolean(), false), + birthday_min_age: v.fallback(v.number(), 0), + birthday_required: v.fallback(v.boolean(), false), description_limit: z.number().catch(1500), - features: z.string().array().catch([]), + features: v.fallback(v.array(v.string()), []), federation: coerceObject({ - enabled: z.boolean().catch(true), // Assume true unless explicitly false + enabled: v.fallback(v.boolean(), true), // Assume true unless explicitly false mrf_policies: z.string().array().optional().catch(undefined), mrf_simple: coerceObject({ - accept: z.string().array().catch([]), - avatar_removal: z.string().array().catch([]), - banner_removal: z.string().array().catch([]), - federated_timeline_removal: z.string().array().catch([]), - followers_only: z.string().array().catch([]), - media_nsfw: z.string().array().catch([]), - media_removal: z.string().array().catch([]), - reject: z.string().array().catch([]), - reject_deletes: z.string().array().catch([]), - report_removal: z.string().array().catch([]), + accept: v.fallback(v.array(v.string()), []), + avatar_removal: v.fallback(v.array(v.string()), []), + banner_removal: v.fallback(v.array(v.string()), []), + federated_timeline_removal: v.fallback(v.array(v.string()), []), + followers_only: v.fallback(v.array(v.string()), []), + media_nsfw: v.fallback(v.array(v.string()), []), + media_removal: v.fallback(v.array(v.string()), []), + reject: v.fallback(v.array(v.string()), []), + reject_deletes: v.fallback(v.array(v.string()), []), + report_removal: v.fallback(v.array(v.string()), []), }), }), fields_limits: coerceObject({ @@ -189,50 +189,50 @@ const pleromaSchema = coerceObject({ value_length: z.number().nonnegative().catch(2047), }), markup: coerceObject({ - allow_headings: z.boolean().catch(false), - allow_inline_images: z.boolean().catch(false), + allow_headings: v.fallback(v.boolean(), false), + allow_inline_images: v.fallback(v.boolean(), false), }), migration_cooldown_period: z.number().optional().catch(undefined), multitenancy: coerceObject({ domains: z .array( - z.object({ + v.object({ domain: z.coerce.string(), - id: z.string(), - public: z.boolean().catch(false), + id: v.string(), + public: v.fallback(v.boolean(), false), }), ) .optional(), - enabled: z.boolean().catch(false), + enabled: v.fallback(v.boolean(), false), }), post_formats: z.string().array().optional().catch(undefined), restrict_unauthenticated: coerceObject({ activities: coerceObject({ - local: z.boolean().catch(false), - remote: z.boolean().catch(false), + local: v.fallback(v.boolean(), false), + remote: v.fallback(v.boolean(), false), }), profiles: coerceObject({ - local: z.boolean().catch(false), - remote: z.boolean().catch(false), + local: v.fallback(v.boolean(), false), + remote: v.fallback(v.boolean(), false), }), timelines: coerceObject({ - bubble: z.boolean().catch(false), - federated: z.boolean().catch(false), - local: z.boolean().catch(false), + bubble: v.fallback(v.boolean(), false), + federated: v.fallback(v.boolean(), false), + local: v.fallback(v.boolean(), false), }), }), translation: coerceObject({ - allow_remote: z.boolean().catch(true), - allow_unauthenticated: z.boolean().catch(false), + allow_remote: v.fallback(v.boolean(), true), + allow_unauthenticated: v.fallback(v.boolean(), false), source_languages: z.string().array().optional().catch(undefined), target_languages: z.string().array().optional().catch(undefined), }), }), - oauth_consumer_strategies: z.string().array().catch([]), + oauth_consumer_strategies: v.fallback(v.array(v.string()), []), stats: coerceObject({ mau: z.number().optional().catch(undefined), }), - vapid_public_key: z.string().catch(''), + vapid_public_key: v.fallback(v.string(), ''), }); const pleromaPollLimitsSchema = coerceObject({ @@ -243,9 +243,9 @@ const pleromaPollLimitsSchema = coerceObject({ }); const registrations = coerceObject({ - approval_required: z.boolean().catch(false), - enabled: z.boolean().catch(false), - message: z.string().optional().catch(undefined), + approval_required: v.fallback(v.boolean(), false), + enabled: v.fallback(v.boolean(), false), + message: v.fallback(v.optional(v.string()), undefined), }); const statsSchema = coerceObject({ @@ -255,38 +255,38 @@ const statsSchema = coerceObject({ }); const thumbnailSchema = coerceObject({ - url: z.string().catch(''), + url: v.fallback(v.string(), ''), }); const usageSchema = coerceObject({ users: coerceObject({ - active_month: z.number().catch(0), + active_month: v.fallback(v.number(), 0), }), }); const instanceV1Schema = coerceObject({ - account_domain: z.string().catch(''), - approval_required: z.boolean().catch(false), + account_domain: v.fallback(v.string(), ''), + approval_required: v.fallback(v.boolean(), false), configuration: configurationSchema, contact_account: accountSchema.optional().catch(undefined), - description: z.string().catch(''), + description: v.fallback(v.string(), ''), description_limit: z.number().catch(1500), email: z.string().email().catch(''), - feature_quote: z.boolean().catch(false), - fedibird_capabilities: z.array(z.string()).catch([]), - languages: z.string().array().catch([]), + feature_quote: v.fallback(v.boolean(), false), + fedibird_capabilities: z.array(v.string()).catch([]), + languages: v.fallback(v.array(v.string()), []), max_media_attachments: z.number().optional().catch(undefined), max_toot_chars: z.number().optional().catch(undefined), pleroma: pleromaSchema, poll_limits: pleromaPollLimitsSchema, - registrations: z.boolean().catch(false), + registrations: v.fallback(v.boolean(), false), rules: filteredArray(ruleSchema), - short_description: z.string().catch(''), + short_description: v.fallback(v.string(), ''), stats: statsSchema, - thumbnail: z.string().catch(''), - title: z.string().catch(''), + thumbnail: v.fallback(v.string(), ''), + title: v.fallback(v.string(), ''), upload_limit: z.number().optional().catch(undefined), - uri: z.string().catch(''), + uri: v.fallback(v.string(), ''), urls: coerceObject({ streaming_api: z.string().url().optional().catch(undefined), }), @@ -307,21 +307,21 @@ const instanceSchema = z.preprocess((data: any) => { return instanceV1ToV2({ ...data, api_versions: apiVersions }); }, coerceObject({ - account_domain: z.string().catch(''), + account_domain: v.fallback(v.string(), ''), api_versions: z.record(z.number()).catch({}), configuration: configurationSchema, contact: contactSchema, - description: z.string().catch(''), - domain: z.string().catch(''), - feature_quote: z.boolean().catch(false), - fedibird_capabilities: z.array(z.string()).catch([]), - languages: z.string().array().catch([]), + description: v.fallback(v.string(), ''), + domain: v.fallback(v.string(), ''), + feature_quote: v.fallback(v.boolean(), false), + fedibird_capabilities: z.array(v.string()).catch([]), + languages: v.fallback(v.array(v.string()), []), pleroma: pleromaSchema, registrations: registrations, rules: filteredArray(ruleSchema), stats: statsSchema, thumbnail: thumbnailSchema, - title: z.string().catch(''), + title: v.fallback(v.string(), ''), usage: usageSchema, version: z.string().catch('0.0.0'), }).transform((instance) => { @@ -333,6 +333,6 @@ const instanceSchema = z.preprocess((data: any) => { }; })); -type Instance = z.infer; +type Instance = v.InferOutput; export { instanceSchema, type Instance }; diff --git a/packages/pl-api/lib/entities/interaction-policy.ts b/packages/pl-api/lib/entities/interaction-policy.ts index d53cfbaf6..975743c92 100644 --- a/packages/pl-api/lib/entities/interaction-policy.ts +++ b/packages/pl-api/lib/entities/interaction-policy.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { coerceObject } from './utils'; @@ -16,7 +16,7 @@ const interactionPolicySchema = coerceObject({ can_reply: interactionPolicyRuleSchema, }); -type InteractionPolicy = z.infer; +type InteractionPolicy = v.InferOutput; const interactionPoliciesSchema = coerceObject({ public: interactionPolicySchema, @@ -25,7 +25,7 @@ const interactionPoliciesSchema = coerceObject({ direct: interactionPolicySchema, }); -type InteractionPolicies = z.infer; +type InteractionPolicies = v.InferOutput; export { interactionPolicySchema, interactionPoliciesSchema, type InteractionPolicy, type InteractionPolicies }; diff --git a/packages/pl-api/lib/entities/interaction-request.ts b/packages/pl-api/lib/entities/interaction-request.ts index 0b679ac2b..92b70a1f1 100644 --- a/packages/pl-api/lib/entities/interaction-request.ts +++ b/packages/pl-api/lib/entities/interaction-request.ts @@ -1,21 +1,21 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { statusSchema } from './status'; /** @see {@link https://docs.gotosocial.org/en/latest/api/swagger.yaml#/definitions/interactionRequest} */ -const interactionRequestSchema = z.object({ +const interactionRequestSchema = v.object({ accepted_at: z.string().datetime().nullable().catch(null), account: accountSchema, created_at: z.string().datetime(), - id: z.string(), + id: v.string(), rejected_at: z.string().datetime().nullable().catch(null), - reply: statusSchema.nullable().catch(null), - status: statusSchema.nullable().catch(null), + reply: v.fallback(v.nullable(statusSchema), null), + status: v.fallback(v.nullable(statusSchema), null), type: z.enum(['favourite', 'reply', 'reblog']), - uri: z.string().nullable().catch(null), + uri: v.fallback(v.nullable(v.string()), null), }); -type InteractionRequest = z.infer; +type InteractionRequest = v.InferOutput; export { interactionRequestSchema, type InteractionRequest }; diff --git a/packages/pl-api/lib/entities/list.ts b/packages/pl-api/lib/entities/list.ts index c1d5d1b7c..2a0cac1c4 100644 --- a/packages/pl-api/lib/entities/list.ts +++ b/packages/pl-api/lib/entities/list.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/List/} */ -const listSchema = z.object({ +const listSchema = v.object({ id: z.coerce.string(), - title: z.string(), - replies_policy: z.string().optional().catch(undefined), - exclusive: z.boolean().optional().catch(undefined), + title: v.string(), + replies_policy: v.fallback(v.optional(v.string()), undefined), + exclusive: v.fallback(v.optional(v.boolean()), undefined), }); -type List = z.infer; +type List = v.InferOutput; export { listSchema, type List }; diff --git a/packages/pl-api/lib/entities/location.ts b/packages/pl-api/lib/entities/location.ts index 0e5edcb1d..b9391c444 100644 --- a/packages/pl-api/lib/entities/location.ts +++ b/packages/pl-api/lib/entities/location.ts @@ -1,23 +1,23 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const locationSchema = z.object({ +const locationSchema = v.object({ url: z.string().url().catch(''), - description: z.string().catch(''), - country: z.string().catch(''), - locality: z.string().catch(''), - region: z.string().catch(''), - postal_code: z.string().catch(''), - street: z.string().catch(''), - origin_id: z.string().catch(''), - origin_provider: z.string().catch(''), - type: z.string().catch(''), - timezone: z.string().catch(''), - geom: z.object({ + description: v.fallback(v.string(), ''), + country: v.fallback(v.string(), ''), + locality: v.fallback(v.string(), ''), + region: v.fallback(v.string(), ''), + postal_code: v.fallback(v.string(), ''), + street: v.fallback(v.string(), ''), + origin_id: v.fallback(v.string(), ''), + origin_provider: v.fallback(v.string(), ''), + type: v.fallback(v.string(), ''), + timezone: v.fallback(v.string(), ''), + geom: v.object({ coordinates: z.tuple([z.number(), z.number()]).nullable().catch(null), - srid: z.string().catch(''), + srid: v.fallback(v.string(), ''), }).nullable().catch(null), }); -type Location = z.infer; +type Location = v.InferOutput; export { locationSchema, type Location }; diff --git a/packages/pl-api/lib/entities/marker.ts b/packages/pl-api/lib/entities/marker.ts index b4b355c79..597d88b12 100644 --- a/packages/pl-api/lib/entities/marker.ts +++ b/packages/pl-api/lib/entities/marker.ts @@ -1,23 +1,23 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from './utils'; const markerSchema = z.preprocess((marker: any) => marker ? ({ unread_count: marker.pleroma?.unread_count, ...marker, -}) : null, z.object({ - last_read_id: z.string(), +}) : null, v.object({ + last_read_id: v.string(), version: z.number().int(), updated_at: dateSchema, unread_count: z.number().int().optional().catch(undefined), })); /** @see {@link https://docs.joinmastodon.org/entities/Marker/} */ -type Marker = z.infer; +type Marker = v.InferOutput; const markersSchema = z.record(markerSchema); -type Markers = z.infer; +type Markers = v.InferOutput; export { markerSchema, diff --git a/packages/pl-api/lib/entities/media-attachment.ts b/packages/pl-api/lib/entities/media-attachment.ts index 2017f129e..778e69eac 100644 --- a/packages/pl-api/lib/entities/media-attachment.ts +++ b/packages/pl-api/lib/entities/media-attachment.ts @@ -1,5 +1,5 @@ import { isBlurhashValid } from 'blurhash'; -import { z } from 'zod'; +import * as v from 'valibot'; import { mimeSchema } from './utils'; @@ -14,31 +14,31 @@ const blurhashSchema = z.string().superRefine((value, ctx) => { } }); -const baseAttachmentSchema = z.object({ - id: z.string(), - type: z.string(), +const baseAttachmentSchema = v.object({ + id: v.string(), + type: v.string(), url: z.string().url().catch(''), preview_url: z.string().url().catch(''), remote_url: z.string().url().nullable().catch(null), - description: z.string().catch(''), - blurhash: blurhashSchema.nullable().catch(null), + description: v.fallback(v.string(), ''), + blurhash: v.fallback(v.nullable(blurhashSchema), null), - mime_type: mimeSchema.nullable().catch(null), + mime_type: v.fallback(v.nullable(mimeSchema), null), }); -const imageMetaSchema = z.object({ +const imageMetaSchema = v.object({ width: z.number(), height: z.number(), size: z.string().regex(/\d+x\d+$/).nullable().catch(null), - aspect: z.number().nullable().catch(null), + aspect: v.fallback(v.nullable(v.number()), null), }); const imageAttachmentSchema = baseAttachmentSchema.extend({ type: z.literal('image'), - meta: z.object({ + meta: v.object({ original: imageMetaSchema.optional().catch(undefined), small: imageMetaSchema.optional().catch(undefined), - focus: z.object({ + focus: v.object({ x: z.number().min(-1).max(1), y: z.number().min(-1).max(1), }).optional().catch(undefined), @@ -47,7 +47,7 @@ const imageAttachmentSchema = baseAttachmentSchema.extend({ const videoAttachmentSchema = baseAttachmentSchema.extend({ type: z.literal('video'), - meta: z.object({ + meta: v.object({ duration: z.number().optional().catch(undefined), original: imageMetaSchema.extend({ frame_rate: z.string().regex(/\d+\/\d+$/).nullable().catch(null), @@ -60,7 +60,7 @@ const videoAttachmentSchema = baseAttachmentSchema.extend({ const gifvAttachmentSchema = baseAttachmentSchema.extend({ type: z.literal('gifv'), - meta: z.object({ + meta: v.object({ duration: z.number().optional().catch(undefined), original: imageMetaSchema.optional().catch(undefined), }).catch({}), @@ -68,15 +68,15 @@ const gifvAttachmentSchema = baseAttachmentSchema.extend({ const audioAttachmentSchema = baseAttachmentSchema.extend({ type: z.literal('audio'), - meta: z.object({ + meta: v.object({ duration: z.number().optional().catch(undefined), - colors: z.object({ - background: z.string().optional().catch(undefined), - foreground: z.string().optional().catch(undefined), - accent: z.string().optional().catch(undefined), + colors: v.object({ + background: v.fallback(v.optional(v.string()), undefined), + foreground: v.fallback(v.optional(v.string()), undefined), + accent: v.fallback(v.optional(v.string()), undefined), duration: z.number().optional().catch(undefined), }).optional().catch(undefined), - original: z.object({ + original: v.object({ duration: z.number().optional().catch(undefined), bitrate: z.number().nonnegative().optional().catch(undefined), }).optional().catch(undefined), @@ -104,6 +104,6 @@ const mediaAttachmentSchema = z.preprocess((data: any) => { unknownAttachmentSchema, ])); -type MediaAttachment = z.infer; +type MediaAttachment = v.InferOutput; export { blurhashSchema, mediaAttachmentSchema, type MediaAttachment }; diff --git a/packages/pl-api/lib/entities/mention.ts b/packages/pl-api/lib/entities/mention.ts index 81f1f7366..99a933d42 100644 --- a/packages/pl-api/lib/entities/mention.ts +++ b/packages/pl-api/lib/entities/mention.ts @@ -1,11 +1,11 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Status/#Mention} */ -const mentionSchema = z.object({ - id: z.string(), - username: z.string().catch(''), +const mentionSchema = v.object({ + id: v.string(), + username: v.fallback(v.string(), ''), url: z.string().url().catch(''), - acct: z.string(), + acct: v.string(), }).transform((mention) => { if (!mention.username) { mention.username = mention.acct.split('@')[0]; @@ -14,6 +14,6 @@ const mentionSchema = z.object({ return mention; }); -type Mention = z.infer; +type Mention = v.InferOutput; export { mentionSchema, type Mention }; diff --git a/packages/pl-api/lib/entities/notification-policy.ts b/packages/pl-api/lib/entities/notification-policy.ts index 769af206e..a4400cf81 100644 --- a/packages/pl-api/lib/entities/notification-policy.ts +++ b/packages/pl-api/lib/entities/notification-policy.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/NotificationPolicy} */ -const notificationPolicySchema = z.object({ - filter_not_following: z.boolean(), - filter_not_followers: z.boolean(), - filter_new_accounts: z.boolean(), - filter_private_mentions: z.boolean(), - summary: z.object({ +const notificationPolicySchema = v.object({ + filter_not_following: v.boolean(), + filter_not_followers: v.boolean(), + filter_new_accounts: v.boolean(), + filter_private_mentions: v.boolean(), + summary: v.object({ pending_requests_count: z.number().int(), pending_notifications_count: z.number().int(), }), }); -type NotificationPolicy = z.infer; +type NotificationPolicy = v.InferOutput; export { notificationPolicySchema, type NotificationPolicy }; diff --git a/packages/pl-api/lib/entities/notification-request.ts b/packages/pl-api/lib/entities/notification-request.ts index 33066f773..51ea8c841 100644 --- a/packages/pl-api/lib/entities/notification-request.ts +++ b/packages/pl-api/lib/entities/notification-request.ts @@ -1,12 +1,12 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from './utils'; import { accountSchema, statusSchema } from '.'; /** @see {@link https://docs.joinmastodon.org/entities/NotificationRequest} */ -const notificationRequestSchema = z.object({ - id: z.string(), +const notificationRequestSchema = v.object({ + id: v.string(), created_at: dateSchema, updated_at: dateSchema, account: accountSchema, @@ -14,6 +14,6 @@ const notificationRequestSchema = z.object({ last_status: statusSchema.optional().catch(undefined), }); -type NotificationRequest = z.infer; +type NotificationRequest = v.InferOutput; export { notificationRequestSchema, type NotificationRequest }; diff --git a/packages/pl-api/lib/entities/notification.ts b/packages/pl-api/lib/entities/notification.ts index 2942a118f..633ad6e8b 100644 --- a/packages/pl-api/lib/entities/notification.ts +++ b/packages/pl-api/lib/entities/notification.ts @@ -1,5 +1,5 @@ import pick from 'lodash.pick'; -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { accountWarningSchema } from './account-warning'; @@ -9,15 +9,15 @@ import { reportSchema } from './report'; import { statusSchema } from './status'; import { dateSchema } from './utils'; -const baseNotificationSchema = z.object({ +const baseNotificationSchema = v.object({ account: accountSchema, created_at: dateSchema, - id: z.string(), - group_key: z.string(), - type: z.string(), + id: v.string(), + group_key: v.string(), + type: v.string(), - is_muted: z.boolean().optional().catch(undefined), - is_seen: z.boolean().optional().catch(undefined), + is_muted: v.fallback(v.optional(v.boolean()), undefined), + is_seen: v.fallback(v.optional(v.boolean()), undefined), }); const accountNotificationSchema = baseNotificationSchema.extend({ @@ -57,8 +57,8 @@ const moveNotificationSchema = baseNotificationSchema.extend({ const emojiReactionNotificationSchema = baseNotificationSchema.extend({ type: z.literal('emoji_reaction'), - emoji: z.string(), - emoji_url: z.string().nullable().catch(null), + emoji: v.string(), + emoji_url: v.fallback(v.nullable(v.string()), null), status: statusSchema, }); @@ -70,7 +70,7 @@ const chatMentionNotificationSchema = baseNotificationSchema.extend({ const eventParticipationRequestNotificationSchema = baseNotificationSchema.extend({ type: z.enum(['participation_accepted', 'participation_request']), status: statusSchema, - participation_message: z.string().nullable().catch(null), + participation_message: v.fallback(v.nullable(v.string()), null), }); /** @see {@link https://docs.joinmastodon.org/entities/Notification/} */ @@ -94,7 +94,7 @@ const notificationSchema: z.ZodType = z.preprocess((notification: eventParticipationRequestNotificationSchema, ])) as any; -type Notification = z.infer< +type Notification = v.InferOutput< | typeof accountNotificationSchema | typeof mentionNotificationSchema | typeof statusNotificationSchema diff --git a/packages/pl-api/lib/entities/oauth-token.ts b/packages/pl-api/lib/entities/oauth-token.ts index 2c5afdd7e..cf9ea0931 100644 --- a/packages/pl-api/lib/entities/oauth-token.ts +++ b/packages/pl-api/lib/entities/oauth-token.ts @@ -1,15 +1,15 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apioauth_tokens} */ const oauthTokenSchema = z.preprocess((token: any) => ({ ...token, valid_until: token?.valid_until?.padEnd(27, 'Z'), -}), z.object({ - app_name: z.string(), +}), v.object({ + app_name: v.string(), id: z.number(), valid_until: z.string().datetime({ offset: true }), })); -type OauthToken = z.infer; +type OauthToken = v.InferOutput; export { oauthTokenSchema, type OauthToken }; diff --git a/packages/pl-api/lib/entities/poll.ts b/packages/pl-api/lib/entities/poll.ts index bfaf627be..923dc3a9a 100644 --- a/packages/pl-api/lib/entities/poll.ts +++ b/packages/pl-api/lib/entities/poll.ts @@ -1,32 +1,32 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { customEmojiSchema } from './custom-emoji'; import { filteredArray } from './utils'; -const pollOptionSchema = z.object({ - title: z.string().catch(''), - votes_count: z.number().catch(0), +const pollOptionSchema = v.object({ + title: v.fallback(v.string(), ''), + votes_count: v.fallback(v.number(), 0), - title_map: z.record(z.string()).nullable().catch(null), + title_map: z.record(v.string()).nullable().catch(null), }); /** @see {@link https://docs.joinmastodon.org/entities/Poll/} */ -const pollSchema = z.object({ +const pollSchema = v.object({ emojis: filteredArray(customEmojiSchema), - expired: z.boolean().catch(false), + expired: v.fallback(v.boolean(), false), expires_at: z.string().datetime().nullable().catch(null), - id: z.string(), - multiple: z.boolean().catch(false), + id: v.string(), + multiple: v.fallback(v.boolean(), false), options: z.array(pollOptionSchema).min(2), - voters_count: z.number().catch(0), - votes_count: z.number().catch(0), + voters_count: v.fallback(v.number(), 0), + votes_count: v.fallback(v.number(), 0), own_votes: z.array(z.number()).nonempty().nullable().catch(null), - voted: z.boolean().catch(false), + voted: v.fallback(v.boolean(), false), - non_anonymous: z.boolean().catch(false), + non_anonymous: v.fallback(v.boolean(), false), }); -type Poll = z.infer; +type Poll = v.InferOutput; type PollOption = Poll['options'][number]; export { pollSchema, type Poll, type PollOption }; diff --git a/packages/pl-api/lib/entities/preview-card.ts b/packages/pl-api/lib/entities/preview-card.ts index 1b03eba06..ad88f1f7f 100644 --- a/packages/pl-api/lib/entities/preview-card.ts +++ b/packages/pl-api/lib/entities/preview-card.ts @@ -1,24 +1,24 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/} */ -const previewCardSchema = z.object({ - author_name: z.string().catch(''), +const previewCardSchema = v.object({ + author_name: v.fallback(v.string(), ''), author_url: z.string().url().catch(''), - blurhash: z.string().nullable().catch(null), - description: z.string().catch(''), + blurhash: v.fallback(v.nullable(v.string()), null), + description: v.fallback(v.string(), ''), embed_url: z.string().url().catch(''), - height: z.number().catch(0), - html: z.string().catch(''), - image: z.string().nullable().catch(null), - image_description: z.string().catch(''), - provider_name: z.string().catch(''), + height: v.fallback(v.number(), 0), + html: v.fallback(v.string(), ''), + image: v.fallback(v.nullable(v.string()), null), + image_description: v.fallback(v.string(), ''), + provider_name: v.fallback(v.string(), ''), provider_url: z.string().url().catch(''), - title: z.string().catch(''), + title: v.fallback(v.string(), ''), type: z.enum(['link', 'photo', 'video', 'rich']).catch('link'), url: z.string().url(), - width: z.number().catch(0), + width: v.fallback(v.number(), 0), }); -type PreviewCard = z.infer; +type PreviewCard = v.InferOutput; export { previewCardSchema, type PreviewCard }; diff --git a/packages/pl-api/lib/entities/relationship-severance-event.ts b/packages/pl-api/lib/entities/relationship-severance-event.ts index 22b33c084..42970bf76 100644 --- a/packages/pl-api/lib/entities/relationship-severance-event.ts +++ b/packages/pl-api/lib/entities/relationship-severance-event.ts @@ -1,16 +1,16 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { dateSchema } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/RelationshipSeveranceEvent/} */ -const relationshipSeveranceEventSchema = z.object({ - id: z.string(), +const relationshipSeveranceEventSchema = v.object({ + id: v.string(), type: z.enum(['domain_block', 'user_domain_block', 'account_suspension']), - purged: z.string(), + purged: v.string(), relationships_count: z.number().optional().catch(undefined), created_at: dateSchema, }); -type RelationshipSeveranceEvent = z.infer; +type RelationshipSeveranceEvent = v.InferOutput; export { relationshipSeveranceEventSchema, type RelationshipSeveranceEvent }; diff --git a/packages/pl-api/lib/entities/relationship.ts b/packages/pl-api/lib/entities/relationship.ts index eae07bad4..e2fc728af 100644 --- a/packages/pl-api/lib/entities/relationship.ts +++ b/packages/pl-api/lib/entities/relationship.ts @@ -1,22 +1,22 @@ -import z from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Relationship/} */ -const relationshipSchema = z.object({ - blocked_by: z.boolean().catch(false), - blocking: z.boolean().catch(false), - domain_blocking: z.boolean().catch(false), - endorsed: z.boolean().catch(false), - followed_by: z.boolean().catch(false), - following: z.boolean().catch(false), - id: z.string(), - muting: z.boolean().catch(false), - muting_notifications: z.boolean().catch(false), - note: z.string().catch(''), - notifying: z.boolean().catch(false), - requested: z.boolean().catch(false), - showing_reblogs: z.boolean().catch(false), +const relationshipSchema = v.object({ + blocked_by: v.fallback(v.boolean(), false), + blocking: v.fallback(v.boolean(), false), + domain_blocking: v.fallback(v.boolean(), false), + endorsed: v.fallback(v.boolean(), false), + followed_by: v.fallback(v.boolean(), false), + following: v.fallback(v.boolean(), false), + id: v.string(), + muting: v.fallback(v.boolean(), false), + muting_notifications: v.fallback(v.boolean(), false), + note: v.fallback(v.string(), ''), + notifying: v.fallback(v.boolean(), false), + requested: v.fallback(v.boolean(), false), + showing_reblogs: v.fallback(v.boolean(), false), }); -type Relationship = z.infer; +type Relationship = v.InferOutput; export { relationshipSchema, type Relationship }; diff --git a/packages/pl-api/lib/entities/report.ts b/packages/pl-api/lib/entities/report.ts index f9573a14d..96b7c9d30 100644 --- a/packages/pl-api/lib/entities/report.ts +++ b/packages/pl-api/lib/entities/report.ts @@ -1,22 +1,22 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { dateSchema } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/Report/} */ -const reportSchema = z.object({ - id: z.string(), - action_taken: z.boolean().optional().catch(undefined), - action_taken_at: dateSchema.nullable().catch(null), - category: z.string().optional().catch(undefined), - comment: z.string().optional().catch(undefined), - forwarded: z.boolean().optional().catch(undefined), +const reportSchema = v.object({ + id: v.string(), + action_taken: v.fallback(v.optional(v.boolean()), undefined), + action_taken_at: v.fallback(v.nullable(dateSchema), null), + category: v.fallback(v.optional(v.string()), undefined), + comment: v.fallback(v.optional(v.string()), undefined), + forwarded: v.fallback(v.optional(v.boolean()), undefined), created_at: dateSchema.optional().catch(undefined), - status_ids: z.array(z.string()).nullable().catch(null), - rule_ids: z.array(z.string()).nullable().catch(null), - target_account: accountSchema.nullable().catch(null), + status_ids: z.array(v.string()).nullable().catch(null), + rule_ids: z.array(v.string()).nullable().catch(null), + target_account: v.fallback(v.nullable(accountSchema), null), }); -type Report = z.infer; +type Report = v.InferOutput; export { reportSchema, type Report }; diff --git a/packages/pl-api/lib/entities/role.ts b/packages/pl-api/lib/entities/role.ts index 7a80eade0..173c6ff89 100644 --- a/packages/pl-api/lib/entities/role.ts +++ b/packages/pl-api/lib/entities/role.ts @@ -1,16 +1,16 @@ -import { z } from 'zod'; +import * as v from 'valibot'; const hexSchema = z.string().regex(/^#[a-f0-9]{6}$/i); -const roleSchema = z.object({ - id: z.string().catch(''), - name: z.string().catch(''), +const roleSchema = v.object({ + id: v.fallback(v.string(), ''), + name: v.fallback(v.string(), ''), color: hexSchema.catch(''), - permissions: z.string().catch(''), - highlighted: z.boolean().catch(true), + permissions: v.fallback(v.string(), ''), + highlighted: v.fallback(v.boolean(), true), }); -type Role = z.infer; +type Role = v.InferOutput; export { roleSchema, diff --git a/packages/pl-api/lib/entities/rule.ts b/packages/pl-api/lib/entities/rule.ts index b7393f453..998a160a5 100644 --- a/packages/pl-api/lib/entities/rule.ts +++ b/packages/pl-api/lib/entities/rule.ts @@ -1,9 +1,9 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const baseRuleSchema = z.object({ - id: z.string(), - text: z.string().catch(''), - hint: z.string().catch(''), +const baseRuleSchema = v.object({ + id: v.string(), + text: v.fallback(v.string(), ''), + hint: v.fallback(v.string(), ''), }); /** @see {@link https://docs.joinmastodon.org/entities/Rule/} */ @@ -12,6 +12,6 @@ const ruleSchema = z.preprocess((data: any) => ({ hint: data.hint || data.subtext, }), baseRuleSchema); -type Rule = z.infer; +type Rule = v.InferOutput; export { ruleSchema, type Rule }; diff --git a/packages/pl-api/lib/entities/scheduled-status.ts b/packages/pl-api/lib/entities/scheduled-status.ts index 8f1094191..93ecbf9f7 100644 --- a/packages/pl-api/lib/entities/scheduled-status.ts +++ b/packages/pl-api/lib/entities/scheduled-status.ts @@ -1,36 +1,36 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { mediaAttachmentSchema } from './media-attachment'; import { filteredArray } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/ScheduledStatus/} */ -const scheduledStatusSchema = z.object({ - id: z.string(), +const scheduledStatusSchema = v.object({ + id: v.string(), scheduled_at: z.string().datetime({ offset: true }), - params: z.object({ - text: z.string().nullable().catch(null), - poll: z.object({ - options: z.array(z.string()), + params: v.object({ + text: v.fallback(v.nullable(v.string()), null), + poll: v.object({ + options: z.array(v.string()), expires_in: z.coerce.string(), - multiple: z.boolean().optional().catch(undefined), - hide_totals: z.boolean().optional().catch(undefined), + multiple: v.fallback(v.optional(v.boolean()), undefined), + hide_totals: v.fallback(v.optional(v.boolean()), undefined), }).nullable().catch(null), - media_ids: z.array(z.string()).nullable().catch(null), + media_ids: z.array(v.string()).nullable().catch(null), sensitive: z.coerce.boolean().nullable().catch(null), - spoiler_text: z.string().nullable().catch(null), + spoiler_text: v.fallback(v.nullable(v.string()), null), visibility: z.string().catch('public'), - in_reply_to_id: z.string().nullable().catch(null), - language: z.string().nullable().catch(null), + in_reply_to_id: v.fallback(v.nullable(v.string()), null), + language: v.fallback(v.nullable(v.string()), null), application_id: z.number().int().nullable().catch(null), scheduled_at: z.string().datetime({ offset: true }).nullable().catch(null), - idempotency: z.string().nullable().catch(null), - with_rate_limit: z.boolean().catch(false), + idempotency: v.fallback(v.nullable(v.string()), null), + with_rate_limit: v.fallback(v.boolean(), false), - expires_in: z.number().nullable().catch(null), + expires_in: v.fallback(v.nullable(v.number()), null), }), media_attachments: filteredArray(mediaAttachmentSchema), }); -type ScheduledStatus = z.infer; +type ScheduledStatus = v.InferOutput; export { scheduledStatusSchema, type ScheduledStatus }; diff --git a/packages/pl-api/lib/entities/scrobble.ts b/packages/pl-api/lib/entities/scrobble.ts index 92f926bfb..1dc838ee9 100644 --- a/packages/pl-api/lib/entities/scrobble.ts +++ b/packages/pl-api/lib/entities/scrobble.ts @@ -1,21 +1,21 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; const scrobbleSchema = z.preprocess((scrobble: any) => scrobble ? { external_link: scrobble.externalLink, ...scrobble, -} : null, z.object({ +} : null, v.object({ id: z.coerce.string(), account: accountSchema, created_at: z.string().datetime({ offset: true }), - title: z.string(), - artist: z.string().catch(''), - album: z.string().catch(''), - external_link: z.string().nullable().catch(null), - length: z.number().nullable().catch(null), + title: v.string(), + artist: v.fallback(v.string(), ''), + album: v.fallback(v.string(), ''), + external_link: v.fallback(v.nullable(v.string()), null), + length: v.fallback(v.nullable(v.number()), null), })); -type Scrobble = z.infer; +type Scrobble = v.InferOutput; export { scrobbleSchema, type Scrobble }; diff --git a/packages/pl-api/lib/entities/search.ts b/packages/pl-api/lib/entities/search.ts index bd32ced96..a8b0d4db6 100644 --- a/packages/pl-api/lib/entities/search.ts +++ b/packages/pl-api/lib/entities/search.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { filteredArray } from './utils'; import { accountSchema, groupSchema, statusSchema, tagSchema } from '.'; /** @see {@link https://docs.joinmastodon.org/entities/Search} */ -const searchSchema = z.object({ +const searchSchema = v.object({ accounts: filteredArray(accountSchema), statuses: filteredArray(statusSchema), hashtags: filteredArray(tagSchema), groups: filteredArray(groupSchema), }); -type Search = z.infer; +type Search = v.InferOutput; export { searchSchema, type Search }; diff --git a/packages/pl-api/lib/entities/status-edit.ts b/packages/pl-api/lib/entities/status-edit.ts index 5e56f42c1..0820e7911 100644 --- a/packages/pl-api/lib/entities/status-edit.ts +++ b/packages/pl-api/lib/entities/status-edit.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { customEmojiSchema } from './custom-emoji'; @@ -6,21 +6,21 @@ import { mediaAttachmentSchema } from './media-attachment'; import { dateSchema, filteredArray } from './utils'; /** @see {@link https://docs.joinmastodon.org/entities/StatusEdit/} */ -const statusEditSchema = z.object({ - content: z.string().catch(''), - spoiler_text: z.string().catch(''), +const statusEditSchema = v.object({ + content: v.fallback(v.string(), ''), + spoiler_text: v.fallback(v.string(), ''), sensitive: z.coerce.boolean(), created_at: dateSchema, account: accountSchema, - poll: z.object({ - options: z.array(z.object({ - title: z.string(), + poll: v.object({ + options: z.array(v.object({ + title: v.string(), })), }).nullable().catch(null), media_attachments: filteredArray(mediaAttachmentSchema), emojis: filteredArray(customEmojiSchema), }); -type StatusEdit = z.infer; +type StatusEdit = v.InferOutput; export { statusEditSchema, type StatusEdit }; diff --git a/packages/pl-api/lib/entities/status-source.ts b/packages/pl-api/lib/entities/status-source.ts index bab98572a..d811d3092 100644 --- a/packages/pl-api/lib/entities/status-source.ts +++ b/packages/pl-api/lib/entities/status-source.ts @@ -1,20 +1,20 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { locationSchema } from './location'; /** @see {@link https://docs.joinmastodon.org/entities/StatusSource/} */ -const statusSourceSchema = z.object({ - id: z.string(), - text: z.string().catch(''), - spoiler_text: z.string().catch(''), +const statusSourceSchema = v.object({ + id: v.string(), + text: v.fallback(v.string(), ''), + spoiler_text: v.fallback(v.string(), ''), content_type: z.string().catch('text/plain'), - location: locationSchema.nullable().catch(null), + location: v.fallback(v.nullable(locationSchema), null), - text_map: z.record(z.string()).nullable().catch(null), - spoiler_text_map: z.record(z.string()).nullable().catch(null), + text_map: z.record(v.string()).nullable().catch(null), + spoiler_text_map: z.record(v.string()).nullable().catch(null), }); -type StatusSource = z.infer; +type StatusSource = v.InferOutput; export { statusSourceSchema, type StatusSource }; diff --git a/packages/pl-api/lib/entities/status.ts b/packages/pl-api/lib/entities/status.ts index 4512e8062..4abbed09f 100644 --- a/packages/pl-api/lib/entities/status.ts +++ b/packages/pl-api/lib/entities/status.ts @@ -1,5 +1,5 @@ import pick from 'lodash.pick'; -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; import { customEmojiSchema } from './custom-emoji'; @@ -15,54 +15,54 @@ import { tagSchema } from './tag'; import { translationSchema } from './translation'; import { dateSchema, filteredArray } from './utils'; -const statusEventSchema = z.object({ - name: z.string().catch(''), +const statusEventSchema = v.object({ + name: v.fallback(v.string(), ''), start_time: z.string().datetime().nullable().catch(null), end_time: z.string().datetime().nullable().catch(null), join_mode: z.enum(['free', 'restricted', 'invite']).nullable().catch(null), - participants_count: z.number().catch(0), - location: z.object({ - name: z.string().catch(''), + participants_count: v.fallback(v.number(), 0), + location: v.object({ + name: v.fallback(v.string(), ''), url: z.string().url().catch(''), - latitude: z.number().catch(0), - longitude: z.number().catch(0), - street: z.string().catch(''), - postal_code: z.string().catch(''), - locality: z.string().catch(''), - region: z.string().catch(''), - country: z.string().catch(''), + latitude: v.fallback(v.number(), 0), + longitude: v.fallback(v.number(), 0), + street: v.fallback(v.string(), ''), + postal_code: v.fallback(v.string(), ''), + locality: v.fallback(v.string(), ''), + region: v.fallback(v.string(), ''), + country: v.fallback(v.string(), ''), }).nullable().catch(null), join_state: z.enum(['pending', 'reject', 'accept']).nullable().catch(null), }); /** @see {@link https://docs.joinmastodon.org/entities/Status/} */ -const baseStatusSchema = z.object({ - id: z.string(), +const baseStatusSchema = v.object({ + id: v.string(), uri: z.string().url().catch(''), created_at: dateSchema, account: accountSchema, - content: z.string().catch(''), + content: v.fallback(v.string(), ''), visibility: z.string().catch('public'), sensitive: z.coerce.boolean(), - spoiler_text: z.string().catch(''), + spoiler_text: v.fallback(v.string(), ''), media_attachments: filteredArray(mediaAttachmentSchema), - application: z.object({ - name: z.string(), + application: v.object({ + name: v.string(), website: z.string().url().nullable().catch(null), }).nullable().catch(null), mentions: filteredArray(mentionSchema), tags: filteredArray(tagSchema), emojis: filteredArray(customEmojiSchema), - reblogs_count: z.number().catch(0), - favourites_count: z.number().catch(0), - replies_count: z.number().catch(0), + reblogs_count: v.fallback(v.number(), 0), + favourites_count: v.fallback(v.number(), 0), + replies_count: v.fallback(v.number(), 0), url: z.string().url().catch(''), - in_reply_to_id: z.string().nullable().catch(null), - in_reply_to_account_id: z.string().nullable().catch(null), - poll: pollSchema.nullable().catch(null), - card: previewCardSchema.nullable().catch(null), - language: z.string().nullable().catch(null), - text: z.string().nullable().catch(null), + in_reply_to_id: v.fallback(v.nullable(v.string()), null), + in_reply_to_account_id: v.fallback(v.nullable(v.string()), null), + poll: v.fallback(v.nullable(pollSchema), null), + card: v.fallback(v.nullable(previewCardSchema), null), + language: v.fallback(v.nullable(v.string()), null), + text: v.fallback(v.nullable(v.string()), null), edited_at: z.string().datetime().nullable().catch(null), favourited: z.coerce.boolean(), reblogged: z.coerce.boolean(), @@ -71,32 +71,32 @@ const baseStatusSchema = z.object({ pinned: z.coerce.boolean(), filtered: filteredArray(filterResultSchema), approval_status: z.enum(['pending', 'approval', 'rejected']).nullable().catch(null), - group: groupSchema.nullable().catch(null), + group: v.fallback(v.nullable(groupSchema), null), scheduled_at: z.null().catch(null), - quote_id: z.string().nullable().catch(null), - local: z.boolean().optional().catch(undefined), - conversation_id: z.string().optional().catch(undefined), - direct_conversation_id: z.string().optional().catch(undefined), - in_reply_to_account_acct: z.string().optional().catch(undefined), + quote_id: v.fallback(v.nullable(v.string()), null), + local: v.fallback(v.optional(v.boolean()), undefined), + conversation_id: v.fallback(v.optional(v.string()), undefined), + direct_conversation_id: v.fallback(v.optional(v.string()), undefined), + in_reply_to_account_acct: v.fallback(v.optional(v.string()), undefined), expires_at: z.string().datetime({ offset: true }).optional().catch(undefined), - thread_muted: z.boolean().optional().catch(undefined), + thread_muted: v.fallback(v.optional(v.boolean()), undefined), emoji_reactions: filteredArray(emojiReactionSchema), - parent_visible: z.boolean().optional().catch(undefined), + parent_visible: v.fallback(v.optional(v.boolean()), undefined), pinned_at: z.string().datetime({ offset: true }).nullable().catch(null), - quote_visible: z.boolean().optional().catch(undefined), - quote_url: z.string().optional().catch(undefined), - quotes_count: z.number().catch(0), - bookmark_folder: z.string().nullable().catch(null), + quote_visible: v.fallback(v.optional(v.boolean()), undefined), + quote_url: v.fallback(v.optional(v.string()), undefined), + quotes_count: v.fallback(v.number(), 0), + bookmark_folder: v.fallback(v.nullable(v.string()), null), - event: statusEventSchema.nullable().catch(null), + event: v.fallback(v.nullable(statusEventSchema), null), translation: translationSchema.nullable().or(z.literal(false)).catch(null), - content_map: z.record(z.string()).nullable().catch(null), - text_map: z.record(z.string()).nullable().catch(null), - spoiler_text_map: z.record(z.string()).nullable().catch(null), + content_map: z.record(v.string()).nullable().catch(null), + text_map: z.record(v.string()).nullable().catch(null), + spoiler_text_map: z.record(v.string()).nullable().catch(null), - dislikes_count: z.number().catch(0), + dislikes_count: v.fallback(v.number(), 0), disliked: z.coerce.boolean().catch(false), interaction_policy: interactionPolicySchema, @@ -141,13 +141,13 @@ const statusSchema: z.ZodType = z.preprocess(preprocess, baseStatusSchem })) as any; const statusWithoutAccountSchema = z.preprocess(preprocess, baseStatusSchema.omit({ account: true }).extend({ - account: accountSchema.nullable().catch(null), + account: v.fallback(v.nullable(accountSchema), null), reblog: z.lazy(() => statusSchema).nullable().catch(null), quote: z.lazy(() => statusSchema).nullable().catch(null), })); -type Status = z.infer & { +type Status = v.InferOutput & { reblog: Status | null; quote: Status | null; } diff --git a/packages/pl-api/lib/entities/streaming-event.ts b/packages/pl-api/lib/entities/streaming-event.ts index 970290c46..758fe2e31 100644 --- a/packages/pl-api/lib/entities/streaming-event.ts +++ b/packages/pl-api/lib/entities/streaming-event.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { announcementSchema } from './announcement'; import { announcementReactionSchema } from './announcement-reaction'; @@ -8,24 +8,24 @@ import { markersSchema } from './marker'; import { notificationSchema } from './notification'; import { statusSchema } from './status'; -const followRelationshipUpdateSchema = z.object({ +const followRelationshipUpdateSchema = v.object({ state: z.enum(['follow_pending', 'follow_accept', 'follow_reject']), - follower: z.object({ - id: z.string(), - follower_count: z.number().nullable().catch(null), - following_count: z.number().nullable().catch(null), + follower: v.object({ + id: v.string(), + follower_count: v.fallback(v.nullable(v.number()), null), + following_count: v.fallback(v.nullable(v.number()), null), }), - following: z.object({ - id: z.string(), - follower_count: z.number().nullable().catch(null), - following_count: z.number().nullable().catch(null), + following: v.object({ + id: v.string(), + follower_count: v.fallback(v.nullable(v.number()), null), + following_count: v.fallback(v.nullable(v.number()), null), }), }); -type FollowRelationshipUpdate = z.infer; +type FollowRelationshipUpdate = v.InferOutput; -const baseStreamingEventSchema = z.object({ - stream: z.array(z.string()).catch([]), +const baseStreamingEventSchema = v.object({ + stream: z.array(v.string()).catch([]), }); const statusStreamingEventSchema = baseStreamingEventSchema.extend({ @@ -35,7 +35,7 @@ const statusStreamingEventSchema = baseStreamingEventSchema.extend({ const stringStreamingEventSchema = baseStreamingEventSchema.extend({ event: z.enum(['delete', 'announcement.delete']), - payload: z.string(), + payload: v.string(), }); const notificationStreamingEventSchema = baseStreamingEventSchema.extend({ @@ -74,8 +74,8 @@ const followRelationshipsUpdateStreamingEventSchema = baseStreamingEventSchema.e const respondStreamingEventSchema = baseStreamingEventSchema.extend({ event: z.literal('respond'), - payload: z.preprocess((payload: any) => JSON.parse(payload), z.object({ - type: z.string(), + payload: z.preprocess((payload: any) => JSON.parse(payload), v.object({ + type: v.string(), result: z.enum(['success', 'ignored', 'error']), })), }); @@ -103,7 +103,7 @@ const streamingEventSchema: z.ZodType = z.preprocess((event: any markerStreamingEventSchema, ])) as any; -type StreamingEvent = z.infer< +type StreamingEvent = v.InferOutput< | typeof statusStreamingEventSchema | typeof stringStreamingEventSchema | typeof notificationStreamingEventSchema diff --git a/packages/pl-api/lib/entities/suggestion.ts b/packages/pl-api/lib/entities/suggestion.ts index 9f568ea3e..1ea79fb53 100644 --- a/packages/pl-api/lib/entities/suggestion.ts +++ b/packages/pl-api/lib/entities/suggestion.ts @@ -1,4 +1,4 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { accountSchema } from './account'; @@ -29,12 +29,12 @@ const suggestionSchema = z.preprocess((suggestion: any) => { } return suggestion; -}, z.object({ - source: z.string().nullable().catch(null), - sources: z.array(z.string()).catch([]), +}, v.object({ + source: v.fallback(v.nullable(v.string()), null), + sources: z.array(v.string()).catch([]), account: accountSchema, })); -type Suggestion = z.infer; +type Suggestion = v.InferOutput; export { suggestionSchema, type Suggestion }; diff --git a/packages/pl-api/lib/entities/tag.ts b/packages/pl-api/lib/entities/tag.ts index 941b2cc66..fea9a679c 100644 --- a/packages/pl-api/lib/entities/tag.ts +++ b/packages/pl-api/lib/entities/tag.ts @@ -1,19 +1,19 @@ -import { z } from 'zod'; +import * as v from 'valibot'; -const historySchema = z.object({ +const historySchema = v.object({ day: z.coerce.number(), accounts: z.coerce.number(), uses: z.coerce.number(), }); /** @see {@link https://docs.joinmastodon.org/entities/tag} */ -const tagSchema = z.object({ +const tagSchema = v.object({ name: z.string().min(1), url: z.string().url().catch(''), history: z.array(historySchema).nullable().catch(null), - following: z.boolean().optional().catch(undefined), + following: v.fallback(v.optional(v.boolean()), undefined), }); -type Tag = z.infer; +type Tag = v.InferOutput; export { historySchema, tagSchema, type Tag }; diff --git a/packages/pl-api/lib/entities/token.ts b/packages/pl-api/lib/entities/token.ts index cd8e50b2c..59d7316dd 100644 --- a/packages/pl-api/lib/entities/token.ts +++ b/packages/pl-api/lib/entities/token.ts @@ -1,18 +1,18 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/Token/} */ -const tokenSchema = z.object({ - access_token: z.string(), - token_type: z.string(), - scope: z.string(), +const tokenSchema = v.object({ + access_token: v.string(), + token_type: v.string(), + scope: v.string(), created_at: z.number().optional().catch(undefined), id: z.number().optional().catch(undefined), - refresh_token: z.string().optional().catch(undefined), + refresh_token: v.fallback(v.optional(v.string()), undefined), expires_in: z.number().optional().catch(undefined), - me: z.string().optional().catch(undefined), + me: v.fallback(v.optional(v.string()), undefined), }); -type Token = z.infer; +type Token = v.InferOutput; export { tokenSchema, type Token }; diff --git a/packages/pl-api/lib/entities/translation.ts b/packages/pl-api/lib/entities/translation.ts index 0dcc502a0..b844818fb 100644 --- a/packages/pl-api/lib/entities/translation.ts +++ b/packages/pl-api/lib/entities/translation.ts @@ -1,17 +1,17 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { filteredArray } from './utils'; -const translationPollSchema = z.object({ - id: z.string(), - options: z.array(z.object({ - title: z.string(), +const translationPollSchema = v.object({ + id: v.string(), + options: z.array(v.object({ + title: v.string(), })), }); -const translationMediaAttachment = z.object({ - id: z.string(), - description: z.string().catch(''), +const translationMediaAttachment = v.object({ + id: v.string(), + description: v.fallback(v.string(), ''), }); /** @see {@link https://docs.joinmastodon.org/entities/Translation/} */ @@ -27,16 +27,16 @@ const translationSchema = z.preprocess((translation: any) => { }; return translation; -}, z.object({ - id: z.string().nullable().catch(null), - content: z.string().catch(''), - spoiler_text: z.string().catch(''), +}, v.object({ + id: v.fallback(v.nullable(v.string()), null), + content: v.fallback(v.string(), ''), + spoiler_text: v.fallback(v.string(), ''), poll: translationPollSchema.optional().catch(undefined), media_attachments: filteredArray(translationMediaAttachment), - detected_source_language: z.string(), - provider: z.string(), + detected_source_language: v.string(), + provider: v.string(), })); -type Translation = z.infer; +type Translation = v.InferOutput; export { translationSchema, type Translation }; diff --git a/packages/pl-api/lib/entities/trends-link.ts b/packages/pl-api/lib/entities/trends-link.ts index 6c37ad420..227e10cb1 100644 --- a/packages/pl-api/lib/entities/trends-link.ts +++ b/packages/pl-api/lib/entities/trends-link.ts @@ -1,29 +1,29 @@ -import { z } from 'zod'; +import * as v from 'valibot'; import { blurhashSchema } from './media-attachment'; import { historySchema } from './tag'; /** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/#trends-link} */ -const trendsLinkSchema = z.preprocess((link: any) => ({ ...link, id: link.url }), z.object({ - id: z.string().catch(''), +const trendsLinkSchema = z.preprocess((link: any) => ({ ...link, id: link.url }), v.object({ + id: v.fallback(v.string(), ''), url: z.string().url().catch(''), - title: z.string().catch(''), - description: z.string().catch(''), + title: v.fallback(v.string(), ''), + description: v.fallback(v.string(), ''), type: z.enum(['link', 'photo', 'video', 'rich']).catch('link'), - author_name: z.string().catch(''), - author_url: z.string().catch(''), - provider_name: z.string().catch(''), - provider_url: z.string().catch(''), - html: z.string().catch(''), - width: z.number().nullable().catch(null), - height: z.number().nullable().catch(null), - image: z.string().nullable().catch(null), - image_description: z.string().nullable().catch(null), - embed_url: z.string().catch(''), - blurhash: blurhashSchema.nullable().catch(null), + author_name: v.fallback(v.string(), ''), + author_url: v.fallback(v.string(), ''), + provider_name: v.fallback(v.string(), ''), + provider_url: v.fallback(v.string(), ''), + html: v.fallback(v.string(), ''), + width: v.fallback(v.nullable(v.number()), null), + height: v.fallback(v.nullable(v.number()), null), + image: v.fallback(v.nullable(v.string()), null), + image_description: v.fallback(v.nullable(v.string()), null), + embed_url: v.fallback(v.string(), ''), + blurhash: v.fallback(v.nullable(blurhashSchema), null), history: z.array(historySchema).nullable().catch(null), })); -type TrendsLink = z.infer; +type TrendsLink = v.InferOutput; export { trendsLinkSchema, type TrendsLink }; diff --git a/packages/pl-api/lib/entities/utils.ts b/packages/pl-api/lib/entities/utils.ts index d6a624b4f..5ebab3a53 100644 --- a/packages/pl-api/lib/entities/utils.ts +++ b/packages/pl-api/lib/entities/utils.ts @@ -1,4 +1,4 @@ -import z from 'zod'; +import * as v from 'valibot'; /** Validate to Mastodon's date format, or use the current date. */ const dateSchema = z.string().datetime({ offset: true }).catch(new Date().toUTCString()); @@ -10,7 +10,7 @@ const filteredArray = (schema: T) => arr.map((item) => { const parsed = schema.safeParse(item); return parsed.success ? parsed.data : undefined; - }).filter((item): item is z.infer => Boolean(item)) + }).filter((item): item is v.InferOutput => Boolean(item)) )); /** Validates the string as an emoji. */ @@ -21,6 +21,6 @@ const mimeSchema = z.string().regex(/^\w+\/[-+.\w]+$/); /** zod schema to force the value into an object, if it isn't already. */ const coerceObject = (shape: T) => - z.object({}).passthrough().catch({}).pipe(z.object(shape)); + v.object({}).passthrough().catch({}).pipe(z.object(shape)); export { filteredArray, emojiSchema, dateSchema, mimeSchema, coerceObject }; diff --git a/packages/pl-api/lib/entities/web-push-subscription.ts b/packages/pl-api/lib/entities/web-push-subscription.ts index 482622e5b..24ad82665 100644 --- a/packages/pl-api/lib/entities/web-push-subscription.ts +++ b/packages/pl-api/lib/entities/web-push-subscription.ts @@ -1,13 +1,13 @@ -import { z } from 'zod'; +import * as v from 'valibot'; /** @see {@link https://docs.joinmastodon.org/entities/WebPushSubscription/} */ -const webPushSubscriptionSchema = z.object({ +const webPushSubscriptionSchema = v.object({ id: z.coerce.string(), - endpoint: z.string(), + endpoint: v.string(), alerts: z.record(z.boolean()), - server_key: z.string(), + server_key: v.string(), }); -type WebPushSubscription = z.infer; +type WebPushSubscription = v.InferOutput; export { webPushSubscriptionSchema, type WebPushSubscription }; diff --git a/packages/pl-api/package.json b/packages/pl-api/package.json index f790227ed..b81524f07 100644 --- a/packages/pl-api/package.json +++ b/packages/pl-api/package.json @@ -42,6 +42,7 @@ "object-to-formdata": "^4.5.1", "query-string": "^9.1.0", "semver": "^7.6.3", + "valibot": "^0.42.1", "zod": "^3.23.8" }, "module": "./dist/main.es.js", diff --git a/packages/pl-api/yarn.lock b/packages/pl-api/yarn.lock index 3bbfde0ed..bd2dfc87d 100644 --- a/packages/pl-api/yarn.lock +++ b/packages/pl-api/yarn.lock @@ -2551,6 +2551,11 @@ uri-js@^4.2.2, uri-js@^4.4.1: dependencies: punycode "^2.1.0" +valibot@^0.42.1: + version "0.42.1" + resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.42.1.tgz#a31183d8e9d7552f98e22ca0977172cab8815188" + integrity sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw== + vite-plugin-dts@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/vite-plugin-dts/-/vite-plugin-dts-4.2.3.tgz#e0d9616eb574700111dbd19ae98e166541433263" diff --git a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/index.tsx b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/index.tsx index 69bdcb761..f2203510f 100644 --- a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/index.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/index.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import { z } from 'zod'; +import * as v from 'valibot'; import { useCreateGroup } from 'pl-fe/api/hooks'; import { Modal, Stack } from 'pl-fe/components/ui'; @@ -56,9 +56,9 @@ const CreateGroupModal: React.FC = ({ onClose }) => { setGroup(group); }, onError(error: { response?: PlfeResponse }) { - const msg = z.object({ error: z.string() }).safeParse(error?.response?.json); + const msg = v.safeParse(v.object({ error: v.string() }), error?.response?.json); if (msg.success) { - toast.error(msg.data.error); + toast.error(msg.output.error); } }, });