UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

55 lines (48 loc) 1.84 kB
import type { TObject, TOptional, TSchema } from "alepha"; import { z } from "alepha"; import { PG_DEFAULT, PG_GENERATED, PG_ORGANIZATION, } from "../constants/PG_SYMBOLS.ts"; /** * Transforms a TObject schema for insert operations. * All default properties at the root level are made optional. * Generated columns are excluded entirely. * * @example * Before: { name: string; age: number(default=0); fullName: generated } * After: { name: string; age?: number; } */ export type TObjectInsert<T extends TObject> = TObject<{ [K in keyof T["shape"] as T["shape"][K] extends { [PG_GENERATED]: any } ? never : K]: T["shape"][K] extends | { [PG_DEFAULT]: any } | { [PG_ORGANIZATION]: any } ? TOptional<Extract<T["shape"][K], TSchema>> : T["shape"][K]; }>; export const insertSchema = <T extends TObject>(obj: T): TObjectInsert<T> => { const newProperties: Record<string, any> = {}; for (const key in obj.shape) { const prop = obj.shape[key]; // Skip generated columns — they are computed by the database if (PG_GENERATED in prop) { continue; } if (PG_DEFAULT in prop || PG_ORGANIZATION in prop) { // PG_DEFAULT fields have a server-side default; PG_ORGANIZATION fields are // auto-stamped by stampOrganization() inside create(). Both are optional // at the TypeScript call-site even when the DB column is NOT NULL. newProperties[key] = prop.optional(); } else if (z.schema.isOptional(prop)) { // An optional field maps to a NULLABLE column, so an explicit `null` is a // valid insert value (means "no value"), not just `undefined`. newProperties[key] = z.schema.unwrap(prop).nullable().optional(); } else { newProperties[key] = prop; } } return z.object(newProperties) as unknown as TObjectInsert<T>; };