effect-qb 0.16.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 (75) hide show
  1. package/dist/mysql.js +1661 -591
  2. package/dist/postgres/metadata.js +1930 -135
  3. package/dist/postgres.js +7808 -6718
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +6 -1
  6. package/src/internal/derived-table.ts +29 -3
  7. package/src/internal/dialect.ts +2 -0
  8. package/src/internal/dsl-mutation-runtime.ts +173 -4
  9. package/src/internal/dsl-plan-runtime.ts +165 -20
  10. package/src/internal/dsl-query-runtime.ts +60 -6
  11. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  12. package/src/internal/executor.ts +47 -9
  13. package/src/internal/expression-ast.ts +3 -2
  14. package/src/internal/grouping-key.ts +141 -1
  15. package/src/internal/implication-runtime.ts +2 -1
  16. package/src/internal/json/types.ts +155 -40
  17. package/src/internal/predicate/context.ts +14 -1
  18. package/src/internal/predicate/key.ts +19 -2
  19. package/src/internal/predicate/runtime.ts +27 -3
  20. package/src/internal/query.ts +252 -30
  21. package/src/internal/renderer.ts +35 -2
  22. package/src/internal/runtime/driver-value-mapping.ts +58 -0
  23. package/src/internal/runtime/normalize.ts +62 -38
  24. package/src/internal/runtime/schema.ts +5 -3
  25. package/src/internal/runtime/value.ts +153 -30
  26. package/src/internal/table-options.ts +108 -1
  27. package/src/internal/table.ts +87 -29
  28. package/src/mysql/column.ts +18 -2
  29. package/src/mysql/datatypes/index.ts +21 -0
  30. package/src/mysql/errors/catalog.ts +5 -5
  31. package/src/mysql/errors/normalize.ts +2 -2
  32. package/src/mysql/internal/dsl.ts +736 -218
  33. package/src/mysql/internal/renderer.ts +2 -1
  34. package/src/mysql/internal/sql-expression-renderer.ts +486 -130
  35. package/src/mysql/query.ts +9 -2
  36. package/src/mysql/table.ts +38 -12
  37. package/src/postgres/column.ts +4 -2
  38. package/src/postgres/errors/normalize.ts +2 -2
  39. package/src/postgres/executor.ts +48 -5
  40. package/src/postgres/function/core.ts +19 -1
  41. package/src/postgres/internal/dsl.ts +683 -240
  42. package/src/postgres/internal/renderer.ts +2 -1
  43. package/src/postgres/internal/schema-ddl.ts +2 -1
  44. package/src/postgres/internal/schema-model.ts +6 -3
  45. package/src/postgres/internal/sql-expression-renderer.ts +420 -91
  46. package/src/postgres/json.ts +57 -17
  47. package/src/postgres/query.ts +9 -2
  48. package/src/postgres/schema-management.ts +91 -4
  49. package/src/postgres/schema.ts +1 -1
  50. package/src/postgres/table.ts +189 -53
  51. package/src/sqlite/column.ts +128 -0
  52. package/src/sqlite/datatypes/index.ts +79 -0
  53. package/src/sqlite/datatypes/spec.ts +98 -0
  54. package/src/sqlite/errors/catalog.ts +103 -0
  55. package/src/sqlite/errors/fields.ts +19 -0
  56. package/src/sqlite/errors/index.ts +19 -0
  57. package/src/sqlite/errors/normalize.ts +229 -0
  58. package/src/sqlite/errors/requirements.ts +71 -0
  59. package/src/sqlite/errors/types.ts +29 -0
  60. package/src/sqlite/executor.ts +227 -0
  61. package/src/sqlite/function/aggregate.ts +2 -0
  62. package/src/sqlite/function/core.ts +2 -0
  63. package/src/sqlite/function/index.ts +19 -0
  64. package/src/sqlite/function/string.ts +2 -0
  65. package/src/sqlite/function/temporal.ts +100 -0
  66. package/src/sqlite/function/window.ts +2 -0
  67. package/src/sqlite/internal/dialect.ts +37 -0
  68. package/src/sqlite/internal/dsl.ts +6926 -0
  69. package/src/sqlite/internal/renderer.ts +47 -0
  70. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  71. package/src/sqlite/json.ts +2 -0
  72. package/src/sqlite/query.ts +196 -0
  73. package/src/sqlite/renderer.ts +24 -0
  74. package/src/sqlite/table.ts +183 -0
  75. package/src/sqlite.ts +22 -0
