effect-qb 0.17.0 → 4.0.0-beta.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +7 -0
  2. package/dist/mysql.js +207 -134
  3. package/dist/postgres/metadata.js +121 -52
  4. package/dist/postgres.js +210 -138
  5. package/dist/sqlite.js +207 -134
  6. package/package.json +2 -4
  7. package/src/internal/column-state.d.ts +3 -3
  8. package/src/internal/column-state.ts +3 -3
  9. package/src/internal/column.ts +8 -8
  10. package/src/internal/dialect.ts +1 -1
  11. package/src/internal/executor.ts +54 -35
  12. package/src/internal/query.d.ts +1 -1
  13. package/src/internal/query.ts +1 -1
  14. package/src/internal/runtime/driver-value-mapping.ts +3 -3
  15. package/src/internal/runtime/schema.ts +28 -38
  16. package/src/internal/runtime/value.ts +20 -23
  17. package/src/internal/scalar.d.ts +1 -1
  18. package/src/internal/scalar.ts +1 -1
  19. package/src/internal/schema-derivation.d.ts +12 -61
  20. package/src/internal/schema-derivation.ts +95 -43
  21. package/src/internal/table.d.ts +29 -22
  22. package/src/internal/table.ts +178 -29
  23. package/src/mysql/column.ts +6 -6
  24. package/src/mysql/executor.ts +4 -4
  25. package/src/mysql/function/temporal.ts +1 -1
  26. package/src/mysql/internal/dsl.ts +23 -17
  27. package/src/mysql/table.ts +28 -25
  28. package/src/postgres/column.ts +11 -11
  29. package/src/postgres/executor.ts +4 -4
  30. package/src/postgres/function/temporal.ts +1 -1
  31. package/src/postgres/internal/dsl.ts +23 -17
  32. package/src/postgres/schema-management.ts +1 -2
  33. package/src/postgres/table.ts +13 -21
  34. package/src/sqlite/column.ts +6 -6
  35. package/src/sqlite/executor.ts +4 -4
  36. package/src/sqlite/function/temporal.ts +1 -1
  37. package/src/sqlite/internal/dsl.ts +7 -6
  38. package/src/sqlite/table.ts +17 -25
@@ -1,64 +1,7 @@
1
- import * as VariantSchema from "@effect/experimental/VariantSchema";
2
1
  import type * as Brand from "effect/Brand";
3
2
  import * as Schema from "effect/Schema";
4
3
  import { type AnyColumnDefinition, type HasDefault, type InsertType, type IsGenerated, type IsNullable, type SelectType, type UpdateType } from "./column-state.js";
