effect-qb 4.0.0-beta.66 → 4.0.0-beta.98

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 (129) hide show
  1. package/README.md +5 -2
  2. package/dist/index.js +9376 -0
  3. package/dist/mysql.js +3921 -2573
  4. package/dist/postgres/metadata.js +2491 -1373
  5. package/dist/postgres.js +5453 -5155
  6. package/dist/sqlite.js +6895 -5529
  7. package/dist/standard.js +9330 -0
  8. package/package.json +9 -2
  9. package/src/casing.ts +71 -0
  10. package/src/index.ts +2 -0
  11. package/src/internal/casing.ts +89 -0
  12. package/src/internal/coercion/rules.ts +13 -1
  13. package/src/internal/column-state.ts +21 -15
  14. package/src/internal/column.ts +44 -7
  15. package/src/internal/datatypes/define.ts +7 -1
  16. package/src/internal/datatypes/enrich.ts +23 -0
  17. package/src/internal/datatypes/lookup.ts +81 -25
  18. package/src/internal/datatypes/matrix.ts +903 -0
  19. package/src/internal/datatypes/shape.ts +2 -0
  20. package/src/internal/derived-table.ts +4 -36
  21. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +552 -361
  22. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +657 -400
  23. package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +505 -347
  24. package/src/internal/dialect.ts +35 -0
  25. package/src/internal/dsl-mutation-runtime.ts +12 -162
  26. package/src/internal/dsl-plan-runtime.ts +10 -138
  27. package/src/internal/dsl-query-runtime.ts +5 -79
  28. package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
  29. package/src/internal/executor.ts +14 -16
  30. package/src/internal/grouping-key.ts +87 -20
  31. package/src/internal/implication-runtime.ts +1 -1
  32. package/src/internal/json/path-access.ts +351 -0
  33. package/src/internal/predicate/runtime.ts +3 -0
  34. package/src/internal/query.d.ts +38 -11
  35. package/src/internal/query.ts +64 -25
  36. package/src/internal/renderer.ts +26 -14
  37. package/src/internal/runtime/normalize.ts +12 -5
  38. package/src/internal/scalar.ts +7 -1
  39. package/src/internal/schema-derivation.d.ts +7 -7
  40. package/src/internal/schema-derivation.ts +9 -9
  41. package/src/internal/schema-expression.ts +2 -2
  42. package/src/internal/sql-expression-renderer.ts +19 -0
  43. package/src/internal/standard-dsl.ts +6978 -0
  44. package/src/internal/table-options.ts +126 -66
  45. package/src/internal/table.ts +652 -219
  46. package/src/mysql/column-extension.ts +3 -0
  47. package/src/mysql/column.ts +8 -9
  48. package/src/mysql/datatypes/index.ts +4 -2
  49. package/src/mysql/datatypes/spec.ts +6 -176
  50. package/src/mysql/errors/normalize.ts +0 -1
  51. package/src/mysql/executor.ts +7 -7
  52. package/src/mysql/internal/dialect.ts +9 -4
  53. package/src/mysql/internal/dsl.ts +312 -154
  54. package/src/mysql/internal/renderer.ts +6 -2
  55. package/src/mysql/json.ts +7 -2
  56. package/src/mysql/query-extension.ts +16 -0
  57. package/src/mysql/renderer.ts +37 -3
  58. package/src/mysql/type.ts +60 -0
  59. package/src/mysql.ts +7 -13
  60. package/src/postgres/check.ts +1 -0
  61. package/src/postgres/column-extension.ts +28 -0
  62. package/src/postgres/column.ts +2 -8
  63. package/src/postgres/datatypes/index.d.ts +2 -1
  64. package/src/postgres/datatypes/index.ts +4 -2
  65. package/src/postgres/datatypes/spec.ts +6 -260
  66. package/src/postgres/errors/normalize.ts +0 -1
  67. package/src/postgres/executor.ts +7 -7
  68. package/src/postgres/foreign-key.ts +24 -0
  69. package/src/postgres/function/core.ts +1 -3
  70. package/src/postgres/function/index.ts +1 -17
  71. package/src/postgres/index.ts +1 -0
  72. package/src/postgres/internal/dialect.ts +9 -4
  73. package/src/postgres/internal/dsl.ts +306 -163
  74. package/src/postgres/internal/renderer.ts +6 -2
  75. package/src/postgres/internal/schema-ddl.ts +22 -10
  76. package/src/postgres/internal/schema-model.ts +238 -7
  77. package/src/postgres/json-extension.ts +7 -0
  78. package/src/postgres/json.ts +762 -173
  79. package/src/postgres/jsonb.ts +37 -0
  80. package/src/postgres/primary-key.ts +24 -0
  81. package/src/postgres/query-extension.ts +2 -0
  82. package/src/postgres/renderer.ts +37 -3
  83. package/src/postgres/schema-management.ts +12 -11
  84. package/src/postgres/schema.ts +106 -15
  85. package/src/postgres/table.ts +205 -530
  86. package/src/postgres/type.ts +93 -10
  87. package/src/postgres/unique.ts +32 -0
  88. package/src/postgres.ts +20 -16
  89. package/src/sqlite/column-extension.ts +3 -0
  90. package/src/sqlite/column.ts +8 -9
  91. package/src/sqlite/datatypes/index.ts +4 -2
  92. package/src/sqlite/datatypes/spec.ts +6 -94
  93. package/src/sqlite/errors/normalize.ts +0 -1
  94. package/src/sqlite/executor.ts +7 -7
  95. package/src/sqlite/internal/dialect.ts +9 -4
  96. package/src/sqlite/internal/dsl.ts +301 -154
  97. package/src/sqlite/internal/renderer.ts +6 -2
  98. package/src/sqlite/json.ts +8 -2
  99. package/src/sqlite/query-extension.ts +2 -0
  100. package/src/sqlite/renderer.ts +37 -3
  101. package/src/sqlite/type.ts +40 -0
  102. package/src/sqlite.ts +7 -13
  103. package/src/standard/cast.ts +113 -0
  104. package/src/standard/check.ts +17 -0
  105. package/src/standard/column.ts +163 -0
  106. package/src/standard/datatypes/index.ts +83 -0
  107. package/src/standard/datatypes/spec.ts +12 -0
  108. package/src/standard/dialect.ts +40 -0
  109. package/src/standard/foreign-key.ts +37 -0
  110. package/src/standard/function/aggregate.ts +2 -0
  111. package/src/standard/function/core.ts +2 -0
  112. package/src/standard/function/index.ts +18 -0
  113. package/src/standard/function/string.ts +2 -0
  114. package/src/standard/function/temporal.ts +78 -0
  115. package/src/standard/function/window.ts +2 -0
  116. package/src/standard/index.ts +17 -0
  117. package/src/standard/internal/renderer.ts +45 -0
  118. package/src/standard/json.ts +883 -0
  119. package/src/standard/primary-key.ts +17 -0
  120. package/src/standard/query.ts +152 -0
  121. package/src/standard/renderer.ts +49 -0
  122. package/src/standard/table.ts +151 -0
  123. package/src/standard/unique.ts +17 -0
  124. package/src/standard.ts +32 -0
  125. package/src/internal/aggregation-validation.ts +0 -57
  126. package/src/internal/table.d.ts +0 -180
  127. package/src/mysql/table.ts +0 -186
  128. package/src/postgres/cast.ts +0 -45
  129. package/src/sqlite/table.ts +0 -175