@@ -12,9 +12,13 @@ import {
12
12
  resolvePrimaryKeyColumns,
13
13
  type DdlExpressionLike,
14
14
  type IndexKeySpec,
15
+ type MatchingColumnArityInput,
16
+ type NonEmptyColumnInput,
15
17
  type NormalizeColumns,
16
18
  type ReferentialAction,
17
19
  type TableOptionSpec,
20
+ type ValidateForeignKeyOptionColumns,
21
+ type ValidateIndexOptionColumns,
18
22
  type ValidateKnownColumns,
19
23
  type ValidatePrimaryKeyColumns,
20
24
  validateOptions
@@ -44,18 +48,32 @@ type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
44
48
  type TableDialect<Fields extends TableFieldMap> = Fields[keyof Fields][typeof import("./column-state.js").ColumnTypeId]["dbType"]["dialect"]
45
49
  type TableKind = "schema" | "alias"
46
50
  type DefaultSchemaName = "public"
47
- type ClassOptionSpec = Exclude<TableOptionSpec, { readonly kind: "primaryKey" }>
51
+ type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
52
+ type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
53
+ type FieldIndexKeySpec<Fields extends TableFieldMap> =
54
+ | (Extract<IndexKeySpec, { readonly kind: "column" }> & { readonly column: FieldColumnName<Fields> })
55
+ | Extract<IndexKeySpec, { readonly kind: "expression" }>
56
+ type ClassOptionSpec<Fields extends TableFieldMap = TableFieldMap> =
57
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "index" }>, "columns" | "include" | "keys"> & {
58
+ readonly columns?: FieldColumnList<Fields>
59
+ readonly include?: readonly FieldColumnName<Fields>[]
60
+ readonly keys?: readonly [FieldIndexKeySpec<Fields>, ...FieldIndexKeySpec<Fields>[]]
61
+ })
62
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "unique" }>, "columns"> & {
63
+ readonly columns: FieldColumnList<Fields>
64
+ })
65
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "foreignKey" }>, "columns"> & {
66
+ readonly columns: FieldColumnList<Fields>
67
+ })
68
+ | Extract<TableOptionSpec, { readonly kind: "check" }>
48
69
  interface TableOptionBuilderLike<
49
70
  Spec extends TableOptionSpec = TableOptionSpec
50
71
  > {
51
- (
52
- table: TableDefinition<any, any, any, "schema", any>
53
- ): TableDefinition<any, any, any, "schema", any>
54
72
  readonly option: Spec
55
73
  }
56
74
 
57
- type ClassTableOption = TableOptionBuilderLike<ClassOptionSpec>
58
- type ClassDeclaredTableOptions = readonly ClassTableOption[]
75
+ type ClassTableOption<Fields extends TableFieldMap> = TableOptionBuilderLike<ClassOptionSpec<Fields>>
76
+ type ClassDeclaredTableOptions<Fields extends TableFieldMap> = readonly ClassTableOption<Fields>[]
59
77
 
60
78
  type BuildPrimaryKey<
61
79
  Table extends TableDefinition<any, any, any, "schema", any>,
@@ -69,9 +87,13 @@ type OptionInputTable<
69
87
  Spec extends TableOptionSpec
70
88
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
71
89
  ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
72
- : Spec extends { readonly columns: infer Columns extends readonly string[] }
73
- ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
74
- : Table
90
+ : Spec extends { readonly kind: "index" }
91
+ ? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
92
+ : Spec extends { readonly kind: "foreignKey" }
93
+ ? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
94
+ : Spec extends { readonly columns: infer Columns extends readonly string[] }
95
+ ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
96
+ : Table
75
97
 
76
98
  type ApplyOption<
77
99
  Table extends TableDefinition<any, any, any, "schema", any>,
@@ -90,6 +112,26 @@ type ApplyOption<
90
112
  "schema"
91
113
  >
92
114
 
