import { z } from "zod"; import { customDomainOrigin } from "../shared/domain-origin.ts"; import { installationId } from "./installation-metadata.ts"; export const domainErrors = z.enum([ "resource_conflict", "reauthorization_required", "temporarily_unavailable", "setup_required", "account_denied", "invalid_hostname", "https_pending", "attachment_outcome_unknown", ]); export const domainOrigin = z .string() .refine((value) => customDomainOrigin(value) === value); // Custom Domain IDs can be 40 hex characters, unlike account and zone IDs. export const domainIdentifier = z .string() .regex(/^(?:[a-f0-9]{32}|[a-f0-9]{40})$/); export const domainRecord = z .strictObject({ revision: z.number().int().positive(), deadline: z.number().int().positive(), origin: domainOrigin.nullable(), hostname: z .string() .refine((value) => customDomainOrigin(`https://${value}`) !== null), zoneId: installationId, domainId: domainIdentifier.nullable(), operationId: installationId, status: z.enum(["connecting", "active", "removing", "removed", "failed"]), action: z.enum(["attach", "remove"]), errorCode: domainErrors.nullable(), // At most one PUT may follow this commit. An uncertain outcome permits // observation only, never another PUT or an absence-based removal. writeIntent: z.boolean(), }) .refine( (value) => value.origin === (value.action === "attach" ? `https://${value.hostname}` : null), ); export interface DomainRecord extends z.infer {} export const domainStart = z.discriminatedUnion("action", [ z.strictObject({ action: z.literal("attach"), zoneId: installationId, origin: domainOrigin, }), z.strictObject({ action: z.literal("remove") }), z.strictObject({ action: z.literal("retry") }), ]); export type DomainStart = z.infer;