effect-qb 0.15.0 → 0.17.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 (88) hide show
  1. package/dist/mysql.js +1957 -595
  2. package/dist/postgres/metadata.js +2507 -182
  3. package/dist/postgres.js +9587 -8201
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +7 -2
  6. package/src/internal/column-state.ts +7 -0
  7. package/src/internal/column.ts +22 -0
  8. package/src/internal/derived-table.ts +29 -3
  9. package/src/internal/dialect.ts +14 -1
  10. package/src/internal/dsl-mutation-runtime.ts +173 -4
  11. package/src/internal/dsl-plan-runtime.ts +165 -20
  12. package/src/internal/dsl-query-runtime.ts +60 -6
  13. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  14. package/src/internal/executor.ts +62 -13
  15. package/src/internal/expression-ast.ts +3 -2
  16. package/src/internal/grouping-key.ts +141 -1
  17. package/src/internal/implication-runtime.ts +2 -1
  18. package/src/internal/json/types.ts +155 -40
  19. package/src/internal/predicate/analysis.ts +103 -1
  20. package/src/internal/predicate/atom.ts +7 -0
  21. package/src/internal/predicate/context.ts +170 -17
  22. package/src/internal/predicate/key.ts +64 -2
  23. package/src/internal/predicate/normalize.ts +115 -34
  24. package/src/internal/predicate/runtime.ts +144 -13
  25. package/src/internal/query.ts +563 -103
  26. package/src/internal/renderer.ts +39 -2
  27. package/src/internal/runtime/driver-value-mapping.ts +244 -0
  28. package/src/internal/runtime/normalize.ts +62 -38
  29. package/src/internal/runtime/schema.ts +5 -3
  30. package/src/internal/runtime/value.ts +153 -30
  31. package/src/internal/scalar.ts +11 -0
  32. package/src/internal/table-options.ts +108 -1
  33. package/src/internal/table.ts +87 -29
  34. package/src/mysql/column.ts +19 -2
  35. package/src/mysql/datatypes/index.ts +21 -0
  36. package/src/mysql/errors/catalog.ts +5 -5
  37. package/src/mysql/errors/normalize.ts +2 -2
  38. package/src/mysql/executor.ts +20 -5
  39. package/src/mysql/internal/dialect.ts +12 -6
  40. package/src/mysql/internal/dsl.ts +995 -263
  41. package/src/mysql/internal/renderer.ts +13 -3
  42. package/src/mysql/internal/sql-expression-renderer.ts +530 -128
  43. package/src/mysql/query.ts +9 -2
  44. package/src/mysql/renderer.ts +7 -2
  45. package/src/mysql/table.ts +38 -12
  46. package/src/postgres/cast.ts +22 -7
  47. package/src/postgres/column.ts +5 -2
  48. package/src/postgres/errors/normalize.ts +2 -2
  49. package/src/postgres/executor.ts +68 -10
  50. package/src/postgres/function/core.ts +19 -1
  51. package/src/postgres/internal/dialect.ts +12 -6
  52. package/src/postgres/internal/dsl.ts +958 -288
  53. package/src/postgres/internal/renderer.ts +13 -3
  54. package/src/postgres/internal/schema-ddl.ts +2 -1
  55. package/src/postgres/internal/schema-model.ts +6 -3
  56. package/src/postgres/internal/sql-expression-renderer.ts +477 -96
  57. package/src/postgres/json.ts +57 -17
  58. package/src/postgres/query.ts +9 -2
  59. package/src/postgres/renderer.ts +7 -2
  60. package/src/postgres/schema-management.ts +91 -4
  61. package/src/postgres/schema.ts +1 -1
  62. package/src/postgres/table.ts +189 -53
  63. package/src/postgres/type.ts +4 -0
  64. package/src/sqlite/column.ts +128 -0
  65. package/src/sqlite/datatypes/index.ts +79 -0
  66. package/src/sqlite/datatypes/spec.ts +98 -0
  67. package/src/sqlite/errors/catalog.ts +103 -0
  68. package/src/sqlite/errors/fields.ts +19 -0
  69. package/src/sqlite/errors/index.ts +19 -0
  70. package/src/sqlite/errors/normalize.ts +229 -0
  71. package/src/sqlite/errors/requirements.ts +71 -0
  72. package/src/sqlite/errors/types.ts +29 -0
  73. package/src/sqlite/executor.ts +227 -0
  74. package/src/sqlite/function/aggregate.ts +2 -0
  75. package/src/sqlite/function/core.ts +2 -0
  76. package/src/sqlite/function/index.ts +19 -0
  77. package/src/sqlite/function/string.ts +2 -0
  78. package/src/sqlite/function/temporal.ts +100 -0
  79. package/src/sqlite/function/window.ts +2 -0
  80. package/src/sqlite/internal/dialect.ts +37 -0
  81. package/src/sqlite/internal/dsl.ts +6926 -0
  82. package/src/sqlite/internal/renderer.ts +47 -0
  83. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  84. package/src/sqlite/json.ts +2 -0
  85. package/src/sqlite/query.ts +196 -0
  86. package/src/sqlite/renderer.ts +24 -0
  87. package/src/sqlite/table.ts +183 -0
  88. package/src/sqlite.ts +22 -0