115
+ export type ValidateDeclaredOptions<
116
+ Table extends TableDefinition<any, any, any, "schema", any>,
117
+ Options extends DeclaredTableOptions
118
+ > = {
119
+ readonly [K in keyof Options]: Options[K] extends TableOptionBuilderLike<infer Spec>
120
+ ? OptionInputTable<Table, Spec> extends never ? never : Options[K]
121
+ : never
122
+ }
123
+
124
+ export type ApplyDeclaredOptions<
125
+ Table extends TableDefinition<any, any, any, "schema", any>,
126
+ Options extends DeclaredTableOptions
127
+ > = Options extends readonly [infer Head, ...infer Tail]
128
+ ? Head extends TableOptionBuilderLike<infer Spec>
129
+ ? Tail extends DeclaredTableOptions
130
+ ? ApplyDeclaredOptions<ApplyOption<Table, Spec>, Tail>
131
+ : ApplyOption<Table, Spec>
132
+ : Table
133
+ : Table
134
+
93
135
  export type MissingSelfGeneric = "Missing `Self` generic - use `class Self extends Table.Class<Self>(...) {}`"
94
136
 
95
137
  /** Bound columns keyed by field name for a particular table. */
@@ -132,16 +174,17 @@ export interface TableSchemaNamespace<SchemaName extends string> {
132
174
  readonly table: <
133
175
  Name extends string,
134
176
  Fields extends TableFieldMap,
177
+ const Options extends DeclaredTableOptions,
135
178
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
136
179
  >(
137
180
  name: Name,
138
181
  fields: Fields,
139
- ...options: DeclaredTableOptions
140
- ) => TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
182
+ ...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
183
+ ) => ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
141
184
  }
142
185
 
143
186
  export type DeclaredTableOptions = readonly TableOptionBuilderLike[]
144
- export type { DdlExpressionLike, IndexKeySpec, NormalizeColumns, ReferentialAction } from "./table-options.js"
187
+ export type { DdlExpressionLike, IndexKeySpec, MatchingColumnArityInput, NonEmptyColumnInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
145
188
 
146
189
  export type TableDefinition<
147
190
  Name extends string,
@@ -192,7 +235,7 @@ export type TableClassStatic<
192
235
  >
193
236
  readonly [OptionsSymbol]: readonly TableOptionSpec[]
194
237
  readonly [DeclaredOptionsSymbol]?: readonly TableOptionSpec[]
195
- readonly [options]?: ClassDeclaredTableOptions
238
+ readonly [options]?: ClassDeclaredTableOptions<Fields>
196
239
  readonly tableName: Name
197
240
  } & BoundColumns<Name, Fields> & Plan.RowSet<
198
241
  BoundColumns<Name, Fields>,
@@ -204,6 +247,14 @@ export type TableClassStatic<
204
247
  /** Minimal structural table-like contract used across helper APIs. */
205
248
  export type AnyTable = TableDefinition<any, any, any, any, any> | TableClassStatic<any, any, any, any>
206
249
 
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
255
+
256
+ type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
257
+
207
258
  /** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
208
259
  export type TableOption<
209
260
  Spec extends TableOptionSpec = TableOptionSpec
@@ -341,7 +392,10 @@ const applyDeclaredOptions = <
341
392
  return table
342
393
  }
343
394
  return declaredOptions.reduce<TableDefinition<any, any, any, "schema", any>>(
344
- (current, option) => option(current),
395
+ (current, option) =>
396
+ (option as unknown as (
397
+ table: TableDefinition<any, any, any, "schema", any>
398
+ ) => TableDefinition<any, any, any, "schema", any>)(current),
345
399
  table
346
400
  ) as unknown as Table
347
401
  }
@@ -491,17 +545,17 @@ export function make<
491
545
  */
492
546
  export const schema = <SchemaName extends string>(
493
547
  schemaName: SchemaName
494
- ): TableSchemaNamespace<SchemaName> => ({
495
- schemaName,
496
- table: <
548
+ ): TableSchemaNamespace<SchemaName> => {
549
+ const table = <
497
550
  Name extends string,
498
551
  Fields extends TableFieldMap,
552
+ const Options extends DeclaredTableOptions,
499
553
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
500
554
  >(
501
555
  name: Name,
502
556
  fields: Fields,
503
- ...options: DeclaredTableOptions
504
- ): TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName> =>
557
+ ...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
558
+ ): ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options> =>
505
559
  applyDeclaredOptions(
506
560
  makeTable(
507
561
  name,
@@ -512,9 +566,13 @@ export const schema = <SchemaName extends string>(
512
566
  schemaName,
513
567
  "explicit"
514
568
  ) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
515
- options
516
- )
517
- })
569
+ options as unknown as Options
570
+ ) as ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
571
+ return {
572
+ schemaName,
573
+ table
574
+ } as unknown as TableSchemaNamespace<SchemaName>
575
+ }
518
576
 
