import { z } from "zod"; /** * Organization ID schema, branded for type safety. * @public */ export const OrganizationId = z.string().nonempty().brand("OrganizationId"); /** * Organization ID type, branded for type safety. * @public */ export type OrganizationId = z.output; /** * Validates and brands a string as an OrganizationId. * @public */ export function brandOrganizationId(id: string): OrganizationId { return OrganizationId.parse(id); } const OrganizationMemberSchema = z.object({ sanityUserId: z.string(), isCurrentUser: z.boolean(), user: z.object({ id: z.string(), displayName: z.string(), familyName: z.string(), givenName: z.string(), middleName: z.string().nullable(), imageUrl: z.string().nullable(), email: z.string(), loginProvider: z.string(), }), roles: z.array( z.object({ name: z.string(), title: z.string(), description: z.string().optional(), }), ), }); /** * @public */ export type OrganizationMember = z.output; /** * Organization schema — validates and brands API responses * from the `/organizations/:id` endpoint. * @public */ export const Organization = z.object({ id: OrganizationId, name: z.string(), slug: z.string().nullable(), createdAt: z.string(), updatedAt: z.string(), dashboardStatus: z.enum(["enabled", "disabled"]), aiFeaturesStatus: z.enum(["enabled", "disabled"]), defaultRoleName: z.string().nullable(), }); /** * Represents an organization with optional members and * features arrays depending on the generic parameters. * - `Organization` — base fields only (default) * - `Organization` — includes `members` * - `Organization` — includes both * @public */ export type Organization< IncludeMembers extends boolean = true, IncludeFeatures extends boolean = true, > = z.output & (IncludeMembers extends true ? { members: OrganizationMember[] } : unknown) & (IncludeFeatures extends true ? { features: string[] } : unknown); /** * Validates and parses a raw API response into a branded * Organization. The options control which schema is used — * matching what the API returns based on query params. * @public */ export function parseOrganization< IncludeMembers extends boolean = true, IncludeFeatures extends boolean = true, >( data: unknown, options?: { includeMembers?: IncludeMembers; includeFeatures?: IncludeFeatures; }, ): Organization { const includeMembers = options?.includeMembers ?? true; const includeFeatures = options?.includeFeatures ?? true; const extensions = { ...(includeMembers && { members: z.array(OrganizationMemberSchema), }), ...(includeFeatures && { features: z.array(z.string()), }), }; const schema = Object.keys(extensions).length > 0 ? Organization.extend(extensions) : Organization; return schema.parse(data) as Organization; }