import { z } from "zod/v4"; export const appPermissionValues = [ "app.home.read", "files.read", "files.write", "index.write", "notifications.read_own", "notifications.write", "profile.read", "tasks.read", "tasks.write", ] as const; export const appPermissionSchema = z.enum(appPermissionValues); export type AppPermission = z.infer; export const appHomeRenderModeValues = ["cached", "live", "hybrid"] as const; export const appHomeRenderModeSchema = z.enum(appHomeRenderModeValues); export type AppHomeRenderMode = z.infer; export const appHostingSchema = z.object({ mode: z.literal("external"), baseUrl: z.url(), }); export type AppHostingConfig = z.infer; export const notificationDeliveryChannelValues = [ "in_app", "desktop", ] as const; export const notificationDeliveryChannelSchema = z.enum( notificationDeliveryChannelValues, ); export type NotificationDeliveryChannel = z.infer< typeof notificationDeliveryChannelSchema >; export const notificationPriorityValues = ["low", "default", "high"] as const; export const notificationPrioritySchema = z.enum(notificationPriorityValues); export type NotificationPriority = z.infer; export const notificationChannelDefinitionSchema = z.object({ key: z.string().trim().min(1).max(160), name: z.string().trim().min(1).max(120), description: z.string().trim().min(1).max(500).optional(), defaultDeliveries: z .array(notificationDeliveryChannelSchema) .min(1) .max(notificationDeliveryChannelValues.length) .refine( (values) => new Set(values).size === values.length, "Notification channel deliveries must be unique.", ), defaultPriority: notificationPrioritySchema.default("default"), }); export type NotificationChannelDefinitionInput = z.input< typeof notificationChannelDefinitionSchema >; export type NotificationChannelDefinition = z.infer< typeof notificationChannelDefinitionSchema >; export const notificationRecipientInputSchema = z.object({ userId: z.string().trim().min(1).max(200), }); export type NotificationRecipientInput = z.infer< typeof notificationRecipientInputSchema >; export const createNotificationInputSchema = z.object({ channelKey: z.string().trim().min(1).max(160), typeKey: z.string().trim().min(1).max(160), recipients: z.array(notificationRecipientInputSchema).min(1).max(100), title: z.string().trim().min(1).max(200), body: z.string().trim().min(1).max(4000).optional(), targetUrl: z.string().trim().min(1).max(2000).optional(), icon: z.string().trim().min(1).max(200).optional(), priority: notificationPrioritySchema.default("default"), dedupeKey: z.string().trim().min(1).max(200).optional(), metadata: z.record(z.string(), z.unknown()).default({}), }); export type CreateNotificationInput = z.infer; export const colineAppManifestSchema = z.object({ key: z.string().trim().min(3).max(120), name: z.string().trim().min(1).max(120), description: z.string().trim().min(1).max(500).optional(), iconUrl: z.url().optional(), permissions: z.array(appPermissionSchema).default([]), notificationChannels: z.array(notificationChannelDefinitionSchema).default([]), hosting: appHostingSchema, }); export type ColineAppManifest = z.infer; export const colineFileTypeSchema = z.object({ typeKey: z.string().trim().min(3).max(160), name: z.string().trim().min(1).max(120), description: z.string().trim().min(1).max(500).optional(), storage: z.enum(["coline_document"]), indexable: z.boolean().default(true), homeRenderMode: appHomeRenderModeSchema.default("cached"), }); export type ColineFileTypeDefinitionInput = z.input; export type ColineFileTypeDefinition = z.infer; export const colineAppRegistrationPayloadSchema = z.object({ version: z.string().trim().min(1).max(64), manifest: colineAppManifestSchema, fileTypes: z.array(colineFileTypeSchema).default([]), }); export type ColineAppRegistrationPayload = z.infer< typeof colineAppRegistrationPayloadSchema >;