effect-qb 0.13.0 → 0.15.0

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 (146) hide show
  1. package/README.md +6 -1431
  2. package/dist/mysql.js +61945 -3611
  3. package/dist/postgres/metadata.js +2818 -0
  4. package/dist/postgres.js +9942 -5591
  5. package/package.json +21 -10
  6. package/src/internal/aggregation-validation.ts +3 -3
  7. package/src/internal/case-analysis.d.ts +18 -0
  8. package/src/internal/case-analysis.ts +4 -4
  9. package/src/internal/coercion/analysis.d.ts +7 -0
  10. package/src/internal/{coercion-analysis.ts → coercion/analysis.ts} +3 -3
  11. package/src/internal/coercion/errors.d.ts +17 -0
  12. package/src/internal/{coercion-errors.ts → coercion/errors.ts} +1 -1
  13. package/src/internal/coercion/kind.d.ts +4 -0
  14. package/src/internal/{coercion-kind.ts → coercion/kind.ts} +2 -2
  15. package/src/internal/{coercion-normalize.ts → coercion/normalize.ts} +1 -1
  16. package/src/internal/coercion/rules.d.ts +6 -0
  17. package/src/internal/{coercion-rules.ts → coercion/rules.ts} +2 -2
  18. package/src/internal/column-state.d.ts +190 -0
  19. package/src/internal/column-state.ts +119 -56
  20. package/src/internal/column.ts +387 -149
  21. package/src/internal/datatypes/define.d.ts +17 -0
  22. package/src/internal/datatypes/define.ts +18 -34
  23. package/src/internal/datatypes/lookup.d.ts +44 -0
  24. package/src/internal/datatypes/lookup.ts +61 -152
  25. package/src/internal/datatypes/shape.d.ts +16 -0
  26. package/src/internal/datatypes/shape.ts +1 -1
  27. package/src/internal/derived-table.d.ts +4 -0
  28. package/src/internal/derived-table.ts +21 -16
  29. package/src/internal/dsl-mutation-runtime.ts +378 -0
  30. package/src/internal/dsl-plan-runtime.ts +387 -0
  31. package/src/internal/dsl-query-runtime.ts +160 -0
  32. package/src/internal/dsl-transaction-ddl-runtime.ts +263 -0
  33. package/src/internal/executor.ts +173 -38
  34. package/src/internal/expression-ast.ts +19 -5
  35. package/src/internal/grouping-key.d.ts +3 -0
  36. package/src/internal/grouping-key.ts +1 -1
  37. package/src/internal/implication-runtime.d.ts +15 -0
  38. package/src/internal/implication-runtime.ts +171 -0
  39. package/src/internal/json/ast.d.ts +30 -0
  40. package/src/internal/json/ast.ts +1 -1
  41. package/src/internal/json/errors.d.ts +8 -0
  42. package/src/internal/json/path.d.ts +75 -0
  43. package/src/internal/json/path.ts +1 -1
  44. package/src/internal/json/types.d.ts +62 -0
  45. package/src/internal/predicate/analysis.d.ts +20 -0
  46. package/src/internal/{predicate-analysis.ts → predicate/analysis.ts} +13 -3
  47. package/src/internal/predicate/atom.d.ts +28 -0
  48. package/src/internal/{predicate-branches.ts → predicate/branches.ts} +2 -2
  49. package/src/internal/predicate/context.d.ts +67 -0
  50. package/src/internal/{predicate-context.ts → predicate/context.ts} +111 -32
  51. package/src/internal/predicate/formula.d.ts +35 -0
  52. package/src/internal/{predicate-formula.ts → predicate/formula.ts} +32 -20
  53. package/src/internal/predicate/key.d.ts +11 -0
  54. package/src/internal/{predicate-key.ts → predicate/key.ts} +2 -2
  55. package/src/internal/{predicate-nnf.ts → predicate/nnf.ts} +2 -2
  56. package/src/internal/predicate/normalize.d.ts +53 -0
  57. package/src/internal/predicate/normalize.ts +273 -0
  58. package/src/internal/predicate/runtime.d.ts +31 -0
  59. package/src/internal/predicate/runtime.ts +679 -0
  60. package/src/internal/projection-alias.d.ts +13 -0
  61. package/src/internal/projections.d.ts +31 -0
  62. package/src/internal/projections.ts +1 -1
  63. package/src/internal/query-ast.d.ts +217 -0
  64. package/src/internal/query-ast.ts +1 -1
  65. package/src/internal/query-requirements.d.ts +20 -0
  66. package/src/internal/query.d.ts +775 -0
  67. package/src/internal/query.ts +767 -275
  68. package/src/internal/renderer.ts +7 -21
  69. package/src/internal/row-set.d.ts +53 -0
  70. package/src/internal/{plan.ts → row-set.ts} +23 -11
  71. package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
  72. package/src/internal/{runtime-schema.ts → runtime/schema.ts} +84 -55
  73. package/src/internal/runtime/value.d.ts +22 -0
  74. package/src/internal/{runtime-value.ts → runtime/value.ts} +2 -2
  75. package/src/internal/scalar.d.ts +107 -0
  76. package/src/internal/scalar.ts +191 -0
  77. package/src/internal/schema-derivation.d.ts +105 -0
  78. package/src/internal/schema-derivation.ts +93 -21
  79. package/src/internal/schema-expression.d.ts +18 -0
  80. package/src/internal/schema-expression.ts +75 -0
  81. package/src/internal/table-options.d.ts +94 -0
  82. package/src/internal/table-options.ts +94 -8
  83. package/src/internal/table.d.ts +173 -0
  84. package/src/internal/table.ts +135 -54
  85. package/src/mysql/column.ts +95 -18
  86. package/src/mysql/datatypes/index.ts +58 -3
  87. package/src/mysql/errors/generated.ts +57336 -0
  88. package/src/mysql/errors/index.ts +1 -0
  89. package/src/mysql/errors/normalize.ts +55 -53
  90. package/src/mysql/errors/types.ts +74 -0
  91. package/src/mysql/executor.ts +69 -7
  92. package/src/mysql/function/aggregate.ts +1 -5
  93. package/src/mysql/function/core.ts +1 -3
  94. package/src/mysql/function/index.ts +1 -1
  95. package/src/mysql/function/string.ts +1 -5
  96. package/src/mysql/function/temporal.ts +12 -15
  97. package/src/mysql/function/window.ts +1 -6
  98. package/src/{internal/mysql-dialect.ts → mysql/internal/dialect.ts} +1 -1
  99. package/src/mysql/internal/dsl.ts +6115 -0
  100. package/src/{internal/mysql-renderer.ts → mysql/internal/renderer.ts} +6 -6
  101. package/src/mysql/internal/sql-expression-renderer.ts +1455 -0
  102. package/src/mysql/json.ts +2 -0
  103. package/src/mysql/query.ts +111 -86
  104. package/src/mysql/renderer.ts +1 -1
  105. package/src/mysql/table.ts +1 -1
  106. package/src/mysql.ts +6 -4
  107. package/src/postgres/cast.ts +30 -0
  108. package/src/postgres/column.ts +178 -20
  109. package/src/postgres/datatypes/index.d.ts +515 -0
  110. package/src/postgres/datatypes/index.ts +49 -5
  111. package/src/postgres/datatypes/spec.d.ts +412 -0
  112. package/src/postgres/errors/generated.ts +2636 -0
  113. package/src/postgres/errors/index.ts +1 -0
  114. package/src/postgres/errors/normalize.ts +47 -62
  115. package/src/postgres/errors/types.ts +92 -34
  116. package/src/postgres/executor.ts +37 -5
  117. package/src/postgres/function/aggregate.ts +1 -5
  118. package/src/postgres/function/core.ts +20 -2
  119. package/src/postgres/function/index.ts +1 -1
  120. package/src/postgres/function/string.ts +1 -5
  121. package/src/postgres/function/temporal.ts +12 -15
  122. package/src/postgres/function/window.ts +1 -6
  123. package/src/{internal/postgres-dialect.ts → postgres/internal/dialect.ts} +1 -1
  124. package/src/{internal/query-factory.ts → postgres/internal/dsl.ts} +1568 -2120
  125. package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +6 -6
  126. package/src/postgres/internal/schema-ddl.ts +108 -0
  127. package/src/postgres/internal/schema-model.ts +150 -0
  128. package/src/{internal → postgres/internal}/sql-expression-renderer.ts +112 -46
  129. package/src/postgres/json.ts +493 -0
  130. package/src/postgres/metadata.ts +31 -0
  131. package/src/postgres/query.ts +113 -86
  132. package/src/postgres/renderer.ts +3 -13
  133. package/src/postgres/schema-expression.ts +17 -0
  134. package/src/postgres/schema-management.ts +204 -0
  135. package/src/postgres/schema.ts +35 -0
  136. package/src/postgres/table.ts +316 -42
  137. package/src/postgres/type.ts +31 -0
  138. package/src/postgres.ts +20 -4
  139. package/CHANGELOG.md +0 -134
  140. package/src/internal/expression.ts +0 -327
  141. package/src/internal/predicate-normalize.ts +0 -202
  142. package/src/mysql/function/json.ts +0 -4
  143. package/src/mysql/private/query.ts +0 -13
  144. package/src/postgres/function/json.ts +0 -4
  145. package/src/postgres/private/query.ts +0 -13
  146. /package/src/internal/{predicate-atom.ts → predicate/atom.ts} +0 -0