@@ -3,6 +3,7 @@ import type * as Schema from "effect/Schema"
3
3
  import type * as Expression from "../internal/scalar.js"
4
4
  import { ColumnTypeId, type AnyColumnDefinition } from "../internal/column-state.js"
5
5
  import * as BaseTable from "../internal/table.js"
6
+ import type { TableOptionSpec } from "../internal/table-options.js"
6
7
 
7
8
  type Dialect = "postgres"
8
9
 
@@ -41,6 +42,8 @@ type FieldsOfTable<Table> = Table extends BaseTable.TableDefinition<any, infer F
41
42
  ? Fields
42
43
  : never
43
44
 
45
+ type ColumnNamesOfTable<Table> = Extract<keyof FieldsOfTable<Table>, string>
46
+
44
47
  type PrimaryKeyOfTable<Table> = Table extends BaseTable.TableDefinition<any, any, infer PrimaryKeyColumns extends string, any, any>
45
48
  ? PrimaryKeyColumns
46
49
  : Table extends BaseTable.TableClassStatic<any, any, infer PrimaryKeyColumns extends string, any>
@@ -53,6 +56,33 @@ type SchemaNameOfTable<Table> = Table extends BaseTable.TableDefinition<any, any
53
56
  ? SchemaName
54
57
  : never
55
58
 
59
+ type ApplySchemaTableOptions<
60
+ Name extends string,
61
+ Fields extends DialectFieldMap,
62
+ PrimaryKeyColumns extends keyof Fields & string,
63
+ SchemaName extends string,
64
+ Options extends BaseTable.DeclaredTableOptions
65
+ > = BaseTable.ApplyDeclaredOptions<
66
+ BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
67
+ Options
68
+ > extends BaseTable.TableDefinition<any, any, infer AppliedPrimaryKeyColumns extends keyof Fields & string, "schema", any>
69
+ ? TableDefinition<Name, Fields, AppliedPrimaryKeyColumns, "schema", SchemaName>
70
+ : TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
71
+
72
+ export type TableSchemaNamespace<SchemaName extends string> = {
73
+ readonly schemaName: SchemaName
74
+ readonly table: <
75
+ Name extends string,
76
+ Fields extends DialectFieldMap,
77
+ const Options extends BaseTable.DeclaredTableOptions,
78
+ PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
79
+ >(
80
+ name: Name,
81
+ fields: Fields,
82
+ ...options: Options & BaseTable.ValidateDeclaredOptions<BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
83
+ ) => ApplySchemaTableOptions<Name, Fields, PrimaryKeyColumns, SchemaName, Options>
84
+ }
85
+
56
86
  export type TableOption = BaseTable.TableOption
57
87
  export type DdlExpressionLike = BaseTable.DdlExpressionLike
58
88
  export type IndexKey = BaseTable.IndexKeySpec
@@ -89,6 +119,34 @@ export const make = <
89
119
  ): TableDefinition<Name, Fields> =>
90
120
  BaseTable.make(name, fields, schemaName) as TableDefinition<Name, Fields>
91
121
 
122
+ export const schema = <SchemaName extends string>(
123
+ schemaName: SchemaName
124
+ ): TableSchemaNamespace<SchemaName> => {
125
+ const table = <
126
+ Name extends string,
127
+ Fields extends DialectFieldMap,
128
+ const Options extends BaseTable.DeclaredTableOptions,
129
+ PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
130
+ >(
131
+ name: Name,
132
+ fields: Fields,
133
+ ...declaredOptions: Options & BaseTable.ValidateDeclaredOptions<BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
134
+ ) =>
135
+ (BaseTable.schema(schemaName).table as (
136
+ name: Name,
137
+ fields: Fields,
138
+ ...options: BaseTable.DeclaredTableOptions
139
+ ) => BaseTable.TableDefinition<any, any, any, "schema", any>)(
140
+ name,
141
+ fields,
142
+ ...declaredOptions
143
+ ) as ApplySchemaTableOptions<Name, Fields, PrimaryKeyColumns, SchemaName, Options>
144
+ return {
145
+ schemaName,
146
+ table
147
+ } as unknown as TableSchemaNamespace<SchemaName>
148
+ }
149
+
92
150
  export const alias = <
93
151
  Table extends AnyTable,
94
152
  AliasName extends string
