import { DrainOuterGeneric } from './type-utils.js'; /** * This type can be used to specify a different type for * select, insert and update operations. * * Also see the {@link Generated} type. * * ### Examples * * The next example defines a number column that is optional * in inserts and updates. All columns are always optional * in updates so therefore we don't need to specify `undefined` * for the update type. The type below is useful for all kinds of * database generated columns like identifiers. The `Generated` * type is actually just a shortcut for the type in this example: * * ```ts * ColumnType * ``` * * The above example makes the column optional in inserts * and updates, but you can still choose to provide the * column. If you want to prevent insertion/update you * can se the type as `never`: * * ```ts * ColumnType * ``` * * Here's one more example where the type is different * for each different operation: * * ```ts * ColumnType * ``` */ export type ColumnType = { readonly __select__: SelectType; readonly __insert__: InsertType; readonly __update__: UpdateType; }; /** * A shortcut for defining database-generated columns. The type * is the same for all selects, inserts and updates but the * column is optional for inserts and updates. * * The implementation: * * ```ts * // The update type is `S` instead of `S | undefined` because * // updates are always optional --> no need to specify optionality. * type Generated = ColumnType * ``` */ export type Generated = ColumnType; /** * A shortcut for defining columns that are only database-generated * (like postgres GENERATED ALWAYS AS IDENTITY). No insert/update * is allowed. */ export type GeneratedAlways = ColumnType; /** * A shortcut for defining JSON columns, which are by default inserted/updated * as stringified JSON strings. */ export type JSONColumnType = ColumnType; /** * Evaluates to `K` if `T` can be `null` or `undefined`. */ type IfNullable = undefined extends T ? K : null extends T ? K : never; /** * Evaluates to `K` if `T` can't be `null` or `undefined`. */ type IfNotNullable = undefined extends T ? never : null extends T ? never : T extends never ? never : K; /** * Evaluates to `K` if `T` isn't `never`. */ type IfNotNever = T extends never ? never : K; export type SelectType = T extends ColumnType ? S : T; export type InsertType = T extends ColumnType ? I : T; export type UpdateType = T extends ColumnType ? U : T; /** * Keys of `R` whose `InsertType` values can be `null` or `undefined`. */ export type NullableInsertKeys = { [K in keyof R]: IfNullable, K>; }[keyof R]; /** * Keys of `R` whose `InsertType` values can't be `null` or `undefined`. */ export type NonNullableInsertKeys = { [K in keyof R]: IfNotNullable, K>; }[keyof R]; /** * Keys of `R` whose `SelectType` values are not `never` */ type NonNeverSelectKeys = { [K in keyof R]: IfNotNever, K>; }[keyof R]; /** * Keys of `R` whose `UpdateType` values are not `never` */ export type UpdateKeys = { [K in keyof R]: IfNotNever, K>; }[keyof R]; /** * Given a table interface, extracts the select type from all * {@link ColumnType} types. * * ### Examples * * ```ts * interface PersonTable { * id: Generated * first_name: string * modified_at: ColumnType * } * * type Person = Selectable * // { * // id: number, * // first_name: string * // modified_at: Date * // } * ``` */ export type Selectable = DrainOuterGeneric<{ [K in NonNeverSelectKeys]: SelectType; }>; /** * Given a table interface, extracts the insert type from all * {@link ColumnType} types. * * ### Examples * * ```ts * interface PersonTable { * id: Generated * first_name: string * modified_at: ColumnType * } * * type InsertablePerson = Insertable * // { * // id?: number, * // first_name: string * // modified_at: string * // } * ``` */ export type Insertable = DrainOuterGeneric<{ [K in NonNullableInsertKeys]: InsertType; } & { [K in NullableInsertKeys]?: InsertType; }>; /** * Given a table interface, extracts the update type from all * {@link ColumnType} types. * * ### Examples * * ```ts * interface PersonTable { * id: Generated * first_name: string * modified_at: ColumnType * } * * type UpdateablePerson = Updateable * // { * // id?: number, * // first_name?: string * // } * ``` */ export type Updateable = DrainOuterGeneric<{ [K in UpdateKeys]?: UpdateType; }>; export {};