@@ -1,22 +1,36 @@
1
+ import type * as Brand from "effect/Brand"
1
2
  import * as Schema from "effect/Schema"
2
3
 
3
- import * as Expression from "./expression.js"
4
+ import * as Expression from "./scalar.js"
5
+ import type { CanCastDbType } from "./datatypes/lookup.js"
4
6
  import {
7
+ BigIntStringSchema,
8
+ InstantStringSchema,
5
9
  LocalDateStringSchema,
6
10
  DecimalStringSchema,
7
11
  LocalDateTimeStringSchema,
12
+ LocalTimeStringSchema,
13
+ OffsetTimeStringSchema,
8
14
  type LocalDateString,
15
+ type LocalTimeString,
16
+ type OffsetTimeString,
17
+ type InstantString,
9
18
  type DecimalString,
10
- type LocalDateTimeString
11
- } from "./runtime-value.js"
19
+ type LocalDateTimeString,
20
+ type BigIntString
21
+ } from "./runtime/value.js"
12
22
  import {
13
23
  type AnyBoundColumn,
14
24
  type AnyColumnDefinition,
15
25
  type BaseSelectType,
16
26
  type BoundColumn,
27
+ BoundColumnTypeId,
17
28
  ColumnTypeId,
29
+ type DdlExpression,
18
30
  type ColumnDefinition,
31
+ type ColumnUniqueOptions,
19
32
  type ColumnReference,
33
+ type ColumnIndexOptions,
20
34
  type HasDefault,
21
35
  type InsertType,
22
36
  type IsGenerated,
@@ -29,11 +43,13 @@ import {
29
43
  type UpdateType
30
44
  } from "./column-state.js"
31
45
 
46
+ type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
47
+
32
48
  type CompatibleReference<
33
49
  Self extends AnyColumnDefinition,
34
50
  Target extends AnyBoundColumn
35
- > = [BaseSelectType<Self>] extends [BaseSelectType<Target>]
36
- ? [BaseSelectType<Target>] extends [BaseSelectType<Self>]
51
+ > = [Self[typeof ColumnTypeId]["dbType"]] extends [Target[typeof ColumnTypeId]["dbType"]]
52
+ ? [Target[typeof ColumnTypeId]["dbType"]] extends [Self[typeof ColumnTypeId]["dbType"]]
37
53
  ? Self
38
54
  : never
39
55
  : never
@@ -51,7 +67,7 @@ type NullableColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
51
67
  IsPrimaryKey<Column>,
52
68
  Column[typeof ColumnTypeId]["unique"],
53
69
  ReferencesOf<Column>
54
- >
70
+ > & PreserveBrand<Column>
55
71
 
56
72
  type PrimaryKeyColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
57
73
  SelectType<Column>,
@@ -64,7 +80,7 @@ type PrimaryKeyColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
64
80
  true,
65
81
  true,
66
82
  ReferencesOf<Column>
67
- >
83
+ > & PreserveBrand<Column>
68
84
 
69
85
  type UniqueColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
70
86
  SelectType<Column>,
@@ -77,7 +93,9 @@ type UniqueColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
77
93
  IsPrimaryKey<Column>,
78
94
  true,
79
95
  ReferencesOf<Column>
80
- >
96
+ > & PreserveBrand<Column>
97
+
98
+ type IndexedColumn<Column extends AnyColumnDefinition> = Column
81
99
 
82
100
  type HasDefaultColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
83
101
  SelectType<Column>,
@@ -90,7 +108,20 @@ type HasDefaultColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
90
108
  IsPrimaryKey<Column>,
91
109
  Column[typeof ColumnTypeId]["unique"],
92
110
  ReferencesOf<Column>
93
- >
111
+ > & PreserveBrand<Column>
112
+
113
+ type DdlTypedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
114
+ SelectType<Column>,
115
+ InsertType<Column>,
116
+ UpdateType<Column>,
117
+ Column[typeof ColumnTypeId]["dbType"],
118
+ IsNullable<Column>,
119
+ HasDefault<Column>,
120
+ IsGenerated<Column>,
121
+ IsPrimaryKey<Column>,
122
+ Column[typeof ColumnTypeId]["unique"],
123
+ ReferencesOf<Column>
124
+ > & PreserveBrand<Column>
94
125
 
95
126
  type GeneratedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
96
127
  SelectType<Column>,
@@ -103,12 +134,55 @@ type GeneratedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
103
134
  IsPrimaryKey<Column>,
104
135
  Column[typeof ColumnTypeId]["unique"],
105
136
  ReferencesOf<Column>
106
- >
137
+ > & PreserveBrand<Column>
138
+
139
+ type ByDefaultIdentityColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
140
+ SelectType<Column>,
141
+ InsertType<Column>,
142
+ UpdateType<Column>,
143
+ Column[typeof ColumnTypeId]["dbType"],
144
+ IsNullable<Column>,
145
+ true,
146
+ false,
147
+ IsPrimaryKey<Column>,
148
+ Column[typeof ColumnTypeId]["unique"],
149
+ ReferencesOf<Column>
150
+ > & PreserveBrand<Column>
151
+
152
+ type AlwaysIdentityColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
153
+ SelectType<Column>,
154
+ InsertType<Column>,
155
+ UpdateType<Column>,
156
+ Column[typeof ColumnTypeId]["dbType"],
157
+ IsNullable<Column>,
158
+ false,
159
+ true,
160
+ IsPrimaryKey<Column>,
161
+ Column[typeof ColumnTypeId]["unique"],
162
+ ReferencesOf<Column>
163
+ > & PreserveBrand<Column>
107
164
 
108
165
  type CompatibleColumnExpression<
109
166
  Column extends AnyColumnDefinition,
110
167
  Value extends Expression.Any
111
- > = [Expression.RuntimeOf<Value>] extends [SelectType<Column>] ? Column : never
168
+ > = [Expression.RuntimeOf<Value>] extends [SelectType<Column>]
169
+ ? Column
170
+ : CanCastDbType<
171
+ Expression.DbTypeOf<Value>,
172
+ Column[typeof ColumnTypeId]["dbType"],
173
+ Column[typeof ColumnTypeId]["dbType"]["dialect"]
174
+ > extends true
175
+ ? Column
176
+ : never
177
+
178
+ type CompatibleDdlExpression<
179
+ Column extends AnyColumnDefinition,
180
+ Value extends DdlExpression
181
+ > = Value extends Expression.Any ? CompatibleColumnExpression<Column, Value> : Column
182
+
183
+ type BaseInsertType<Column extends AnyColumnDefinition> = NonNullable<InsertType<Column>>
184
+
185
+ type BaseUpdateType<Column extends AnyColumnDefinition> = NonNullable<UpdateType<Column>>
112
186
 
113
187
  type ReferencingColumn<
114
188
  Column extends AnyColumnDefinition,
@@ -124,7 +198,16 @@ type ReferencingColumn<
124
198
  IsPrimaryKey<Column>,
125
199
  Column[typeof ColumnTypeId]["unique"],
126
200
  ColumnReference<Target>
127
- >
201
+ > & PreserveBrand<Column>
202
+
203
+ type ForeignKeyOptions<Target extends AnyBoundColumn> = {
204
+ readonly target: () => Target
205
+ readonly name?: string
206
+ readonly onUpdate?: ReferentialAction
207
+ readonly onDelete?: ReferentialAction
208
+ readonly deferrable?: boolean
209
+ readonly initiallyDeferred?: boolean
210
+ }
128
211
 
129
212
  type SchemaCompatibleColumn<
130
213
  Column extends AnyColumnDefinition,
@@ -154,20 +237,130 @@ type ColumnWithSchema<
154
237
  IsPrimaryKey<Column>,
155
238
  Column[typeof ColumnTypeId]["unique"],
156
239
  ReferencesOf<Column>,
157
- Column[typeof ColumnTypeId]["source"],
158
240
  Column[typeof ColumnTypeId]["dependencies"]
159
- >
241
+ > & PreserveBrand<Column>
242
+
243
+ type BrandNameOf<Column extends AnyBoundColumn> =
244
+ `${Column[typeof BoundColumnTypeId]["tableName"]}.${Column[typeof BoundColumnTypeId]["columnName"]}`
245
+
246
+ type BrandedValue<
247
+ Value,
248
+ BrandName extends string
249
+ > = [Extract<Value, null | undefined>] extends [never]
250
+ ? Value & Brand.Brand<BrandName>
251
+ : Exclude<Value, null | undefined> & Brand.Brand<BrandName> | Extract<Value, null | undefined>
252
+
253
+ type BrandMetadata<Column extends AnyColumnDefinition> = {
254
+ readonly metadata: Column["metadata"] & { readonly brand: true }
255
+ }
256
+
257
+ type PreserveBrand<Column extends AnyColumnDefinition> = Column["metadata"]["brand"] extends true
258
+ ? BrandMetadata<Column>
259
+ : {}
260
+
261
+ type BrandedBoundColumn<
262
+ Column extends AnyBoundColumn
263
+ > = BoundColumn<
264
+ BrandedValue<SelectType<Column>, BrandNameOf<Column>>,
265
+ BrandedValue<InsertType<Column>, BrandNameOf<Column>>,
266
+ BrandedValue<UpdateType<Column>, BrandNameOf<Column>>,
267
+ Column[typeof ColumnTypeId]["dbType"],
268
+ IsNullable<Column>,
269
+ HasDefault<Column>,
270
+ IsGenerated<Column>,
271
+ IsPrimaryKey<Column>,
272
+ Column[typeof ColumnTypeId]["unique"],
273
+ ReferencesOf<Column>,
274
+ Column[typeof BoundColumnTypeId]["tableName"],
275
+ Column[typeof BoundColumnTypeId]["columnName"],
276
+ Column[typeof BoundColumnTypeId]["baseTableName"]
277
+ > & BrandMetadata<Column>
278
+
279
+ type BrandMarkedColumn<
280
+ Column extends AnyColumnDefinition
281
+ > = ColumnDefinition<
282
+ SelectType<Column>,
283
+ InsertType<Column>,
284
+ UpdateType<Column>,
285
+ Column[typeof ColumnTypeId]["dbType"],
286
+ IsNullable<Column>,
287
+ HasDefault<Column>,
288
+ IsGenerated<Column>,
289
+ IsPrimaryKey<Column>,
290
+ Column[typeof ColumnTypeId]["unique"],
291
+ ReferencesOf<Column>,
292
+ Column[typeof ColumnTypeId]["dependencies"]
293
+ > & BrandMetadata<Column>
294
+
295
+ export interface ArrayOptions {
296
+ readonly nullableElements?: boolean
297
+ }
298
+
299
+ export type NumericOptions =
300
+ | {
301
+ readonly precision?: undefined
302
+ readonly scale?: undefined
303
+ }
304
+ | {
305
+ readonly precision: number
306
+ readonly scale?: number
307
+ }
308
+
309
+ type ArrayElementSelect<
310
+ Column extends AnyColumnDefinition,
311
+ Options extends ArrayOptions | undefined
312
+ > = Options extends { readonly nullableElements: true }
313
+ ? NullableSelect<BaseSelectType<Column>>
314
+ : BaseSelectType<Column>
315
+
316
+ type ArrayElementInsert<
317
+ Column extends AnyColumnDefinition,
318
+ Options extends ArrayOptions | undefined
319
+ > = Options extends { readonly nullableElements: true }
320
+ ? NullableSelect<BaseInsertType<Column>>
321
+ : BaseInsertType<Column>
322
+
323
+ type ArrayElementUpdate<
324
+ Column extends AnyColumnDefinition,
325
+ Options extends ArrayOptions | undefined
326
+ > = Options extends { readonly nullableElements: true }
327
+ ? NullableSelect<BaseUpdateType<Column>>
328
+ : BaseUpdateType<Column>
329
+
330
+ type ArrayColumn<
331
+ Column extends AnyColumnDefinition,
332
+ Options extends ArrayOptions | undefined = undefined
333
+ > = ColumnDefinition<
334
+ ReadonlyArray<ArrayElementSelect<Column, Options>>,
335
+ ReadonlyArray<ArrayElementInsert<Column, Options>>,
336
+ ReadonlyArray<ArrayElementUpdate<Column, Options>>,
337
+ Expression.DbType.Array<
338
+ Column[typeof ColumnTypeId]["dbType"]["dialect"],
339
+ Column[typeof ColumnTypeId]["dbType"],
340
+ `${Column[typeof ColumnTypeId]["dbType"]["kind"]}[]`
341
+ >,
342
+ IsNullable<Column>,
343
+ HasDefault<Column>,
344
+ IsGenerated<Column>,
345
+ IsPrimaryKey<Column>,
346
+ Column[typeof ColumnTypeId]["unique"],
347
+ ReferencesOf<Column>,
348
+ Column[typeof ColumnTypeId]["dependencies"]
349
+ > & PreserveBrand<Column>
160
350
 
161
351
  const mapColumn = <
162
352
  Column extends AnyColumnDefinition,
163
353
  Next extends AnyColumnDefinition
164
354
  >(
165
355
  column: Column,
166
- metadata: Next["metadata"]
356
+ metadata: AnyColumnDefinition["metadata"]
167
357
  ): Next => remapColumnDefinition(column as any, {
168
358
  metadata
169
359
  }) as Next
170
360
 
361
+ const isColumnDefinitionValue = (value: unknown): value is AnyColumnDefinition =>
362
+ typeof value === "object" && value !== null && ColumnTypeId in value
363
+
171
364
  const primitive = <Type, Db extends Expression.DbType.Any>(
172
365
  schema: Schema.Schema<Type, any, any>,
173
366
  dbType: Db
@@ -214,7 +407,7 @@ type ColumnModule<
214
407
  readonly uuid: () => ColumnDefinition<string, string, string, Expression.DbType.Base<Dialect, UuidKind>, false, false, false, false, false, undefined>
215
408
  readonly text: () => ColumnDefinition<string, string, string, Expression.DbType.Base<Dialect, TextKind>, false, false, false, false, false, undefined>
216
409
  readonly int: () => ColumnDefinition<number, number, number, Expression.DbType.Base<Dialect, IntKind>, false, false, false, false, false, undefined>
217
- readonly number: () => ColumnDefinition<DecimalString, DecimalString, DecimalString, Expression.DbType.Base<Dialect, NumberKind>, false, false, false, false, false, undefined>
410
+ readonly number: (options?: NumericOptions) => ColumnDefinition<DecimalString, DecimalString, DecimalString, Expression.DbType.Base<Dialect, NumberKind>, false, false, false, false, false, undefined>
218
411
  readonly boolean: () => ColumnDefinition<boolean, boolean, boolean, Expression.DbType.Base<Dialect, BooleanKind>, false, false, false, false, false, undefined>
219
412
  readonly date: () => ColumnDefinition<LocalDateString, LocalDateString, LocalDateString, Expression.DbType.Base<Dialect, DateKind>, false, false, false, false, false, undefined>
220
413
  readonly timestamp: () => ColumnDefinition<LocalDateTimeString, LocalDateTimeString, LocalDateTimeString, Expression.DbType.Base<Dialect, TimestampKind>, false, false, false, false, false, undefined>
@@ -234,117 +427,6 @@ type ColumnModule<
234
427
  >
235
428
  }
236
429
 
237
- const typeFactory = <Dialect extends string>(dialect: Dialect) =>
238
- <Kind extends string>(kind: Kind): Expression.DbType.Base<Dialect, Kind> => ({
239
- dialect,
240
- kind
241
- })
242
-
243
- const makeColumnModule = <
244
- Dialect extends string,
245
- UuidKind extends string,
246
- TextKind extends string,
247
- IntKind extends string,
248
- NumberKind extends string,
249
- BooleanKind extends string,
250
- DateKind extends string,
251
- TimestampKind extends string,
252
- JsonKind extends string
253
- >(
254
- dialect: Dialect,
255
- kinds: {
256
- readonly uuid: UuidKind
257
- readonly text: TextKind
258
- readonly int: IntKind
259
- readonly number: NumberKind
260
- readonly boolean: BooleanKind
261
- readonly date: DateKind
262
- readonly timestamp: TimestampKind
263
- readonly json: JsonKind
264
- }
265
- ): ColumnModule<Dialect, UuidKind, TextKind, IntKind, NumberKind, BooleanKind, DateKind, TimestampKind, JsonKind> => {
266
- const dialectType = typeFactory(dialect)
267
- return {
268
- custom: <SchemaType extends Schema.Schema.Any, Db extends Expression.DbType.Any>(
269
- schema: SchemaType,
270
- dbType: Db
271
- ) =>
272
- makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
273
- dbType,
274
- nullable: false,
275
- hasDefault: false,
276
- generated: false,
277
- primaryKey: false,
278
- unique: false,
279
- references: undefined
280
- }),
281
- uuid: () => primitive(Schema.UUID, dialectType(kinds.uuid)),
282
- text: () => primitive(Schema.String, dialectType(kinds.text)),
283
- int: () => primitive(Schema.Int, dialectType(kinds.int)),
284
- number: () => primitive(DecimalStringSchema, dialectType(kinds.number)),
285
- boolean: () => primitive(Schema.Boolean, dialectType(kinds.boolean)),
286
- date: () => primitive(LocalDateStringSchema, dialectType(kinds.date)),
287
- timestamp: () => primitive(LocalDateTimeStringSchema, dialectType(kinds.timestamp)),
288
- json: <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =>
289
- makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
290
- dbType: {
291
- ...dialectType(kinds.json),
292
- variant: "json"
293
- } as Expression.DbType.Json<Dialect, JsonKind>,
294
- nullable: false,
295
- hasDefault: false,
296
- generated: false,
297
- primaryKey: false,
298
- unique: false,
299
- references: undefined
300
- })
301
- }
302
- }
303
-
304
- /** Postgres-specialized column constructors. */
305
- export const postgres = makeColumnModule("postgres", {
306
- uuid: "uuid",
307
- text: "text",
308
- int: "int4",
309
- number: "numeric",
310
- boolean: "bool",
311
- date: "date",
312
- timestamp: "timestamp",
313
- json: "json"
314
- })
315
-
316
- /** MySQL-specialized column constructors. */
317
- export const mysql = makeColumnModule("mysql", {
318
- uuid: "uuid",
319
- text: "text",
320
- int: "int",
321
- number: "decimal",
322
- boolean: "boolean",
323
- date: "date",
324
- timestamp: "timestamp",
325
- json: "json"
326
- })
327
-
328
- /** Creates a Postgres `uuid` column. */
329
- export const uuid = postgres.uuid
330
- /** Creates a Postgres `text` column. */
331
- export const text = postgres.text
332
- /** Creates a Postgres `int4` column. */
333
- export const int = postgres.int
334
- /** Creates a Postgres `numeric` column decoded as `DecimalString`. */
335
- export const number = postgres.number
336
- /** Creates a Postgres `bool` column. */
337
- export const boolean = postgres.boolean
338
- /** Creates a Postgres `date` column decoded as `LocalDateString`. */
339
- export const date = postgres.date
340
- /** Creates a Postgres `timestamp` column decoded as `LocalDateTimeString`. */
341
- export const timestamp = postgres.timestamp
342
-
343
- /** Creates a Postgres `json` column backed by an arbitrary Effect schema. */
344
- export const json = postgres.json
345
- /** Creates a Postgres column backed by an arbitrary SQL type and Effect schema. */
346
- export const custom = postgres.custom
347
-
348
430
  /** Replaces a column's runtime schema while preserving its SQL type metadata. */
