// Shared wire-shape for a product + a row→wire mapper. // // Imported by every `*.route.tsx` AND by `openapiPlugin({ routes })` (both // server-side — REST route files are NOT pulled into the browser rpcGroup, // so they're free to import server modules). One source of truth means the // generated OpenAPI schema and the runtime encode can never disagree. import { Schema } from 'effect' export const Product = Schema.Struct({ id: Schema.String, name: Schema.String, priceCents: Schema.Number, // ISO-8601 string on the wire (we stringify the Date in the mapper below). createdAt: Schema.String, }) export type Product = Schema.Schema.Type /** * Coerce a raw store row into the wire shape. Two store-path quirks this * absorbs: a `timestamp` column can come back as a `Date` OR an ISO string, * and an `integer` column can come back as a STRING on some dialects — so we * normalise both before the strict output Schema encodes them. */ export const toProduct = (r: Record): Product => ({ id: r['id'] as string, name: r['name'] as string, priceCents: Number(r['priceCents']), createdAt: r['createdAt'] instanceof Date ? r['createdAt'].toISOString() : String(r['createdAt']), })