@@ -4,7 +4,10 @@ import {
4
4
  type AnyColumnDefinition,
5
5
  type IsNullable
6
6
  } from "./column-state.js"
7
+ import type * as Casing from "./casing.js"
8
+ import * as Expression from "./scalar.js"
7
9
  import type { Any as AnyExpression } from "./scalar.js"
10
+ import * as SchemaExpression from "./schema-expression.js"
8
11
  import type { Any as AnySchemaExpression } from "./schema-expression.js"
9
12
  import type { TableFieldMap } from "./schema-derivation.js"
10
13
 
@@ -39,6 +42,27 @@ const validateReferentialAction = (action: unknown): void => {
39
42
  }
40
43
  }
41
44
 
45
+ const requireColumnArray = (
46
+ value: unknown,
47
+ message: string
48
+ ): readonly string[] => {
49
+ if (!Array.isArray(value) || value.some((column) => typeof column !== "string" || column.length === 0)) {
50
+ throw new Error(message)
51
+ }
52
+ return value
53
+ }
54
+
55
+ const requireOptionalColumnArray = (
56
+ value: unknown,
57
+ message: string
58
+ ): readonly string[] =>
59
+ value === undefined ? [] : requireColumnArray(value, message)
60
+
61
+ const isDdlExpressionLike = (value: unknown): value is DdlExpressionLike =>
62
+ typeof value === "object" &&
63
+ value !== null &&
64
+ (Expression.TypeId in value || SchemaExpression.TypeId in value)
65
+
42
66
  export type IndexKeySpec =