349
431
  export const schema = <SchemaType extends Schema.Schema.Any>(nextSchema: SchemaType) =>
350
432
  <Column extends AnyColumnDefinition>(
@@ -354,6 +436,33 @@ export const schema = <SchemaType extends Schema.Schema.Any>(nextSchema: SchemaT
354
436
  schema: nextSchema
355
437
  }) as ColumnWithSchema<Column, SchemaType>
356
438
 
439
+ type BrandResult<Column extends AnyColumnDefinition> = Column extends AnyBoundColumn
440
+ ? BrandedBoundColumn<Column>
441
+ : BrandMarkedColumn<Column>
442
+
443
+ /** Brands a column with its `table.column` provenance. */
444
+ export const brand = <Column extends AnyColumnDefinition>(
445
+ column: Column
446
+ ): BrandResult<Column> => {
447
+ if (BoundColumnTypeId in column) {
448
+ const boundColumn = column as unknown as AnyBoundColumn
449
+ const brandName = `${boundColumn[BoundColumnTypeId].tableName}.${boundColumn[BoundColumnTypeId].columnName}`
450
+ return remapColumnDefinition(boundColumn, {
451
+ schema: Schema.brand(brandName)(boundColumn.schema),
452
+ metadata: {
453
+ ...boundColumn.metadata,
454
+ brand: true
455
+ }
456
+ }) as BrandResult<Column>
457
+ }
458
+ return remapColumnDefinition(column, {
459
+ metadata: {
460
+ ...column.metadata,
461
+ brand: true
462
+ }
463
+ }) as BrandResult<Column>
464
+ }
465
+
357
466
  /** Marks a column as nullable. Nullable columns decode as `T | null`. */