519
577
  /**
520
578
  * Creates an aliased source from an existing table definition.
@@ -664,7 +722,7 @@ export function Class<
664
722
  export const primaryKey = <
665
723
  const Columns extends string | readonly string[]
666
724
  >(
667
- columns: Columns
725
+ columns: Columns & NonEmptyColumnInput<Columns>
668
726
  ): TableOption<{
669
727
  readonly kind: "primaryKey"
670
728
  readonly columns: NormalizeColumns<Columns>
@@ -677,7 +735,7 @@ export const primaryKey = <
677
735
  export const unique = <
678
736
  const Columns extends string | readonly string[]
679
737
  >(
680
- columns: Columns
738
+ columns: Columns & NonEmptyColumnInput<Columns>
681
739
  ): TableOption<{
682
740
  readonly kind: "unique"
683
741
  readonly columns: NormalizeColumns<Columns>
@@ -690,7 +748,7 @@ export const unique = <
690
748
  export const index = <
691
749
  const Columns extends string | readonly string[]
692
750
  >(
693
- columns: Columns
751
+ columns: Columns & NonEmptyColumnInput<Columns>
694
752
  ): TableOption<{
695
753
  readonly kind: "index"
696
754
  readonly columns: NormalizeColumns<Columns>
@@ -705,9 +763,9 @@ export const foreignKey = <
705
763
  TargetTable extends AnyTable,
706
764
  const TargetColumns extends string | readonly string[]
707
765
  >(
708
- columns: LocalColumns,
766
+ columns: LocalColumns & NonEmptyColumnInput<LocalColumns>,
709
767
  target: () => TargetTable,
710
- referencedColumns: TargetColumns
768
+ referencedColumns: TargetColumns & NonEmptyColumnInput<TargetColumns> & MatchingColumnArityInput<LocalColumns, TargetColumns>
711
769
  ): TableOption<{
712
770
  readonly kind: "foreignKey"
713
771
  readonly columns: NormalizeColumns<LocalColumns>
@@ -715,7 +773,7 @@ export const foreignKey = <
715
773
  readonly tableName: string
716
774
  readonly schemaName?: string
717
775
  readonly columns: NormalizeColumns<TargetColumns>
718
- readonly knownColumns: readonly string[]
776
+ readonly knownColumns: readonly ColumnNamesOfAnyTable<TargetTable>[]
719
777
  }
720
778
  }> => makeOption({
721
779
  kind: "foreignKey",
@@ -724,7 +782,7 @@ export const foreignKey = <
724
782
  tableName: target()[TypeId].baseName,
725
783
  schemaName: target()[TypeId].schemaName,
726
784
  columns: normalizeColumnList(referencedColumns) as NormalizeColumns<TargetColumns>,
727
- knownColumns: Object.keys(target()[TypeId].fields)
785
+ knownColumns: Object.keys(target()[TypeId].fields) as unknown as readonly ColumnNamesOfAnyTable<TargetTable>[]
728
786
  })
729
787
  })
730
788
 
@@ -1,7 +1,7 @@
1
1
  import * as Schema from "effect/Schema"
2
2
 
3
3
  import * as BaseColumn from "../internal/column.js"
4
- import { makeColumnDefinition, type ColumnDefinition } from "../internal/column-state.js"
4
+ import { makeColumnDefinition, type AnyColumnDefinition, type ColumnDefinition } from "../internal/column-state.js"
5
5
  import type * as Expression from "../internal/scalar.js"
6
6
  import {
7
7
  DecimalStringSchema,
@@ -97,7 +97,23 @@ export const json = <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =
97
97
  export const nullable = BaseColumn.nullable
98
98
  export const brand = BaseColumn.brand
99
99
  export const primaryKey = BaseColumn.primaryKey
100
- export const unique = BaseColumn.unique
100
+ type UniqueColumn<Column extends AnyColumnDefinition> = ReturnType<typeof BaseColumn.unique<Column>>
101
+
102
+ type MysqlUniqueOptions = {
103
+ readonly name?: string
104
+ readonly nullsNotDistinct?: never
105
+ readonly deferrable?: never
106
+ readonly initiallyDeferred?: never
107
+ }
108
+
109
+ type UniqueModifier = {
110
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
111
+ readonly options: <const Options extends MysqlUniqueOptions>(
112
+ options: Options
113
+ ) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
114
+ }
115
+
116
+ export const unique = BaseColumn.unique as UniqueModifier
101
117
  const default_ = BaseColumn.default_
102
118
  export const generated = BaseColumn.generated
103
119
  export const driverValueMapping = BaseColumn.driverValueMapping
@@ -50,12 +50,33 @@ type MysqlUuidWitness = Expression.DbType.Base<"mysql", "uuid"> & {
50
50
  }
51
51
  }
52
52
 
53
+ type MysqlJsonWitness = Expression.DbType.Base<"mysql", "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
+ mysqlDatatypeModule.json = () => ({
64
+ ...withMetadata("json"),
65
+ driverValueMapping: {
66
+ toDriver: (value: unknown) =>
67
+ value !== null && typeof value === "object"
68
+ ? JSON.stringify(value)
69
+ : value
70
+ }
71
+ }) as MysqlJsonWitness
72
+
53
73
  export const mysqlDatatypes = mysqlDatatypeModule as DatatypeModule<
54
74
  "mysql",
55
75
  typeof mysqlDatatypeKinds,
56
76
  typeof mysqlDatatypeFamilies
57
77
  > & {
58
78
  readonly uuid: () => MysqlUuidWitness
79
+ readonly json: () => MysqlJsonWitness
59
80
  }
60
81
 
61
82
  export type MysqlDatatypeModule = typeof mysqlDatatypes
@@ -51636,17 +51636,17 @@ export const mysqlErrorCatalogByNumber = {
51636
51636
  "MY-015153": [mysqlErrorCatalogBySymbol["ER_WARN_AUDIT_LOG_FILTER_RECOVERY_LOGGING_DISABLED_LOG"]!],
51637
51637
  } as const
51638
51638
 
51639
- const mysqlSymbolPattern = /^(?:[A-Z][A-Z0-9_]*|MY-\d+)$/
51640
- const mysqlNumberPattern = /^(?:\d+|MY-\d+)$/
51641
-
51642
51639
  export type MysqlErrorSymbol = keyof typeof mysqlErrorCatalogBySymbol
51643
51640
  export type MysqlErrorDescriptor<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = (typeof mysqlErrorCatalogBySymbol)[Symbol]
51644
51641
  export type MysqlErrorNumber = keyof typeof mysqlErrorCatalogByNumber
51645
51642
  export type MysqlErrorTag<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = MysqlErrorDescriptor<Symbol>["tag"]
51646
51643
  export type MysqlErrorDescriptorsByNumber<Number extends MysqlErrorNumber = MysqlErrorNumber> = (typeof mysqlErrorCatalogByNumber)[Number]
51647
51644
 
51648
- export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol => mysqlSymbolPattern.test(value)
51649
- export const isMysqlErrorNumber = (value: string): value is MysqlErrorNumber => mysqlNumberPattern.test(value)
51645
+ export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol =>
51646
+ value in mysqlErrorCatalogBySymbol
51647
+
51648
+ export const isMysqlErrorNumber = (value: string): value is MysqlErrorNumber =>
51649
+ value in mysqlErrorCatalogByNumber
51650
51650
 
51651
51651
  export const getMysqlErrorDescriptor = <Symbol extends MysqlErrorSymbol>(symbol: Symbol): MysqlErrorDescriptor<Symbol> =>
51652
51652
  mysqlErrorCatalogBySymbol[symbol]
@@ -48,8 +48,8 @@ const asNumber = (value: unknown): number | undefined => {
48
48
  if (typeof value === "number" && Number.isFinite(value)) {
49
49
  return value
50
50
  }
51
- if (typeof value === "string" && value.trim() !== "") {
52
- const parsed = Number(value)
51
+ if (typeof value === "string" && /^[+-]?\d+$/.test(value.trim())) {
52
+ const parsed = Number(value.trim())
53
53
  return Number.isFinite(parsed) ? parsed : undefined
54
54
  }
55
55
  return undefined