@@ -125,14 +183,14 @@ export const Class = <Self = never, SchemaName extends string | undefined = "pub
125
183
  export const option = BaseTable.option
126
184
 
127
185
  type RichPrimaryKeyInput<Columns extends string | readonly string[]> = {
128
- readonly columns: Columns
186
+ readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
129
187
  readonly name?: string
130
188
  readonly deferrable?: boolean
131
189
  readonly initiallyDeferred?: boolean
132
190
  }
133
191
 
134
192
  type RichUniqueInput<Columns extends string | readonly string[]> = {
135
- readonly columns: Columns
193
+ readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
136
194
  readonly name?: string
137
195
  readonly nullsNotDistinct?: boolean
138
196
  readonly deferrable?: boolean
@@ -155,9 +213,7 @@ type RichIndexKeyInput =
155
213
  readonly collation?: string
156
214
  }
157
215
 
158
- type RichIndexInput<Columns extends string | readonly string[] = string | readonly string[]> = {
159
- readonly columns?: Columns
160
- readonly keys?: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
216
+ type RichIndexDetails = {
161
217
  readonly name?: string
162
218
  readonly unique?: boolean
163
219
  readonly method?: string
@@ -165,14 +221,98 @@ type RichIndexInput<Columns extends string | readonly string[] = string | readon
165
221
  readonly predicate?: DdlExpressionLike
166
222
  }
167
223
 
224
+ type RichIndexInput<Columns extends string | readonly string[] = string | readonly string[]> = RichIndexDetails & (
225
+ | {
226
+ readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
227
+ readonly keys?: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
228
+ }
229
+ | {
230
+ readonly columns?: Columns & BaseTable.NonEmptyColumnInput<Columns>
231
+ readonly keys: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
232
+ }
233
+ )
234
+
235
+ type PrimaryKeyOptionSpec = Extract<TableOptionSpec, { readonly kind: "primaryKey" }>
236
+ type UniqueOptionSpec = Extract<TableOptionSpec, { readonly kind: "unique" }>
237
+ type IndexOptionSpec = Extract<TableOptionSpec, { readonly kind: "index" }>
238
+ type ForeignKeyOptionSpec = Extract<TableOptionSpec, { readonly kind: "foreignKey" }>
239
+
240
+ type RichPrimaryKeyOptionSpec<Columns extends string | readonly string[]> = PrimaryKeyOptionSpec & {
241
+ readonly kind: "primaryKey"
242
+ readonly columns: BaseTable.NormalizeColumns<Columns>
243
+ }
244
+
245
+ type RichUniqueOptionSpec<Columns extends string | readonly string[]> = UniqueOptionSpec & {
246
+ readonly kind: "unique"
247
+ readonly columns: BaseTable.NormalizeColumns<Columns>
248
+ }
249
+
250
+ type KnownTargetColumnsInput<
251
+ TargetTable extends AnyTable,
252
+ Columns extends string | readonly string[]
253
+ > = BaseTable.NormalizeColumns<Columns> extends infer NormalizedColumns extends readonly string[]
254
+ ? string extends NormalizedColumns[number]
255
+ ? unknown
256
+ : Exclude<NormalizedColumns[number], ColumnNamesOfTable<TargetTable>> extends never
257
+ ? unknown
258
+ : never
259
+ : never
260
+
261
+ type RichIndexColumnOption<Spec> = Spec extends { readonly columns: infer Columns extends string | readonly string[] }
262
+ ? { readonly columns: BaseTable.NormalizeColumns<Columns> }
263
+ : {}
264
+
265
+ type RichIndexIncludeOption<Spec> = Spec extends { readonly include: infer Include extends readonly string[] }
266
+ ? { readonly include: Include }
267
+ : {}
268
+
269
+ type RichIndexKeySpec<Key> = Key extends { readonly column: infer Column extends string }
270
+ ? BaseTable.IndexKeySpec & { readonly kind: "column"; readonly column: Column }
271
+ : BaseTable.IndexKeySpec & { readonly kind: "expression" }
272
+
273
+ type RichIndexKeys<Keys extends readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]> = {
274
+ readonly [K in keyof Keys]: Keys[K] extends RichIndexKeyInput ? RichIndexKeySpec<Keys[K]> : never
275
+ } & readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
276
+
277
+ type RichIndexKeysOption<Spec> = Spec extends { readonly keys: infer Keys extends readonly [RichIndexKeyInput, ...RichIndexKeyInput[]] }
278
+ ? { readonly keys: RichIndexKeys<Keys> }
279
+ : {}
280
+
281
+ type RichIndexColumnsConstraint<Spec> = Spec extends { readonly columns: infer Columns extends string | readonly string[] }
282
+ ? BaseTable.NonEmptyColumnInput<Columns> extends never ? never : unknown
283
+ : unknown
284
+
285
+ type RichIndexOptionSpec<Spec> = IndexOptionSpec & {
286
+ readonly kind: "index"
287
+ readonly name?: string
288
+ readonly unique?: boolean
289
+ readonly method?: string
290
+ readonly predicate?: DdlExpressionLike
291
+ } & RichIndexColumnOption<Spec> & RichIndexIncludeOption<Spec> & RichIndexKeysOption<Spec>
292
+
293
+ type RichForeignKeyOptionSpec<
294
+ LocalColumns extends string | readonly string[],
295
+ TargetTable extends AnyTable,
296
+ TargetColumns extends string | readonly string[]
297
+ > = ForeignKeyOptionSpec & {
298
+ readonly kind: "foreignKey"
299
+ readonly columns: BaseTable.NormalizeColumns<LocalColumns>
300
+ readonly references: () => {
301
+ readonly tableName: string
302
+ readonly schemaName?: string
303
+ readonly columns: BaseTable.NormalizeColumns<TargetColumns>
304
+ readonly knownColumns: readonly ColumnNamesOfTable<TargetTable>[]
305
+ }
306
+ }
307
+
168
308
  type RichForeignKeyInput<