358
467
  export const nullable = <Column extends AnyColumnDefinition>(
359
468
  column: Column[typeof ColumnTypeId]["primaryKey"] extends true ? never : Column
@@ -361,7 +470,7 @@ export const nullable = <Column extends AnyColumnDefinition>(
361
470
  mapColumn(column, {
362
471
  ...column.metadata,
363
472
  nullable: true
364
- })
473
+ }) as NullableColumn<Column>
365
474
 
366
475
  /** Marks a column as a primary key. Primary keys are always unique and non-null. */
367
476
  export const primaryKey = <Column extends AnyColumnDefinition>(
@@ -372,55 +481,184 @@ export const primaryKey = <Column extends AnyColumnDefinition>(
372
481
  nullable: false,
373
482
  primaryKey: true,
374
483
  unique: true
375
- })
484
+ }) as PrimaryKeyColumn<Column>
485
+
486
+ type UniqueModifier = {
487
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
488
+ readonly options: <const Options extends ColumnUniqueOptions>(
489
+ options: Options
490
+ ) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
491
+ }
376
492
 
377
493
  /** Marks a column as unique. */
378
- export const unique = <Column extends AnyColumnDefinition>(
379
- column: Column
380
- ): UniqueColumn<Column> =>
381
- mapColumn(column, {
382
- ...column.metadata,
383
- unique: true
384
- })
494
+ export const unique: UniqueModifier = Object.assign(
495
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column> =>
496
+ mapColumn(column, {
497
+ ...column.metadata,
498
+ unique: true
499
+ }) as UniqueColumn<Column>,
500
+ {
501
+ options: <const Options extends ColumnUniqueOptions>(options: Options) =>
502
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column> =>
503
+ mapColumn(column, {
504
+ ...column.metadata,
505
+ unique: true,
506
+ uniqueConstraint: options
507
+ }) as UniqueColumn<Column>
508
+ }
509
+ )
385
510
 
