1
9
10import { z } from "zod";
11
12import { LIMITS } from "../constants.js";
13import { generatePosition } from "../positions.js";
14
15const idString = z.string().min(1);
16
17export const createPageSchema = z
18 .object({
19 title: z.string().max(LIMITS.MAX_PAGE_TITLE).default(""),
20 icon: z.string().max(32).optional().nullable(),
21 coverUrl: z.string().url().optional().nullable(),
22 description: z.string().max(2000).optional().nullable(),
23
24 teamId: idString.optional(),
25 parentId: idString.optional(),
26
27 position: z.string().min(1).optional(),
28 })
29 .strict()
30 .transform((v) => ({
31 title: v.title,
32 icon: v.icon ?? null,
33 coverUrl: v.coverUrl ?? null,
34 description: v.description ?? null,
35 teamId: v.teamId,
36 parentId: v.parentId,
37 position: v.position ?? generatePosition(),
38 }));
39export type CreatePage = z.infer<typeof createPageSchema>;
40
41export const updatePageSchema = z
42 .object({
43 title: z.string().max(LIMITS.MAX_PAGE_TITLE).optional(),
44 icon: z.string().max(32).optional().nullable(),
45 coverUrl: z.string().url().optional().nullable(),
46 description: z.string().max(2000).optional().nullable(),
47 isPrivate: z.boolean().optional(),
48 isFavorite: z.boolean().optional(),
49 archived: z.boolean().optional(),
50 trashed: z.boolean().optional(),
51 })
52 .strict()
53 .refine((v) => Object.keys(v).length > 0, { message: "No fields to update" });
54export type UpdatePage = z.infer<typeof updatePageSchema>;
55
56
61export const movePageSchema = z
62 .object({
63
64 parentId: idString.optional(),
65 before: idString.optional(),
66 after: idString.optional(),
67 })
68 .strict()
69 .refine((v) => !(v.before && v.after), {
70 message: "Specify at most one of before/after",
71 })
72 .refine((v) => v.parentId || v.before || v.after, {
73 message: "Nothing to move: provide parentId, before, or after",
74 });
75export type MovePage = z.infer<typeof movePageSchema>;
76