169
309
  LocalColumns extends string | readonly string[],
170
310
  TargetTable extends AnyTable,
171
311
  TargetColumns extends string | readonly string[]
172
312
  > = {
173
- readonly columns: LocalColumns
313
+ readonly columns: LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>
174
314
  readonly target: () => TargetTable
175
- readonly referencedColumns: TargetColumns
315
+ readonly referencedColumns: TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
176
316
  readonly name?: string
177
317
  readonly onUpdate?: ReferentialAction
178
318
  readonly onDelete?: ReferentialAction
@@ -205,8 +345,13 @@ const makeTableScopedOption = <
205
345
  return builder
206
346
  }
207
347
 
208
- const normalizeColumns = (columns: string | readonly string[]): readonly [string, ...string[]] =>
209
- (Array.isArray(columns) ? [...columns] : [columns]) as unknown as readonly [string, ...string[]]
348
+ const normalizeColumns = (columns: string | readonly string[]): readonly [string, ...string[]] => {
349
+ const normalized = Array.isArray(columns) ? [...columns] : [columns]
350
+ if (normalized.length === 0) {
351
+ throw new Error("Table options require at least one column")
352
+ }
353
+ return normalized as unknown as readonly [string, ...string[]]
354
+ }
210
355
 
211
356
  const normalizeIndexKeys = (
212
357
  keys: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
@@ -231,14 +376,14 @@ const normalizeIndexKeys = (
231
376
 
232
377
  export const primaryKey: {
233
378
  <const Columns extends string | readonly string[]>(
234
- columns: Columns
379
+ columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
235
380
  ): BaseTable.TableOption<{
236
381
  readonly kind: "primaryKey"
237
382
  readonly columns: BaseTable.NormalizeColumns<Columns>
238
383
  }>
239
384
  <const Columns extends string | readonly string[]>(
240
385
  spec: RichPrimaryKeyInput<Columns>
241
- ): BaseTable.TableOption
386
+ ): BaseTable.TableOption<RichPrimaryKeyOptionSpec<Columns>>
242
387
  } = ((input: unknown) =>
243
388
  isObject(input) && "columns" in input
244
389
  ? BaseTable.option({
@@ -252,14 +397,14 @@ export const primaryKey: {
252
397
 
253
398
  export const unique: {
254
399
  <const Columns extends string | readonly string[]>(
255
- columns: Columns
400
+ columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
256
401
  ): BaseTable.TableOption<{
257
402
  readonly kind: "unique"
258
403
  readonly columns: BaseTable.NormalizeColumns<Columns>
259
404
  }>
260
405
  <const Columns extends string | readonly string[]>(
261
406
  spec: RichUniqueInput<Columns>
262
- ): BaseTable.TableOption
407
+ ): BaseTable.TableOption<RichUniqueOptionSpec<Columns>>
263
408
  } = ((input: unknown) =>
264
409
  isObject(input) && "columns" in input && ("name" in input || "nullsNotDistinct" in input || "deferrable" in input || "initiallyDeferred" in input)
265
410
  ? BaseTable.option({
@@ -274,30 +419,21 @@ export const unique: {
274
419
 
275
420
  export const index: {
276
421
  <const Columns extends string | readonly string[]>(
277
- columns: Columns
422
+ columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
278
423
  ): BaseTable.TableOption<{
279
424
  readonly kind: "index"
280
425
  readonly columns: BaseTable.NormalizeColumns<Columns>
281
426
  }>
282
- <Table extends SchemaTable, const Columns extends string | readonly string[]>(
283
- spec: Omit<RichIndexInput<Columns>, "predicate"> & {
427
+ <Table extends SchemaTable, const Columns extends string | readonly string[], const Spec extends Omit<RichIndexInput<Columns>, "predicate"> & {
284
428
  readonly predicate: TableExpressionFactory<Table>
285
- }
286
- ): TableScopedOptionBuilder<Table, {
287
- readonly kind: "index"
288
- readonly columns?: BaseTable.NormalizeColumns<Columns>
289
- readonly keys?: readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
290
- readonly name?: string
291
- readonly unique?: boolean
292
- readonly method?: string
293
- readonly include?: readonly string[]
294
- readonly predicate?: DdlExpressionLike
295
- }>
296
- <const Columns extends string | readonly string[]>(
297
- spec: RichIndexInput<Columns>
298
- ): BaseTable.TableOption
429
+ }>(
430
+ spec: Spec & RichIndexColumnsConstraint<Spec>
431
+ ): TableScopedOptionBuilder<Table, RichIndexOptionSpec<Spec>>
432
+ <const Columns extends string | readonly string[], const Spec extends RichIndexInput<Columns>>(
433
+ spec: Spec & RichIndexColumnsConstraint<Spec>
434
+ ): BaseTable.TableOption<RichIndexOptionSpec<Spec>>
299
435
  } = ((input: unknown) =>
300
- isObject(input) && ("keys" in input || "name" in input || "unique" in input || "method" in input || "include" in input || "predicate" in input)
436
+ isObject(input) && ("columns" in input || "keys" in input || "name" in input || "unique" in input || "method" in input || "include" in input || "predicate" in input)
301
437
  ? (() => {
302
438
  const spec = input as RichIndexInput<string | readonly string[]> & {
303
439
  readonly predicate?: DdlExpressionLike | TableExpressionFactory<SchemaTable>
@@ -333,35 +469,35 @@ export const foreignKey = <
333
469
  TargetTable extends AnyTable,
334
470
  const TargetColumns extends string | readonly string[]
335
471
  >(
336
- columnsOrSpec: LocalColumns | RichForeignKeyInput<LocalColumns, TargetTable, TargetColumns>,
472
+ columnsOrSpec: (LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>) | RichForeignKeyInput<LocalColumns, TargetTable, TargetColumns>,
337
473
  target?: () => TargetTable,
338
- referencedColumns?: TargetColumns
339
- ): BaseTable.TableOption =>
474
+ referencedColumns?: TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
475
+ ): BaseTable.TableOption<RichForeignKeyOptionSpec<LocalColumns, TargetTable, TargetColumns>> =>
340
476
  isObject(columnsOrSpec) && "columns" in columnsOrSpec && "target" in columnsOrSpec
341
477
  ? (() => {
342
478
  const spec = columnsOrSpec as RichForeignKeyInput<LocalColumns, TargetTable, TargetColumns>
343
- const targetTable = spec.target() as BaseTable.AnyTable
479
+ const targetTable = spec.target()
344
480
  const targetState = targetTable[BaseTable.TypeId]
345
481
  return BaseTable.option({
346
- kind: "foreignKey",
347
- columns: normalizeColumns(spec.columns),
348
- name: spec.name,
349
- references: () => ({
350
- tableName: targetState.baseName,
351
- schemaName: targetState.schemaName,
352
- columns: normalizeColumns(spec.referencedColumns),
353
- knownColumns: Object.keys(targetState.fields)
354
- }),
355
- onUpdate: spec.onUpdate,
356
- onDelete: spec.onDelete,
357
- deferrable: spec.deferrable,
358
- initiallyDeferred: spec.initiallyDeferred
359
- })
482
+ kind: "foreignKey",
483
+ columns: normalizeColumns(spec.columns) as BaseTable.NormalizeColumns<LocalColumns>,
484
+ name: spec.name,
485
+ references: () => ({
486
+ tableName: targetState.baseName,
487
+ schemaName: targetState.schemaName,
488
+ columns: normalizeColumns(spec.referencedColumns) as BaseTable.NormalizeColumns<TargetColumns>,
489
+ knownColumns: Object.keys(targetState.fields) as unknown as readonly ColumnNamesOfTable<TargetTable>[]
490
+ }),
491
+ onUpdate: spec.onUpdate,
492
+ onDelete: spec.onDelete,
493
+ deferrable: spec.deferrable,
494
+ initiallyDeferred: spec.initiallyDeferred
495
+ } as RichForeignKeyOptionSpec<LocalColumns, TargetTable, TargetColumns>)
360
496
  })()
361
- : BaseTable.foreignKey(
362
- columnsOrSpec as LocalColumns,
363
- target as () => BaseTable.AnyTable,
364
- referencedColumns as TargetColumns
497
+ : BaseTable.foreignKey<LocalColumns, TargetTable, TargetColumns>(
498
+ columnsOrSpec as LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>,
499
+ target as () => TargetTable,
500
+ referencedColumns as TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
365
501
  )
366
502
 
367
503
  export const check: {
@@ -25,6 +25,10 @@ type PostgresTypeNamespace = typeof postgresDatatypes & {
25
25
  readonly enum: <Kind extends string>(kind: Kind) => Expression.DbType.Enum<"postgres", Kind>
26
26
  readonly set: <Kind extends string>(kind: Kind) => Expression.DbType.Set<"postgres", Kind>
27
27
  readonly custom: <Kind extends string>(kind: Kind) => Expression.DbType.Base<"postgres", Kind>
28
+ readonly driverValueMapping: <Db extends Expression.DbType.Any>(
29
+ dbType: Db,
30
+ mapping: Expression.DriverValueMapping
31
+ ) => Db
28
32
  }
29
33
 
30
34
  /** Postgres database-type constructors for casts and typed column references. */
@@ -0,0 +1,128 @@
1
+ import * as Schema from "effect/Schema"
2
+
3
+ import * as BaseColumn from "../internal/column.js"
4
+ import { makeColumnDefinition, type AnyColumnDefinition, type ColumnDefinition } from "../internal/column-state.js"
5
+ import type * as Expression from "../internal/scalar.js"
6
+ import {
7
+ DecimalStringSchema,
8
+ LocalDateStringSchema,
9
+ LocalDateTimeStringSchema,
10
+ LocalTimeStringSchema,
11
+ type DecimalString,
12
+ type LocalDateString,
13
+ type LocalDateTimeString,
14
+ type LocalTimeString
15
+ } from "../internal/runtime/value.js"
16
+ import { sqliteDatatypes } from "./datatypes/index.js"
17
+
18
+ const enrichDbType = <Db extends Expression.DbType.Any>(dbType: Db): Db => {
19
+ const candidate = (sqliteDatatypes as unknown as Record<string, (() => Expression.DbType.Any) | undefined>)[dbType.kind]
20
+ return typeof candidate === "function"
21
+ ? { ...candidate(), ...dbType } as Db
22
+ : dbType
23
+ }
24
+
25
+ const primitive = <Type, Db extends Expression.DbType.Any>(
26
+ schema: Schema.Schema<Type, any, any>,
27
+ dbType: Db
28
+ ): ColumnDefinition<Type, Type, Type, Db, false, false, false, false, false, undefined> =>
29
+ makeColumnDefinition(schema as Schema.Schema<NonNullable<Type>>, {
30
+ dbType,
31
+ nullable: false,
32
+ hasDefault: false,
33
+ generated: false,
34
+ primaryKey: false,
35
+ unique: false,
36
+ references: undefined
37
+ })
38
+
39
+ const renderNumericDdlType = (
40
+ kind: string,
41
+ options?: BaseColumn.NumericOptions
42
+ ): string | undefined => {
43
+ if (options === undefined || options.precision === undefined) {
44
+ return undefined
45
+ }
46
+ return options.scale === undefined
47
+ ? `${kind}(${options.precision})`
48
+ : `${kind}(${options.precision},${options.scale})`
49
+ }
50
+
51
+ export const custom = <SchemaType extends Schema.Schema.Any, Db extends Expression.DbType.Any>(
52
+ schema: SchemaType,
53
+ dbType: Db
54
+ ) =>
55
+ makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
56
+ dbType: enrichDbType(dbType),
57
+ nullable: false,
58
+ hasDefault: false,
59
+ generated: false,
60
+ primaryKey: false,
61
+ unique: false,
62
+ references: undefined,
63
+ ddlType: undefined,
64
+ identity: undefined
65
+ })
66
+
67
+ export const uuid = () => primitive(Schema.UUID, sqliteDatatypes.uuid())
68
+ export const text = () => primitive(Schema.String, sqliteDatatypes.text())
69
+ export const int = () => primitive(Schema.Int, sqliteDatatypes.int())
70
+ export const number = (options?: BaseColumn.NumericOptions) =>
71
+ makeColumnDefinition(DecimalStringSchema, {
72
+ dbType: sqliteDatatypes.decimal(),
73
+ nullable: false,
74
+ hasDefault: false,
75
+ generated: false,
76
+ primaryKey: false,
77
+ unique: false,
78
+ references: undefined,
79
+ ddlType: renderNumericDdlType("decimal", options),
80
+ identity: undefined
81
+ })
82
+ export const boolean = () => primitive(Schema.Boolean, sqliteDatatypes.boolean())
83
+ export const date = () => primitive(LocalDateStringSchema, sqliteDatatypes.date())
84
+ export const time = () => primitive(LocalTimeStringSchema, sqliteDatatypes.time())
85
+ export const datetime = () => primitive(LocalDateTimeStringSchema, sqliteDatatypes.datetime())
86
+ export const timestamp = () => primitive(LocalDateTimeStringSchema, sqliteDatatypes.timestamp())
87
+ export const json = <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =>
88
+ makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
89
+ dbType: { ...sqliteDatatypes.json(), variant: "json" } as Expression.DbType.Json<"sqlite", "json">,
90
+ nullable: false,
91
+ hasDefault: false,
92
+ generated: false,
93
+ primaryKey: false,
94
+ unique: false,
95
+ references: undefined,
96
+ ddlType: undefined,
97
+ identity: undefined
98
+ })
99
+
100
+ export const nullable = BaseColumn.nullable
101
+ export const brand = BaseColumn.brand
102
+ export const primaryKey = BaseColumn.primaryKey
103
+ type UniqueColumn<Column extends AnyColumnDefinition> = ReturnType<typeof BaseColumn.unique<Column>>
104
+
105
+ type SqliteUniqueOptions = {
106
+ readonly name?: string
107
+ readonly nullsNotDistinct?: never
108
+ readonly deferrable?: never
109
+ readonly initiallyDeferred?: never
110
+ }
111
+
112
+ type UniqueModifier = {
113
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
114
+ readonly options: <const Options extends SqliteUniqueOptions>(
115
+ options: Options
116
+ ) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
117
+ }
118
+
119
+ export const unique = BaseColumn.unique as UniqueModifier
120
+ const default_ = BaseColumn.default_
121
+ export const generated = BaseColumn.generated
122
+ export const driverValueMapping = BaseColumn.driverValueMapping
123
+ export const references = BaseColumn.references
124
+ export const schema = BaseColumn.schema
125
+ export { default_ as default }
126
+
127
+ export type Any = BaseColumn.Any
128
+ export type AnyBound = BaseColumn.AnyBound
@@ -0,0 +1,79 @@
1
+ import type { DatatypeModule } from "../../internal/datatypes/define.js"
2
+ import type * as Expression from "../../internal/scalar.js"
3
+ import { sqliteDatatypeFamilies, sqliteDatatypeKinds } from "./spec.js"
4
+
5
+ const withMetadata = <Kind extends keyof typeof sqliteDatatypeKinds & string>(
6
+ kind: Kind
7
+ ): Expression.DbType.Base<"sqlite", Kind> => {
8
+ const kindSpec = sqliteDatatypeKinds[kind]
9
+ const familySpec = sqliteDatatypeFamilies[kindSpec.family as keyof typeof sqliteDatatypeFamilies]
10
+ return {
11
+ dialect: "sqlite",
12
+ kind,
13
+ family: kindSpec.family,
14
+ runtime: kindSpec.runtime,
15
+ compareGroup: familySpec?.compareGroup,
16
+ castTargets: familySpec?.castTargets,
17
+ traits: familySpec?.traits
18
+ }
19
+ }
20
+
21
+ const sqliteDatatypeModule = {
22
+ custom: (kind: string) => ({
23
+ dialect: "sqlite",
24
+ kind
25
+ }),
26
+ uuid: () => ({
27
+ dialect: "sqlite",
28
+ kind: "uuid",
29
+ family: "uuid",
30
+ runtime: "string",
31
+ compareGroup: "uuid",
32
+ castTargets: ["uuid", "char", "varchar", "text"],
33
+ traits: {
34
+ textual: true
35
+ }
36
+ })
37
+ } as Record<string, (...args: readonly any[]) => Expression.DbType.Base<"sqlite", string>>
38
+
39
+ for (const kind of Object.keys(sqliteDatatypeKinds)) {
40
+ sqliteDatatypeModule[kind] = () => withMetadata(kind as keyof typeof sqliteDatatypeKinds & string)
41
+ }
42
+
43
+ type SqliteUuidWitness = Expression.DbType.Base<"sqlite", "uuid"> & {
44
+ readonly family: "uuid"
45
+ readonly runtime: "string"
46
+ readonly compareGroup: "uuid"
47
+ readonly castTargets: readonly ["uuid", "char", "varchar", "text"]
48
+ readonly traits: {
49
+ readonly textual: true
50
+ }
51
+ }
52
+
53
+ type SqliteJsonWitness = Expression.DbType.Base<"sqlite", "json"> & {
54
+ readonly family: "json"
55
+ readonly runtime: "json"
56
+ readonly compareGroup: "json"
57
+ readonly castTargets: readonly ["json", "text"]
58
+ readonly driverValueMapping: {
59
+ readonly toDriver: (value: unknown) => unknown
60
+ }
61
+ }
62
+
63
+ sqliteDatatypeModule.json = () => ({
64
+ ...withMetadata("json"),
65
+ driverValueMapping: {
66
+ toDriver: (value: unknown) => JSON.stringify(value)
67
+ }
68
+ }) as SqliteJsonWitness
69
+
70
+ export const sqliteDatatypes = sqliteDatatypeModule as DatatypeModule<
71
+ "sqlite",
72
+ typeof sqliteDatatypeKinds,
73
+ typeof sqliteDatatypeFamilies
74
+ > & {
75
+ readonly uuid: () => SqliteUuidWitness
76
+ readonly json: () => SqliteJsonWitness
77
+ }
78
+
79
+ export type SqliteDatatypeModule = typeof sqliteDatatypes
@@ -0,0 +1,98 @@
1
+ import type { DatatypeFamilySpec, DatatypeKindSpec } from "../../internal/datatypes/shape.js"
2
+
3
+ export const sqliteDatatypeFamilies = {
4
+ text: {
5
+ compareGroup: "text",
6
+ castTargets: ["text", "numeric", "integer", "real", "boolean", "date", "time", "datetime", "json", "blob", "null"],
7
+ traits: {
8
+ textual: true,
9
+ ordered: true
10
+ }
11
+ },
12
+ numeric: {
13
+ compareGroup: "numeric",
14
+ castTargets: ["numeric", "integer", "real", "text", "boolean", "date", "time", "datetime"],
15
+ traits: {
16
+ ordered: true
17
+ }
18
+ },
19
+ integer: {
20
+ compareGroup: "numeric",
21
+ castTargets: ["integer", "numeric", "real", "text", "boolean", "date", "time", "datetime"],
22
+ traits: {
23
+ ordered: true
24
+ }
25
+ },
26
+ real: {
27
+ compareGroup: "numeric",
28
+ castTargets: ["real", "numeric", "integer", "text", "boolean"],
29
+ traits: {
30
+ ordered: true
31
+ }
32
+ },
33
+ boolean: {
34
+ compareGroup: "boolean",
35
+ castTargets: ["boolean", "integer", "numeric", "text"],
36
+ traits: {}
37
+ },
38
+ date: {
39
+ compareGroup: "date",
40
+ castTargets: ["date", "time", "datetime", "text", "numeric", "integer"],
41
+ traits: {
42
+ ordered: true
43
+ }
44
+ },
45
+ time: {
46
+ compareGroup: "time",
47
+ castTargets: ["time", "date", "datetime", "text", "numeric", "integer"],
48
+ traits: {
49
+ ordered: true
50
+ }
51
+ },
52
+ datetime: {
53
+ compareGroup: "datetime",
54
+ castTargets: ["datetime", "date", "time", "text", "numeric", "integer"],
55
+ traits: {
56
+ ordered: true
57
+ }
58
+ },
59
+ json: {
60
+ compareGroup: "json",
61
+ castTargets: ["json", "text"],
62
+ traits: {}
63
+ },
64
+ blob: {
65
+ compareGroup: "blob",
66
+ castTargets: ["blob", "text"],
67
+ traits: {}
68
+ },
69
+ null: {
70
+ compareGroup: "null",
71
+ castTargets: ["text", "numeric", "integer", "real", "boolean", "date", "time", "datetime", "json", "blob", "null"],
72
+ traits: {}
73
+ }
74
+ } as const satisfies Record<string, DatatypeFamilySpec>
75
+
76
+ export const sqliteDatatypeKinds = {
77
+ text: { family: "text", runtime: "string" },
78
+ varchar: { family: "text", runtime: "string" },
79
+ char: { family: "text", runtime: "string" },
80
+ clob: { family: "text", runtime: "string" },
81
+ int: { family: "integer", runtime: "number" },
82
+ integer: { family: "integer", runtime: "number" },
83
+ bigint: { family: "integer", runtime: "bigintString" },
84
+ numeric: { family: "numeric", runtime: "decimalString" },
85
+ decimal: { family: "numeric", runtime: "decimalString" },
86
+ real: { family: "real", runtime: "number" },
87
+ double: { family: "real", runtime: "number" },
88
+ boolean: { family: "boolean", runtime: "boolean" },
89
+ date: { family: "date", runtime: "localDate" },
90
+ time: { family: "time", runtime: "localTime" },
91
+ datetime: { family: "datetime", runtime: "localDateTime" },
92
+ timestamp: { family: "datetime", runtime: "localDateTime" },
93
+ json: { family: "json", runtime: "json" },
94
+ blob: { family: "blob", runtime: "bytes" }
95
+ } as const satisfies Record<string, DatatypeKindSpec>
96
+
97
+ export type SqliteDatatypeFamily = keyof typeof sqliteDatatypeFamilies
98
+ export type SqliteDatatypeKind = keyof typeof sqliteDatatypeKinds