# `schemas/site.ts` ## Purpose Defines the Zod schemas that describe the canonical `site` entity, its create/update inputs, the public-facing slice, and the `:id` URL-parameter shape. These schemas live inside `@suaveplan/api-plugin-site` rather than `@suaveplan/api-schemas` because (a) the upstream `api-schemas/site` surface has not yet been migrated to suaveplan, and (b) the site plugin is the canonical owner of the site shape — every other consumer reads it through the plugin's exports. Inlining keeps the contract auditable in one package and prevents drift between the schema and the SurrealDB migration. ## Features - `SiteSchema` — full record shape with `id`, `organization_id`, `name`, `slug`, `domains`, `settings`, `state`, `created_at`, `updated_at`. - `SiteSettingsSchema` — embedded settings: `maintenance_mode`, `theme`, `features`, optional `push` (Apple + Firebase). - `SiteThemeSchema` — `primary_color` / `secondary_color` / `font_family` palette with default values matching the SurrealDB defaults. - `SiteStateNumberSchema` — the four legal numeric states (`1 / 2 / 4 / 8`). - `CreateSiteSchema` — strict input with min/max domain count. - `UpdateSiteSchema` — strict partial shape; rejects unknown keys. - `SitePublicInfoSchema` — sanitized slice returned by public routes (no secrets / push config). - `SiteIdParamSchema` — `{ id }` path parameter wrapper. - `RecordIdSchema` — non-empty string id placeholder matching SurrealDB's `record:rand` surface. ## Usage: Basic ```ts import { CreateSiteSchema } from "@suaveplan/api-plugin-site/schemas/site"; const parsed = CreateSiteSchema.parse({ organization_id: "organization:abc", name: "Acme Marketing", domains: ["acme.example.com"], }); ``` ## Usage: Advanced ```ts import { SiteSchema, UpdateSiteSchema } from "@suaveplan/api-plugin-site/schemas/site"; const update = UpdateSiteSchema.safeParse({ name: "Acme — Renamed", settings: { features: ["beta-cms"] }, }); if (!update.success) { throw new SiteError(SITE_CODES.VALIDATION, "invalid update", { cause: update.error, }); } const fresh = SiteSchema.parse(persistedRowFromSurreal); ``` ## API Reference - `RecordIdSchema: ZodString` — non-empty. - `SiteStateNumberSchema: ZodUnion<[ZodLiteral<1|2|4|8>]>`. - `SiteThemeSchema: ZodObject` — defaulted palette. - `SiteSettingsSchema: ZodObject` — settings + push. - `SiteSchema: ZodObject` — full record. - `CreateSiteSchema: ZodObject` — input for `SiteService.create`. - `UpdateSiteSchema: ZodObject (strict)` — input for `SiteService.update`. - `SitePublicInfoSchema: ZodObject` — public projection. - `SiteIdParamSchema: ZodObject` — `{ id }`. - Inferred types: `Site`, `CreateSite`, `UpdateSite`, `SitePublicInfo`, `SiteIdParam`. ## Implementation Notes - Zod default-import (`import z from "zod"`) per the repo's Bun-safe convention. - Domain count is capped at 5 in `CreateSiteSchema` to match `maxDomainsPerSite`'s default; runtime checks in `SiteService` re-validate against the configured (possibly larger) cap. - `RecordIdSchema` is intentionally narrow — full SurrealDB record-id parsing belongs in `@suaveplan/surrealdb`. - `UpdateSiteSchema` is `.strict()` so callers can't smuggle through unknown keys; this prevents accidental writes to fields not in the update surface. - Push config is optional — sites without push are valid.