386
511
  /** Marks a column as having a database default expression and therefore optional on insert. */
387
- export const default_ = <Value extends Expression.Any>(value: Value) =>
512
+ export const default_ = <Value extends DdlExpression>(value: Value) =>
388
513
  <Column extends AnyColumnDefinition>(
389
- column: Column[typeof ColumnTypeId]["generated"] extends true ? never : CompatibleColumnExpression<Column, Value>
514
+ column: Column[typeof ColumnTypeId]["generated"] extends true ? never : CompatibleDdlExpression<Column, Value>
390
515
  ): HasDefaultColumn<Column> =>
391
516
  mapColumn(column, {
392
517
  ...column.metadata,
393
518
  hasDefault: true,
394
519
  defaultValue: value,
395
- generatedValue: undefined
396
- })
520
+ generatedValue: undefined,
521
+ identity: undefined
522
+ }) as HasDefaultColumn<Column>
397
523
 
398
524
  /** Marks a column as generated by the database expression and omitted from insert/update. */
399
- export const generated = <Value extends Expression.Any>(value: Value) =>
525
+ export const generated = <Value extends DdlExpression>(value: Value) =>
400
526
  <Column extends AnyColumnDefinition>(
401
- column: Column[typeof ColumnTypeId]["hasDefault"] extends true ? never : CompatibleColumnExpression<Column, Value>
527
+ column: Column[typeof ColumnTypeId]["hasDefault"] extends true ? never : CompatibleDdlExpression<Column, Value>
402
528
  ): GeneratedColumn<Column> =>