43
67
  | {
44
68
  readonly kind: "column"
@@ -91,6 +115,7 @@ export type TableOptionSpec =
91
115
  readonly references: () => {
92
116
  readonly tableName: string
93
117
  readonly schemaName?: string
118
+ readonly casing?: Casing.Options
94
119
  readonly columns: ColumnList
95
120
  readonly knownColumns?: readonly string[]
96
121
  }
@@ -134,6 +159,83 @@ type TupleFromColumns<Columns> = Columns extends readonly [infer Head extends st
134
159
  export type NonEmptyColumnInput<Columns extends string | readonly string[]> =
135
160
  TupleFromColumns<Columns> extends never ? never : Columns
136
161
 
162
+ export type NonEmptyStringInput<Value extends string> =
163
+ string extends Value ? Value : Value extends "" ? never : Value
164
+
165
+ export type LiteralStringInput<Value extends string> =
166
+ string extends Value ? never : NonEmptyStringInput<Value>
167
+
168
+ type LowerAlpha =
169
+ | "a"
170
+ | "b"
171
+ | "c"
172
+ | "d"
173
+ | "e"
174
+ | "f"
175
+ | "g"
176
+ | "h"
177
+ | "i"
178
+ | "j"
179
+ | "k"
180
+ | "l"
181
+ | "m"
182
+ | "n"
183
+ | "o"
184
+ | "p"
185
+ | "q"
186
+ | "r"
187
+ | "s"
188
+ | "t"
189
+ | "u"
190
+ | "v"
191
+ | "w"
192
+ | "x"
193
+ | "y"
194
+ | "z"
195
+ type UpperAlpha = Uppercase<LowerAlpha>
196
+ type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
197
+ type IdentifierStart = LowerAlpha | UpperAlpha | "_"
198
+ type IdentifierRest = IdentifierStart | Digit
199
+
200
+ type SafeIdentifierRest<Value extends string> =
201
+ Value extends ""
202
+ ? Value
203
+ : Value extends `${infer Head}${infer Tail}`
204
+ ? Head extends IdentifierRest ? SafeIdentifierRest<Tail> : never
205
+ : never
206
+
207
+ type SafeSqlIdentifier<Value extends string> =
208
+ Value extends `${infer Head}${infer Tail}`
209
+ ? Head extends IdentifierStart
210
+ ? SafeIdentifierRest<Tail> extends never ? never : Value
211
+ : never
212
+ : never
213
+
214
+ export type SafeSqlIdentifierPathInput<Value extends string> =
215
+ string extends Value
216
+ ? never
217
+ : Value extends `${infer Head}.${infer Tail}`
218
+ ? SafeSqlIdentifier<Head> extends never
219
+ ? never
220
+ : SafeSqlIdentifierPathInput<Tail> extends never ? never : Value
221
+ : SafeSqlIdentifier<Value> extends never ? never : Value
222
+
223
+ export type SafeSqlIdentifierInput<Value extends string> =
224
+ string extends Value
225
+ ? never
226
+ : SafeSqlIdentifier<Value> extends never ? never : Value
227
+
228
+ type LiteralStringTupleInput<Values extends readonly string[]> = {
229
+ readonly [K in keyof Values]: Values[K] extends string ? LiteralStringInput<Values[K]> : never
230
+ } & Values
231
+
232
+ export type CollationIdentifierInput<Value extends string | readonly [string, ...string[]]> =
233
+ Value extends string
234
+ ? LiteralStringInput<Value>
235
+ : Value extends readonly [string, ...string[]]
236
+ ? LiteralStringTupleInput<Value>
237
+ : never
238
+
137
239
  export type MatchingColumnArityInput<
138
240
  Left extends string | readonly string[],
139
241
  Right extends string | readonly string[]
@@ -206,11 +308,10 @@ type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
206
308
 
207
309
  /** Normalizes a string or tuple input into a non-empty column list. */
208
310
  export const normalizeColumnList = (columns: string | readonly string[]): ColumnList => {
209
- const normalized = Array.isArray(columns) ? [...columns] : [columns]
210
- if (normalized.length === 0) {
211
- throw new Error("Table options require at least one column")
311
+ if (typeof columns === "string") {
312
+ return [columns]
212
313
  }
213
- return normalized as unknown as ColumnList
314
+ return [columns[0] as string, ...columns.slice(1)]
214
315
  }
215
316
 
216
317
  /** Converts inline column flags into normalized table option records. */
@@ -236,8 +337,6 @@ export const collectInlineOptions = <Fields extends TableFieldMap>(
236
337
  })
237
338
  }
238
339
  if (column.metadata.references) {
239
- validateReferentialAction(column.metadata.references.onUpdate)
240
- validateReferentialAction(column.metadata.references.onDelete)
241
340
  const local = [columnName] as ColumnList
242
341
  options.push({
243
342
  kind: "foreignKey",
@@ -248,6 +347,7 @@ export const collectInlineOptions = <Fields extends TableFieldMap>(
248
347
  return {
249
348
  tableName: bound.baseTableName,
250
349
  schemaName: bound.schemaName,
350
+ casing: bound.casing,
251
351
  columns: [bound.columnName]
252
352
  }
253
353
  },
@@ -287,24 +387,16 @@ export const resolvePrimaryKeyColumns = <Fields extends TableFieldMap>(
287
387
  const inline = Object.entries(fields)
288
388
  .filter(([, column]) => column.metadata.primaryKey)
289
389
  .map(([key]) => key) as (keyof Fields & string)[]
290
- const explicit = declaredOptions
291
- .filter((option) => option.kind === "primaryKey")
292
- .map((option) => option.columns)
293
- if (explicit.length > 1) {
294
- throw new Error("Only one primary key declaration is allowed")
295
- }
390
+ const explicit = declaredOptions.flatMap((option) => {
391
+ if (typeof option !== "object" || option === null || !("kind" in option) || option.kind !== "primaryKey") {
392
+ return []
393
+ }
394
+ return Array.isArray(option.columns) ? [option.columns] : []
395
+ })
296
396
  if (explicit.length === 0) {
297
397
  return inline
298
398
  }
299
399
  const tablePrimaryKey = [...explicit[0]!] as (keyof Fields & string)[]
300
- if (inline.length > 0) {
301
- const same =
302
- inline.length === tablePrimaryKey.length &&
303
- inline.every((column) => tablePrimaryKey.includes(column))
304
- if (!same) {
305
- throw new Error("Inline primary keys conflict with table-level primary key declaration")
306
- }
307
- }
308
400
  return tablePrimaryKey
309
401
  }
310
402
 
@@ -312,67 +404,35 @@ export const resolvePrimaryKeyColumns = <Fields extends TableFieldMap>(
312
404
  export const validateOptions = <Fields extends TableFieldMap>(
313
405
  tableName: string,
314
406
  fields: Fields,
315
- options: readonly TableOptionSpec[]
407
+ options: unknown
316
408
  ): void => {
317
- const knownColumns = new Set(Object.keys(fields))
318
- for (const option of options) {
409
+ const tableOptions = (Array.isArray(options)
410
+ ? options
411
+ : [options]) as readonly TableOptionSpec[]
412
+ for (const option of tableOptions) {
413
+ if (typeof option !== "object" || option === null || !("kind" in option)) {
414
+ continue
415
+ }
319
416
  switch (option.kind) {
320
417
  case "index":
321
418
  case "primaryKey":
322
419
  case "unique":
323
420
  case "foreignKey": {
324
- const columns = option.kind === "index"
325
- ? option.columns ?? []
326
- : option.columns
327
- if (columns.length === 0 && option.kind !== "index") {
328
- throw new Error(`Option '${option.kind}' on table '${tableName}' requires at least one column`)
329
- }
330
- for (const column of columns) {
331
- if (!knownColumns.has(column)) {
332
- throw new Error(`Unknown column '${column}' on table '${tableName}'`)
333
- }
334
- }
335
- if (option.kind === "foreignKey") {
336
- validateReferentialAction(option.onUpdate)
337
- validateReferentialAction(option.onDelete)
338
- const reference = option.references()
339
- if (reference.columns.length !== columns.length) {
340
- throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`)
341
- }
342
- if (reference.knownColumns) {
343
- const referenced = new Set(reference.knownColumns)
344
- for (const column of reference.columns) {
345
- if (!referenced.has(column)) {
346
- throw new Error(`Unknown referenced column '${column}' on table '${reference.tableName}'`)
347
- }
348
- }
349
- }
350
- }
351
421
  if (option.kind === "index") {
352
- for (const column of option.include ?? []) {
353
- if (!knownColumns.has(column)) {
354
- throw new Error(`Unknown included column '${column}' on table '${tableName}'`)
355
- }
356
- }
357
- for (const key of option.keys ?? []) {
358
- if (key.kind === "column" && !knownColumns.has(key.column)) {
359
- throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`)
422
+ const keys = Array.isArray(option.keys) ? option.keys : []
423
+ for (const key of keys) {
424
+ if (typeof key !== "object" || key === null || !("kind" in key)) {
425
+ continue
360
426
  }
361
427
  }
362
- if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
363
- throw new Error(`Index on table '${tableName}' requires at least one column or key`)
364
- }
365
428
  }
366
429
  break
367
430
  }
368
431
  case "check": {
369
432
  break
370
433
  }
371
- }
372
- }
373
- for (const column of resolvePrimaryKeyColumns(fields, options)) {
374
- if (fields[column]!.metadata.nullable) {
375
- throw new Error(`Primary key column '${String(column)}' cannot be nullable`)
434
+ default:
435
+ break
376
436
  }
377
437
  }
378
438
  }