Add groups schemas with zod

develop^2
Alex Gleason 2023-03-10 12:42:49 -06:00
rodzic 37f5b35aab
commit 6be8d4d46e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
4 zmienionych plików z 99 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,17 @@
import z from 'zod';
/**
* Represents a custom emoji.
* https://docs.joinmastodon.org/entities/CustomEmoji/
*/
const customEmojiSchema = z.object({
category: z.string().catch(''),
shortcode: z.string(),
static_url: z.string().catch(''),
url: z.string(),
visible_in_picker: z.boolean().catch(true),
});
type CustomEmoji = z.infer<typeof customEmojiSchema>;
export { customEmojiSchema, CustomEmoji };

Wyświetl plik

@ -0,0 +1,12 @@
import z from 'zod';
const groupRelationshipSchema = z.object({
id: z.string(),
member: z.boolean().catch(false),
requested: z.boolean().catch(false),
role: z.string().nullish().catch(null),
});
type GroupRelationship = z.infer<typeof groupRelationshipSchema>;
export { groupRelationshipSchema, GroupRelationship };

Wyświetl plik

@ -0,0 +1,49 @@
import escapeTextContentForBrowser from 'escape-html';
import z from 'zod';
import emojify from 'soapbox/features/emoji';
import { unescapeHTML } from 'soapbox/utils/html';
import { customEmojiSchema } from './custom-emoji';
import { groupRelationshipSchema } from './group-relationship';
import { filteredArray, makeCustomEmojiMap } from './utils';
const avatarMissing = require('assets/images/avatar-missing.png');
const headerMissing = require('assets/images/header-missing.png');
const groupSchema = z.object({
avatar: z.string().catch(avatarMissing),
avatar_static: z.string().catch(''),
created_at: z.string().datetime().catch(new Date().toUTCString()),
display_name: z.string().catch(''),
domain: z.string().catch(''),
emojis: filteredArray(customEmojiSchema),
group_visibility: z.string().catch(''), // TruthSocial
header: z.string().catch(headerMissing),
header_static: z.string().catch(''),
id: z.string().catch(''),
locked: z.boolean().catch(false),
membership_required: z.boolean().catch(false),
members_count: z.number().optional().catch(undefined),
note: z.string().catch('').refine(note => note === '<p></p>' ? '' : note),
relationship: groupRelationshipSchema.optional().catch(undefined), // Dummy field to be overwritten later
statuses_visibility: z.string().catch('public'),
uri: z.string().catch(''),
url: z.string().catch(''),
}).refine(group => {
group.avatar_static = group.avatar_static || group.avatar;
group.header_static = group.header_static || group.header;
group.locked = group.locked || group.group_visibility === 'members_only'; // TruthSocial
const customEmojiMap = makeCustomEmojiMap(group.emojis);
return {
...group,
display_name_html: emojify(escapeTextContentForBrowser(group.display_name), customEmojiMap),
note_emojified: emojify(group.note, customEmojiMap),
note_plain: unescapeHTML(group.note),
};
});
type Group = z.infer<typeof groupSchema>;
export { groupSchema, Group };

Wyświetl plik

@ -0,0 +1,21 @@
import z from 'zod';
import type { CustomEmoji } from './custom-emoji';
/** Validates individual items in an array, dropping any that aren't valid. */
function filteredArray<T extends z.ZodTypeAny>(schema: T) {
return z.any().array().transform((arr) => (
arr.map((item) => schema.safeParse(item).success ? item as z.infer<T> : undefined)
.filter((item): item is z.infer<T> => Boolean(item))
));
}
/** Map a list of CustomEmoji to their shortcodes. */
function makeCustomEmojiMap(customEmojis: CustomEmoji[]) {
return customEmojis.reduce<Record<string, CustomEmoji>>((result, emoji) => {
result[`:${emoji.shortcode}:`] = emoji;
return result;
}, {});
}
export { filteredArray, makeCustomEmojiMap };