403
529
  mapColumn(column, {
404
530
  ...column.metadata,
405
531
  generated: true,
406
532
  hasDefault: false,
407
533
  defaultValue: undefined,
408
- generatedValue: value
534
+ generatedValue: value,
535
+ identity: undefined
536
+ }) as GeneratedColumn<Column>
537
+
538
+ /** Preserves the exact SQL type used for DDL rendering. */
539
+ export const ddlType = <SqlType extends string>(sqlType: SqlType) =>
540
+ <Column extends AnyColumnDefinition>(column: Column): DdlTypedColumn<Column> =>
541
+ mapColumn(column, {
542
+ ...column.metadata,
543
+ ddlType: sqlType
544
+ }) as DdlTypedColumn<Column>
545
+
546
+ /** Marks a column as a Postgres array type. */
547
+ export const array = <Options extends ArrayOptions | undefined = undefined>(
548
+ options?: Options
549
+ ) =>
550
+ <Column extends AnyColumnDefinition>(
551
+ column: Column
552
+ ): ArrayColumn<Column, Options> =>
553
+ remapColumnDefinition(column as AnyColumnDefinition, {
554
+ schema: Schema.Array(options?.nullableElements ? Schema.NullOr(column.schema) : column.schema),
555
+ metadata: {
556
+ ...column.metadata,
557
+ dbType: {
558
+ dialect: column.metadata.dbType.dialect,
559
+ kind: `${column.metadata.dbType.kind}[]`,
560
+ element: column.metadata.dbType
561
+ } as Expression.DbType.Array<
562
+ Column[typeof ColumnTypeId]["dbType"]["dialect"],
563
+ Column[typeof ColumnTypeId]["dbType"],
564
+ `${Column[typeof ColumnTypeId]["dbType"]["kind"]}[]`
565
+ >,
566
+ ddlType: `${column.metadata.ddlType ?? column.metadata.dbType.kind}[]`
567
+ }
568
+ }) as ArrayColumn<Column, Options>
569
+
570
+ /** Marks a column as indexed. */
571
+ export function index<Column extends AnyColumnDefinition>(
572
+ column: Column
573
+ ): IndexedColumn<Column>
574
+ export function index<const Options extends ColumnIndexOptions>(
575
+ options: Options
576
+ ): <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
577
+ export function index(arg: unknown): unknown {
578
+ if (isColumnDefinitionValue(arg)) {
579
+ return mapColumn(arg, {
580
+ ...arg.metadata,
581
+ index: arg.metadata.index ?? {}
409
582
  })
583
+ }
584
+ const options = (arg ?? {}) as ColumnIndexOptions
585
+ return <Column extends AnyColumnDefinition>(
586
+ column: Column
587
+ ): IndexedColumn<Column> =>
588
+ mapColumn(column, {
589
+ ...column.metadata,
590
+ index: options
591
+ })
592
+ }
593
+
594
+ /** Marks a column as `generated by default as identity`. */
595
+ export const identityByDefault = <Column extends AnyColumnDefinition>(
596
+ column: Column[typeof ColumnTypeId]["generated"] extends true ? never : Column
597
+ ): ByDefaultIdentityColumn<Column> =>
598
+ mapColumn(column, {
599
+ ...column.metadata,
600
+ hasDefault: true,
601
+ generated: false,
602
+ defaultValue: undefined,
603
+ generatedValue: undefined,
604
+ identity: {
605
+ generation: "byDefault"
606
+ }
607
+ }) as ByDefaultIdentityColumn<Column>
608
+
609
+ /** Marks a column as `generated always as identity`. */
610
+ export const identityAlways = <Column extends AnyColumnDefinition>(
611
+ column: Column[typeof ColumnTypeId]["hasDefault"] extends true ? never : Column
612
+ ): AlwaysIdentityColumn<Column> =>
613
+ mapColumn(column, {
614
+ ...column.metadata,
615
+ hasDefault: false,
616
+ generated: true,
617
+ defaultValue: undefined,
618
+ generatedValue: undefined,
619
+ identity: {
620
+ generation: "always"
621
+ }
622
+ }) as AlwaysIdentityColumn<Column>
410
623
 