5
- /** Variant-schema helper used to derive select / insert / update schemas. */
6
- export declare const TableSchema: {
7
- readonly Struct: <const A extends VariantSchema.Struct.Fields>(fields: A & VariantSchema.Struct.Validate<A, "insert" | "select" | "update">) => VariantSchema.Struct<A>;
8
- readonly Field: <const A extends VariantSchema.Field.ConfigWithKeys<"insert" | "select" | "update">>(config: A & { readonly [K in Exclude<keyof A, "insert" | "select" | "update">]: never; }) => VariantSchema.Field<A>;
9
- readonly FieldOnly: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Keys[number]]: S; }>;
10
- readonly FieldExcept: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Exclude<"insert", Keys[number]> | Exclude<"select", Keys[number]> | Exclude<"update", Keys[number]>]: S; }>;
11
- readonly fieldEvolve: {
12
- <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
13
- readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
14
- readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
15
- readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
16
- }>(f: Mapping): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping ? Mapping[K] extends (arg: any) => any ? ReturnType<Mapping[K]> : S_1[K] : S_1[K]; } : {
17
- readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping ? Mapping[T] extends (arg: any) => any ? ReturnType<Mapping[T]> : Self : Self : never : never;
18
- readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping ? Mapping[T_1] extends (arg: any) => any ? ReturnType<Mapping[T_1]> : Self : Self : never : never;
19
- readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping ? Mapping[T_2] extends (arg: any) => any ? ReturnType<Mapping[T_2]> : Self : Self : never : never;
20
- }>;
21
- <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_1 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
22
- readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
23
- readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
24
- readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
25
- }>(self: Self, f: Mapping_1): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_1 ? Mapping_1[K] extends (arg: any) => any ? ReturnType<Mapping_1[K]> : S_1[K] : S_1[K]; } : {
26
- readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_1 ? Mapping_1[T] extends (arg: any) => any ? ReturnType<Mapping_1[T]> : Self : Self : never : never;
27
- readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_1 ? Mapping_1[T_1] extends (arg: any) => any ? ReturnType<Mapping_1[T_1]> : Self : Self : never : never;
28
- readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_1 ? Mapping_1[T_2] extends (arg: any) => any ? ReturnType<Mapping_1[T_2]> : Self : Self : never : never;
29
- }>;
30
- };
31
- readonly fieldFromKey: {
32
- <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_2 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
33
- readonly insert?: string | undefined;
34
- readonly select?: string | undefined;
35
- readonly update?: string | undefined;
36
- }>(mapping: Mapping_2): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_2 ? Mapping_2[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_2[K]> : S_1[K] : S_1[K]; } : {
37
- readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_2 ? Mapping_2[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T]> : Self : Self : never : never;
38
- readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_2 ? Mapping_2[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_1]> : Self : Self : never : never;
39
- readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_2 ? Mapping_2[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_2]> : Self : Self : never : never;
40
- }>;
41
- <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_3 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
42
- readonly insert?: string | undefined;
43
- readonly select?: string | undefined;
44
- readonly update?: string | undefined;
45
- }>(self: Self, mapping: Mapping_3): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_3 ? Mapping_3[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_3[K]> : S_1[K] : S_1[K]; } : {
46
- readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_3 ? Mapping_3[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T]> : Self : Self : never : never;
47
- readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_3 ? Mapping_3[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_1]> : Self : Self : never : never;
48
- readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_3 ? Mapping_3[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_2]> : Self : Self : never : never;
49
- }>;
50
- };
51
- readonly Class: <Self = never>(identifier: string) => <const Fields extends VariantSchema.Struct.Fields>(fields: Fields & VariantSchema.Struct.Validate<Fields, "insert" | "select" | "update">, annotations?: Schema.Annotations.Schema<Self, readonly []> | undefined) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Class<Self>()({ ... })`" : VariantSchema.Class<Self, Fields, VariantSchema.ExtractFields<"select", Fields, true>, Schema.Struct.Type<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Struct.Encoded<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Schema.Context<VariantSchema.ExtractFields<"select", Fields, true>[keyof VariantSchema.ExtractFields<"select", Fields, true>]>, Schema.Struct.Constructor<VariantSchema.ExtractFields<"select", Fields, true>>> & {
52
- readonly insert: Schema.Struct<VariantSchema.ExtractFields<"insert", Fields, false> extends infer T ? { [K in keyof T]: T[K]; } : never>;
53
- readonly select: Schema.Struct<VariantSchema.ExtractFields<"select", Fields, false> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never>;
54
- readonly update: Schema.Struct<VariantSchema.ExtractFields<"update", Fields, false> extends infer T_2 ? { [K in keyof T_2]: T_2[K]; } : never>;
55
- };
56
- readonly Union: <const Members extends readonly VariantSchema.Struct<any>[]>(...members: Members) => VariantSchema.Union<Members> & VariantSchema.Union.Variants<Members, "insert" | "select" | "update">;
57
- readonly extract: {
58
- <V extends "insert" | "select" | "update">(variant: V): <A extends VariantSchema.Struct<any>>(self: A) => VariantSchema.Extract<V, A, V extends "select" ? true : false>;
59
- <V extends "insert" | "select" | "update", A extends VariantSchema.Struct<any>>(self: A, variant: V): VariantSchema.Extract<V, A, V extends "select" ? true : false>;
60
- };
61
- };
4
+ export type TableSchemaVariant = "select" | "insert" | "update";
62
5
  /** Normalized field map used by table definitions. */
63
6
  export type TableFieldMap = Record<string, AnyColumnDefinition>;
64
7
  type GeneratedKeys<Fields extends TableFieldMap> = {
@@ -91,15 +34,23 @@ export type InsertRow<TableName extends string, Fields extends TableFieldMap> =
91
34
  export type UpdateRow<TableName extends string, Fields extends TableFieldMap, PrimaryKey extends keyof Fields> = Simplify<Partial<{
92
35
  [K in UpdateKeys<Fields, PrimaryKey>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>;
93
36
  }>>;
37
+ type SchemaOfVariant<Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> = Variant extends "select" ? Schema.Decoder<SelectRow<TableName, Fields>, never> : Variant extends "insert" ? Schema.Decoder<InsertRow<TableName, Fields>, never> : Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
38
+ export declare const deriveSchema: <Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(variant: Variant, tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns>;
39
+ export declare const deriveSelectSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<SelectRow<TableName, Fields>, never>;
40
+ export declare const deriveInsertSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<InsertRow<TableName, Fields>, never>;
41
+ export declare const deriveUpdateSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
94
42
  /**
95
43
  * Derives the `select`, `insert`, and `update` schemas for a table.
96
44
  *
97
45
  * This is the central place where the column capability flags are turned into
98
46
  * real runtime schemas.
47
+ *
48
+ * @deprecated Prefer `deriveSelectSchema`, `deriveInsertSchema`, and
49
+ * `deriveUpdateSchema` so individual variants are derived lazily.
99
50
  */
100
51
  export declare const deriveSchemas: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => {
101
- readonly select: Schema.Schema<{ [K in keyof { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }]: { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }[K]; }, { [K in keyof { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }]: { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }[K]; }, never>;
102
- readonly insert: Schema.Schema<{ [K in Exclude<keyof Fields, GeneratedKeys<Fields> | OptionalInsertKeys<Fields>>]: BrandedInsertType<Fields[K], TableName, Extract<K, string>>; } & { [K in OptionalInsertKeys<Fields>]?: BrandedInsertType<Fields[K], TableName, Extract<K, string>> | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never, { [K in Exclude<keyof Fields, GeneratedKeys<Fields> | OptionalInsertKeys<Fields>>]: BrandedInsertType<Fields[K], TableName, Extract<K, string>>; } & { [K in OptionalInsertKeys<Fields>]?: BrandedInsertType<Fields[K], TableName, Extract<K, string>> | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never, never>;
103
- readonly update: Schema.Schema<Partial<{ [K in Exclude<keyof Fields, PrimaryKeyColumns | GeneratedKeys<Fields>>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>; }> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never, Partial<{ [K in Exclude<keyof Fields, PrimaryKeyColumns | GeneratedKeys<Fields>>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>; }> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never, never>;
52
+ readonly select: Schema.Decoder<SelectRow<TableName, Fields>, never>;
53
+ readonly insert: Schema.Decoder<InsertRow<TableName, Fields>, never>;
54
+ readonly update: Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
104
55
  };
105
56
  export {};
@@ -1,4 +1,3 @@
1
- import * as VariantSchema from "@effect/experimental/VariantSchema"
2
1
  import type * as Brand from "effect/Brand"
3
2
  import * as Schema from "effect/Schema"
4
3
 
@@ -12,13 +11,7 @@ import {
12
11
  type UpdateType
13
12
  } from "./column-state.js"
14
13
 
15
- /** Variant-schema helper used to derive select / insert / update schemas. */
16
- export const TableSchema = VariantSchema.make({
17
- variants: ["select", "insert", "update"] as const,
18
- defaultVariant: "select"
19
- })
20
-
21
- type Variants = "select" | "insert" | "update"
14
+ export type TableSchemaVariant = "select" | "insert" | "update"
22
15
 
23
16
  /** Normalized field map used by table definitions. */
24
17
  export type TableFieldMap = Record<string, AnyColumnDefinition>
@@ -112,7 +105,7 @@ const maybeBrandSchema = (
112
105
  column: AnyColumnDefinition,
113
106
  tableName: string,
114
107
  columnName: string
115
- ): Schema.Schema.Any =>
108
+ ): Schema.Top =>
116
109
  column.metadata.brand === true
117
110
  ? Schema.brand(`${tableName}.${columnName}`)(column.schema)
118
111
  : column.schema
@@ -121,7 +114,7 @@ const selectSchema = (
121
114
  column: AnyColumnDefinition,
122
115
  tableName: string,
123
116
  columnName: string
124
- ): Schema.Schema.Any =>
117
+ ): Schema.Top =>
125
118
  column.metadata.nullable ? Schema.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName)
126
119
 
127
120
  const insertSchema = (
@@ -153,11 +146,95 @@ const updateSchema = (
153
146
  return Schema.optional(base)
154
147
  }
155
148
 
149
+ type SchemaOfVariant<
150
+ Variant extends TableSchemaVariant,
151
+ TableName extends string,
152
+ Fields extends TableFieldMap,
153
+ PrimaryKeyColumns extends keyof Fields & string
154
+ > = Variant extends "select" ? Schema.Decoder<SelectRow<TableName, Fields>, never>
155
+ : Variant extends "insert" ? Schema.Decoder<InsertRow<TableName, Fields>, never>
156
+ : Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
157
+
158
+ const fieldSchemaForVariant = (
159
+ variant: TableSchemaVariant,
160
+ column: AnyColumnDefinition,
161
+ tableName: string,
162
+ columnName: string,
163
+ primaryKeySet: ReadonlySet<string>
164
+ ): any | undefined => {
165
+ switch (variant) {
166
+ case "select":
167
+ return selectSchema(column, tableName, columnName)
168
+ case "insert":
169
+ return insertSchema(column, tableName, columnName)
170
+ case "update":
171
+ return updateSchema(column, tableName, columnName, primaryKeySet.has(columnName))
172
+ }
173
+ }
174
+
175
+ export const deriveSchema = <
176
+ Variant extends TableSchemaVariant,
177
+ TableName extends string,
178
+ Fields extends TableFieldMap,
179
+ PrimaryKeyColumns extends keyof Fields & string
180
+ >(
181
+ variant: Variant,
182
+ tableName: TableName,
183
+ fields: Fields,
184
+ primaryKeyColumns: readonly PrimaryKeyColumns[]
185
+ ): SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns> => {
186
+ const primaryKeySet = new Set<string>(primaryKeyColumns)
187
+ const structFields: Record<string, any> = {}
188
+ for (const [key, column] of Object.entries(fields)) {
189
+ const schema = fieldSchemaForVariant(variant, column, tableName, key, primaryKeySet)
190
+ if (schema !== undefined) {
191
+ structFields[key] = schema
192
+ }
193
+ }
194
+ return Schema.Struct(structFields) as unknown as SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns>
195
+ }
196
+
197
+ export const deriveSelectSchema = <
198
+ TableName extends string,
199
+ Fields extends TableFieldMap,
200
+ PrimaryKeyColumns extends keyof Fields & string
201
+ >(
202
+ tableName: TableName,
203
+ fields: Fields,
204
+ primaryKeyColumns: readonly PrimaryKeyColumns[]
205
+ ): Schema.Decoder<SelectRow<TableName, Fields>, never> =>
206
+ deriveSchema("select", tableName, fields, primaryKeyColumns)
207
+
208
+ export const deriveInsertSchema = <
209
+ TableName extends string,
210
+ Fields extends TableFieldMap,
211
+ PrimaryKeyColumns extends keyof Fields & string
212
+ >(
213
+ tableName: TableName,
214
+ fields: Fields,
215
+ primaryKeyColumns: readonly PrimaryKeyColumns[]
216
+ ): Schema.Decoder<InsertRow<TableName, Fields>, never> =>
217
+ deriveSchema("insert", tableName, fields, primaryKeyColumns)
218
+
219
+ export const deriveUpdateSchema = <
220
+ TableName extends string,
221
+ Fields extends TableFieldMap,
222
+ PrimaryKeyColumns extends keyof Fields & string
223
+ >(
224
+ tableName: TableName,
225
+ fields: Fields,
226
+ primaryKeyColumns: readonly PrimaryKeyColumns[]
227
+ ): Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never> =>
228
+ deriveSchema("update", tableName, fields, primaryKeyColumns)
229
+
156
230
  /**
157
231
  * Derives the `select`, `insert`, and `update` schemas for a table.
158
232
  *
159
233
  * This is the central place where the column capability flags are turned into
160
234
  * real runtime schemas.
235
+ *
236
+ * @deprecated Prefer `deriveSelectSchema`, `deriveInsertSchema`, and
237
+ * `deriveUpdateSchema` so individual variants are derived lazily.
161
238
  */
162
239
  export const deriveSchemas = <
163
240
  TableName extends string,
@@ -168,36 +245,11 @@ export const deriveSchemas = <
168
245
  fields: Fields,
169
246
  primaryKeyColumns: readonly PrimaryKeyColumns[]
170
247
  ): {
171
- readonly select: Schema.Schema<SelectRow<TableName, Fields>>
172
- readonly insert: Schema.Schema<InsertRow<TableName, Fields>>
173
- readonly update: Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>
174
- } => {
175
- const primaryKeySet = new Set<string>(primaryKeyColumns)
176
- const variants: Record<string, VariantSchema.Field<any>> = {}
177
- for (const [key, column] of Object.entries(fields)) {
178
- const config: Record<Variants, any> = {
179
- select: selectSchema(column, tableName, key),
180
- insert: undefined,
181
- update: undefined
182
- }
183
- const insert = insertSchema(column, tableName, key)
184
- const update = updateSchema(column, tableName, key, primaryKeySet.has(key))
185
- if (insert !== undefined) {
186
- config.insert = insert
187
- } else {
188
- delete config.insert
189
- }
190
- if (update !== undefined) {
191
- config.update = update
192
- } else {
193
- delete config.update
194
- }
195
- variants[key] = TableSchema.Field(config)
196
- }
197
- const struct = TableSchema.Struct(variants as any)
198
- return {
199
- select: TableSchema.extract(struct, "select") as unknown as Schema.Schema<SelectRow<TableName, Fields>>,
200
- insert: TableSchema.extract(struct, "insert") as unknown as Schema.Schema<InsertRow<TableName, Fields>>,
201
- update: TableSchema.extract(struct, "update") as unknown as Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>
202
- }
203
- }
248
+ readonly select: Schema.Decoder<SelectRow<TableName, Fields>, never>
249
+ readonly insert: Schema.Decoder<InsertRow<TableName, Fields>, never>
250
+ readonly update: Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
251
+ } => ({
252
+ select: deriveSelectSchema(tableName, fields, primaryKeyColumns),
253
+ insert: deriveInsertSchema(tableName, fields, primaryKeyColumns),
254
+ update: deriveUpdateSchema(tableName, fields, primaryKeyColumns)
255
+ })
@@ -47,9 +47,9 @@ export type BoundColumns<Name extends string, Fields extends TableFieldMap> = {
47
47
  };
48
48
  /** Derived runtime schemas exposed by a table definition. */
49
49
  export interface TableSchemas<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> {
50
- readonly select: Schema.Schema<SelectRow<Name, Fields>>;
51
- readonly insert: Schema.Schema<InsertRow<Name, Fields>>;
52
- readonly update: Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>;
50
+ readonly select: Schema.Decoder<SelectRow<Name, Fields>, never>;
51
+ readonly insert: Schema.Decoder<InsertRow<Name, Fields>, never>;
52
+ readonly update: Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>;
53
53
  }
54
54
  interface TableState<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string, Kind extends TableKind = "schema", SchemaName extends string | undefined = DefaultSchemaName> {
55
55
  readonly name: Name;
@@ -92,7 +92,10 @@ export type TableClassStatic<Name extends string, Fields extends TableFieldMap,
92
92
  readonly tableName: Name;
93
93
  } & BoundColumns<Name, Fields> & Plan.RowSet<BoundColumns<Name, Fields>, never, Record<Name, Plan.Source<Name, "required", TrueFormula>>, TableDialect<Fields>>;
94
94
  /** Minimal structural table-like contract used across helper APIs. */
95
- export type AnyTable = TableDefinition<any, any, any, any, any> | TableClassStatic<any, any, any, any>;
95
+ export type AnyTable<Dialect extends string = string> = {
96
+ readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>;
97
+ readonly [OptionsSymbol]: readonly TableOptionSpec[];
98
+ } & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>;
96
99
  /** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
97
100
  export type TableOption<Spec extends TableOptionSpec = TableOptionSpec> = {
98
101
  <Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>;
@@ -114,6 +117,12 @@ export declare const schema: <SchemaName extends string>(schemaName: SchemaName)
114
117
  * downstream SQL rendering work.
115
118
  */
116
119
  export declare const alias: <Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string, SchemaName extends string, AliasName extends string>(table: TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName> | TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName>, aliasName: AliasName) => TableDefinition<AliasName, Fields, PrimaryKeyColumns, "alias", SchemaName>;
120
+ /** Returns the lazily derived select schema for a table. */
121
+ export declare function selectSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<SelectRow<Name, Fields>, never>;
122
+ /** Returns the lazily derived insert schema for a table. */
123
+ export declare function insertSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<InsertRow<Name, Fields>, never>;
124
+ /** Returns the lazily derived update schema for a table. */
125
+ export declare function updateSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>;
117
126
  /**
118
127
  * Class-based table constructor mirroring `Schema.Class`.
119
128
  *
@@ -153,21 +162,19 @@ export declare const check: <Name extends string>(name: Name, predicate: DdlExpr
153
162
  readonly name: Name;
154
163
  readonly predicate: DdlExpressionLike;
155
164
  }>;
156
- /** Extracts the row type of a table's select schema. */
157
- export type SelectOf<Table extends {
158
- readonly schemas: {
159
- readonly select: Schema.Schema<any>;
160
- };
161
- }> = Schema.Schema.Type<Table["schemas"]["select"]>;
162
- /** Extracts the payload type of a table's insert schema. */
163
- export type InsertOf<Table extends {
164
- readonly schemas: {
165
- readonly insert: Schema.Schema<any>;
166
- };
167
- }> = Schema.Schema.Type<Table["schemas"]["insert"]>;
168
- /** Extracts the payload type of a table's update schema. */
169
- export type UpdateOf<Table extends {
170
- readonly schemas: {
171
- readonly update: Schema.Schema<any>;
172
- };
173
- }> = Schema.Schema.Type<Table["schemas"]["update"]>;
165
+ /** Extracts the row type produced by `selectSchema(table)`. */
166
+ export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
167
+ readonly name: infer Name extends string;
168
+ readonly fields: infer Fields extends TableFieldMap;
169
+ } ? SelectRow<Name, Fields> : never;
170
+ /** Extracts the payload type produced by `insertSchema(table)`. */
171
+ export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
172
+ readonly name: infer Name extends string;
173
+ readonly fields: infer Fields extends TableFieldMap;
174
+ } ? InsertRow<Name, Fields> : never;
175
+ /** Extracts the payload type produced by `updateSchema(table)`. */
176
+ export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
177
+ readonly name: infer Name extends string;
178
+ readonly fields: infer Fields extends TableFieldMap;
179
+ readonly primaryKey: readonly (infer PrimaryKeyColumns)[];
180
+ } ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never;
@@ -24,10 +24,13 @@ import {
24
24
  validateOptions
25
25
  } from "./table-options.js"
26
26
  import {
27
- deriveSchemas,
27
+ deriveInsertSchema,
28
+ deriveSelectSchema,
29
+ deriveUpdateSchema,
28
30
  type InsertRow,
29
31
  type SelectRow,
30
32
  type TableFieldMap,
33
+ type TableSchemaVariant,
31
34
  type UpdateRow
32
35
  } from "./schema-derivation.js"
33
36
 
@@ -39,6 +42,7 @@ export const OptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/normaliz
39
42
  export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOptions")
40
43
 
41
44
  const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
45
+ const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
42
46
  const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
43
47
 
44
48
  type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
@@ -148,9 +152,17 @@ export interface TableSchemas<
148
152
  Fields extends TableFieldMap,
149
153
  PrimaryKeyColumns extends keyof Fields & string
150
154
  > {
151
- readonly select: Schema.Schema<SelectRow<Name, Fields>>
152
- readonly insert: Schema.Schema<InsertRow<Name, Fields>>
153
- readonly update: Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
155
+ readonly select: Schema.Decoder<SelectRow<Name, Fields>, never>
156
+ readonly insert: Schema.Decoder<InsertRow<Name, Fields>, never>
157
+ readonly update: Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
158
+ }
159
+
160
+ type TableSchemaCache<
161
+ Name extends string,
162
+ Fields extends TableFieldMap,
163
+ PrimaryKeyColumns extends keyof Fields & string
164
+ > = Partial<TableSchemas<Name, Fields, PrimaryKeyColumns>> & {
165
+ schemas?: TableSchemas<Name, Fields, PrimaryKeyColumns>
154
166
  }
155
167
 
156
168
  interface TableState<
@@ -245,13 +257,12 @@ export type TableClassStatic<
245
257
  >
246
258
 
247
259
  /** Minimal structural table-like contract used across helper APIs. */
248
- export type AnyTable = TableDefinition<any, any, any, any, any> | TableClassStatic<any, any, any, any>
260
+ export type AnyTable<Dialect extends string = string> = {
261
+ readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>
262
+ readonly [OptionsSymbol]: readonly TableOptionSpec[]
263
+ } & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>
249
264
 
250
- type FieldsOfAnyTable<Table extends AnyTable> = Table extends TableDefinition<any, infer Fields extends TableFieldMap, any, any, any>
251
- ? Fields
252
- : Table extends TableClassStatic<any, infer Fields extends TableFieldMap, any, any>
253
- ? Fields
254
- : never
265
+ type FieldsOfAnyTable<Table extends AnyTable> = Table[typeof TypeId]["fields"]
255
266
 
256
267
  type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
257
268
 
@@ -292,7 +303,6 @@ type BuildArtifacts<
292
303
  PrimaryKeyColumns extends keyof Fields & string
293
304
  > = {
294
305
  readonly columns: BoundColumns<Name, Fields>
295
- readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
296
306
  readonly normalizedOptions: readonly TableOptionSpec[]
297
307
  readonly primaryKey: readonly PrimaryKeyColumns[]
298
308
  }
@@ -314,15 +324,149 @@ const buildArtifacts = <
314
324
  const columns = Object.fromEntries(
315
325
  Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)])
316
326
  ) as BoundColumns<Name, Fields>
317
- const schemas = deriveSchemas(name, fields, primaryKey)
318
327
  return {
319
328
  columns,
320
- schemas,
321
329
  normalizedOptions,
322
330
  primaryKey
323
331
  }
324
332
  }
325
333
 
334
+ const getSchemaCache = <
335
+ Name extends string,
336
+ Fields extends TableFieldMap,
337
+ PrimaryKeyColumns extends keyof Fields & string
338
+ >(
339
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
340
+ ): TableSchemaCache<Name, Fields, PrimaryKeyColumns> => {
341
+ const target = table as unknown as {
342
+ [SchemaCacheSymbol]?: TableSchemaCache<Name, Fields, PrimaryKeyColumns>
343
+ }
344
+ if (target[SchemaCacheSymbol] !== undefined) {
345
+ return target[SchemaCacheSymbol]
346
+ }
347
+ const cache: TableSchemaCache<Name, Fields, PrimaryKeyColumns> = {}
348
+ Object.defineProperty(table, SchemaCacheSymbol, {
349
+ configurable: true,
350
+ value: cache
351
+ })
352
+ return cache
353
+ }
354
+
355
+ const deriveTableSchema = <
356
+ Variant extends TableSchemaVariant,
357
+ Name extends string,
358
+ Fields extends TableFieldMap,
359
+ PrimaryKeyColumns extends keyof Fields & string
360
+ >(
361
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
362
+ variant: Variant
363
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
364
+ const state = table[TypeId]
365
+ switch (variant) {
366
+ case "select":
367
+ return deriveSelectSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
368
+ case "insert":
369
+ return deriveInsertSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
370
+ case "update":
371
+ return deriveUpdateSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
372
+ }
373
+ }
374
+
375
+ const schemaFor = <
376
+ Variant extends TableSchemaVariant,
377
+ Name extends string,
378
+ Fields extends TableFieldMap,
379
+ PrimaryKeyColumns extends keyof Fields & string
380
+ >(
381
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
382
+ variant: Variant
383
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
384
+ const cache = getSchemaCache(table)
385
+ const cached = cache[variant]
386
+ if (cached !== undefined) {
387
+ return cached as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
388
+ }
389
+ const schema = deriveTableSchema(table, variant)
390
+ cache[variant] = schema as any
391
+ return schema
392
+ }
393
+
394
+ export function selectSchema<
395
+ Name extends string,
396
+ Fields extends TableFieldMap,
397
+ PrimaryKeyColumns extends keyof Fields & string
398
+ >(
399
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
400
+ ): Schema.Decoder<SelectRow<Name, Fields>, never> {
401
+ return schemaFor(table, "select") as Schema.Decoder<SelectRow<Name, Fields>, never>
402
+ }
403
+
404
+ export function insertSchema<
405
+ Name extends string,
406
+ Fields extends TableFieldMap,
407
+ PrimaryKeyColumns extends keyof Fields & string
408
+ >(
409
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
410
+ ): Schema.Decoder<InsertRow<Name, Fields>, never> {
411
+ return schemaFor(table, "insert") as Schema.Decoder<InsertRow<Name, Fields>, never>
412
+ }
413
+
414
+ export function updateSchema<
415
+ Name extends string,
416
+ Fields extends TableFieldMap,
417
+ PrimaryKeyColumns extends keyof Fields & string
418
+ >(
419
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
420
+ ): Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never> {
421
+ return schemaFor(table, "update") as Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
422
+ }
423
+
424
+ const schemasFor = <
425
+ Name extends string,
426
+ Fields extends TableFieldMap,
427
+ PrimaryKeyColumns extends keyof Fields & string
428
+ >(
429
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
430
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns> => {
431
+ const cache = getSchemaCache(table)
432
+ if (cache.schemas !== undefined) {
433
+ return cache.schemas
434
+ }
435
+ const schemas = {} as TableSchemas<Name, Fields, PrimaryKeyColumns>
436
+ Object.defineProperties(schemas, {
437
+ select: {
438
+ enumerable: true,
439
+ get: () => selectSchema(table)
440
+ },
441
+ insert: {
442
+ enumerable: true,
443
+ get: () => insertSchema(table)
444
+ },
445
+ update: {
446
+ enumerable: true,
447
+ get: () => updateSchema(table)
448
+ }
449
+ })
450
+ cache.schemas = schemas
451
+ return schemas
452
+ }
453
+
454
+ const defineSchemasGetter = <
455
+ Name extends string,
456
+ Fields extends TableFieldMap,
457
+ PrimaryKeyColumns extends keyof Fields & string
458
+ >(
459
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any>
460
+ ): void => {
461
+ Object.defineProperty(table, "schemas", {
462
+ configurable: true,
463
+ enumerable: true,
464
+ get() {
465
+ return schemasFor(table)
466
+ }
467
+ })
468
+ }
469
+
326
470
  const makeTable = <
327
471
  Name extends string,
328
472
  Fields extends TableFieldMap,
@@ -346,7 +490,7 @@ const makeTable = <
346
490
  const table = attachPipe(Object.create(TableProto))
347
491
  table.name = name
348
492
  table.columns = artifacts.columns
349
- table.schemas = artifacts.schemas
493
+ defineSchemasGetter(table)
350
494
  table[TypeId] = {
351
495
  name,
352
496
  baseName,
@@ -457,7 +601,6 @@ const ensureClassArtifacts = <
457
601
  )
458
602
  const artifacts = {
459
603
  columns: table.columns,
460
- schemas: table.schemas,
461
604
  normalizedOptions: table[OptionsSymbol],
462
605
  primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
463
606
  } satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
@@ -604,7 +747,7 @@ export const alias = <
604
747
  const aliased = attachPipe(Object.create(TableProto))
605
748
  aliased.name = aliasName
606
749
  aliased.columns = columns
607
- aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey)
750
+ defineSchemasGetter(aliased)
608
751
  aliased[TypeId] = {
609
752
  name: aliasName,
610
753
  baseName: state.baseName,
@@ -663,7 +806,7 @@ export function Class<
663
806
  }
664
807
 
665
808
  static get schemas() {
666
- return ensureClassArtifacts(this as any).schemas
809
+ return schemasFor(this as any)
667
810
  }
668
811
 
669
812
  static get [TypeId]() {
@@ -800,15 +943,21 @@ export const check = <Name extends string>(
800
943
  predicate
801
944
  })
802
945
 
803
- /** Extracts the row type of a table's select schema. */
804
- export type SelectOf<Table extends { readonly schemas: { readonly select: Schema.Schema<any> } }> = Schema.Schema.Type<
805
- Table["schemas"]["select"]
806
- >
807
- /** Extracts the payload type of a table's insert schema. */
808
- export type InsertOf<Table extends { readonly schemas: { readonly insert: Schema.Schema<any> } }> = Schema.Schema.Type<
809
- Table["schemas"]["insert"]
810
- >
811
- /** Extracts the payload type of a table's update schema. */
812
- export type UpdateOf<Table extends { readonly schemas: { readonly update: Schema.Schema<any> } }> = Schema.Schema.Type<
813
- Table["schemas"]["update"]
814
- >
946
+ /** Extracts the row type produced by `selectSchema(table)`. */
947
+ export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
948
+ readonly name: infer Name extends string
949
+ readonly fields: infer Fields extends TableFieldMap
950
+ } ? SelectRow<Name, Fields> : never
951
+
952
+ /** Extracts the payload type produced by `insertSchema(table)`. */
953
+ export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
954
+ readonly name: infer Name extends string
955
+ readonly fields: infer Fields extends TableFieldMap
956
+ } ? InsertRow<Name, Fields> : never
957
+
958
+ /** Extracts the payload type produced by `updateSchema(table)`. */
959
+ export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
960
+ readonly name: infer Name extends string
961
+ readonly fields: infer Fields extends TableFieldMap
962
+ readonly primaryKey: readonly (infer PrimaryKeyColumns)[]
963
+ } ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never