411
624
  /**
412
625
  * Attaches a lazy foreign-key reference to another bound column.
413
626
  *
414
627
  * The base, non-null select types must match.
415
628
  */
416
- export const references = <Target extends AnyBoundColumn>(target: () => Target) =>
417
- <Column extends AnyColumnDefinition>(
418
- column: CompatibleReference<Column, Target>
419
- ): ReferencingColumn<Column, Target> =>
629
+ export function foreignKey<Target extends AnyBoundColumn>(
630
+ target: () => Target
631
+ ): <Column extends AnyColumnDefinition>(
632
+ column: CompatibleReference<Column, Target>
633
+ ) => ReferencingColumn<Column, Target>
634
+ export function foreignKey<const Options extends ForeignKeyOptions<AnyBoundColumn>>(
635
+ options: Options
636
+ ): <Column extends AnyColumnDefinition>(
637
+ column: CompatibleReference<Column, ReturnType<Options["target"]>>
638
+ ) => ReferencingColumn<Column, ReturnType<Options["target"]>>
639
+ export function foreignKey(arg: unknown): unknown {
640
+ if (typeof arg === "function") {
641
+ const target = arg as () => AnyBoundColumn
642
+ return <Column extends AnyColumnDefinition>(
643
+ column: CompatibleReference<Column, AnyBoundColumn>
644
+ ): ReferencingColumn<Column, AnyBoundColumn> =>
645
+ mapColumn(column, {
646
+ ...column.metadata,
647
+ references: { target }
648
+ }) as ReferencingColumn<Column, AnyBoundColumn>
649
+ }
650
+ const options = arg as ForeignKeyOptions<AnyBoundColumn>
651
+ return <Column extends AnyColumnDefinition>(
652
+ column: CompatibleReference<Column, ReturnType<typeof options.target>>
653
+ ): ReferencingColumn<Column, ReturnType<typeof options.target>> =>
420
654
  mapColumn(column, {
421
655
  ...column.metadata,
422
- references: { target }
423
- })
656
+ references: options
657
+ }) as ReferencingColumn<Column, ReturnType<typeof options.target>>
658
+ }
659
+
660
+ export const references = <Target extends AnyBoundColumn>(target: () => Target) =>
661
+ foreignKey(target)
424
662
 
425
663
  /** Convenience alias for any column definition. */
426
664
  export type Any = AnyColumnDefinition