effect-qb 0.16.0 → 0.19.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.
- package/README.md +4 -0
- package/dist/index.js +8065 -0
- package/dist/mysql.js +4036 -2418
- package/dist/postgres/metadata.js +2536 -625
- package/dist/postgres.js +8248 -7857
- package/dist/sqlite.js +8854 -0
- package/dist/standard.js +8019 -0
- package/package.json +15 -3
- package/src/casing.ts +71 -0
- package/src/index.ts +2 -0
- package/src/internal/casing.ts +89 -0
- package/src/internal/column-state.ts +11 -6
- package/src/internal/column.ts +44 -7
- package/src/internal/datatypes/define.ts +2 -1
- package/src/internal/datatypes/enrich.ts +23 -0
- package/src/internal/datatypes/lookup.ts +14 -7
- package/src/internal/derived-table.ts +7 -13
- package/src/internal/dialect-renderers/mysql.ts +2046 -0
- package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +867 -283
- package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +834 -358
- package/src/internal/dialect.ts +37 -0
- package/src/internal/dsl-mutation-runtime.ts +29 -10
- package/src/internal/dsl-plan-runtime.ts +41 -24
- package/src/internal/dsl-query-runtime.ts +11 -31
- package/src/internal/dsl-transaction-ddl-runtime.ts +61 -15
- package/src/internal/executor.ts +57 -15
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +216 -9
- package/src/internal/implication-runtime.ts +3 -2
- package/src/internal/json/types.ts +155 -40
- package/src/internal/predicate/context.ts +14 -1
- package/src/internal/predicate/key.ts +19 -2
- package/src/internal/predicate/runtime.ts +30 -3
- package/src/internal/query.d.ts +38 -11
- package/src/internal/query.ts +315 -54
- package/src/internal/renderer.ts +51 -6
- package/src/internal/runtime/driver-value-mapping.ts +58 -0
- package/src/internal/runtime/normalize.ts +74 -43
- package/src/internal/runtime/schema.ts +5 -3
- package/src/internal/runtime/value.ts +153 -30
- package/src/internal/scalar.ts +6 -1
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +90 -38
- package/src/internal/schema-expression.ts +2 -2
- package/src/internal/sql-expression-renderer.ts +19 -0
- package/src/internal/standard-dsl.ts +6885 -0
- package/src/internal/table-options.ts +229 -62
- package/src/internal/table.d.ts +33 -32
- package/src/internal/table.ts +469 -160
- package/src/mysql/column-extension.ts +3 -0
- package/src/mysql/column.ts +27 -12
- package/src/mysql/datatypes/index.ts +24 -2
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +7 -5
- package/src/mysql/internal/dialect.ts +9 -4
- package/src/mysql/internal/dsl.ts +906 -324
- package/src/mysql/internal/renderer.ts +7 -2
- package/src/mysql/json.ts +37 -0
- package/src/mysql/query-extension.ts +16 -0
- package/src/mysql/query.ts +9 -2
- package/src/mysql/renderer.ts +31 -4
- package/src/mysql.ts +4 -12
- package/src/postgres/column-extension.ts +28 -0
- package/src/postgres/column.ts +9 -13
- package/src/postgres/datatypes/index.d.ts +2 -1
- package/src/postgres/datatypes/index.ts +3 -2
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +55 -10
- package/src/postgres/function/core.ts +20 -4
- package/src/postgres/function/index.ts +1 -17
- package/src/postgres/internal/dialect.ts +9 -4
- package/src/postgres/internal/dsl.ts +850 -359
- package/src/postgres/internal/renderer.ts +7 -2
- package/src/postgres/internal/schema-ddl.ts +22 -9
- package/src/postgres/internal/schema-model.ts +244 -10
- package/src/postgres/json.ts +100 -24
- package/src/postgres/jsonb.ts +38 -0
- package/src/postgres/query-extension.ts +2 -0
- package/src/postgres/query.ts +9 -2
- package/src/postgres/renderer.ts +31 -4
- package/src/postgres/schema-management.ts +108 -16
- package/src/postgres/schema.ts +98 -15
- package/src/postgres/table.ts +203 -398
- package/src/postgres/type.ts +8 -7
- package/src/postgres.ts +9 -11
- package/src/sqlite/column-extension.ts +3 -0
- package/src/sqlite/column.ts +127 -0
- package/src/sqlite/datatypes/index.ts +80 -0
- package/src/sqlite/datatypes/spec.ts +98 -0
- package/src/sqlite/errors/catalog.ts +103 -0
- package/src/sqlite/errors/fields.ts +19 -0
- package/src/sqlite/errors/index.ts +19 -0
- package/src/sqlite/errors/normalize.ts +229 -0
- package/src/sqlite/errors/requirements.ts +71 -0
- package/src/sqlite/errors/types.ts +29 -0
- package/src/sqlite/executor.ts +229 -0
- package/src/sqlite/function/aggregate.ts +2 -0
- package/src/sqlite/function/core.ts +2 -0
- package/src/sqlite/function/index.ts +19 -0
- package/src/sqlite/function/string.ts +2 -0
- package/src/sqlite/function/temporal.ts +100 -0
- package/src/sqlite/function/window.ts +2 -0
- package/src/sqlite/internal/dialect.ts +42 -0
- package/src/sqlite/internal/dsl.ts +6979 -0
- package/src/sqlite/internal/renderer.ts +51 -0
- package/src/sqlite/json.ts +39 -0
- package/src/sqlite/query-extension.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +51 -0
- package/src/sqlite.ts +14 -0
- package/src/standard/column.ts +163 -0
- package/src/standard/datatypes/index.ts +83 -0
- package/src/standard/datatypes/spec.ts +98 -0
- package/src/standard/dialect.ts +40 -0
- package/src/standard/function/aggregate.ts +2 -0
- package/src/standard/function/core.ts +2 -0
- package/src/standard/function/index.ts +18 -0
- package/src/standard/function/string.ts +2 -0
- package/src/standard/function/temporal.ts +78 -0
- package/src/standard/function/window.ts +2 -0
- package/src/standard/internal/renderer.ts +45 -0
- package/src/standard/query.ts +152 -0
- package/src/standard/renderer.ts +21 -0
- package/src/standard/table.ts +147 -0
- package/src/standard.ts +18 -0
- package/src/internal/aggregation-validation.ts +0 -57
- package/src/mysql/table.ts +0 -157
|
@@ -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
|
|
|
@@ -15,6 +18,51 @@ export type DdlExpressionLike = AnyExpression | AnySchemaExpression
|
|
|
15
18
|
|
|
16
19
|
export type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
|
|
17
20
|
|
|
21
|
+
const referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault"
|
|
22
|
+
|
|
23
|
+
export const renderReferentialAction = (action: unknown): string => {
|
|
24
|
+
switch (action) {
|
|
25
|
+
case "noAction":
|
|
26
|
+
return "no action"
|
|
27
|
+
case "restrict":
|
|
28
|
+
return "restrict"
|
|
29
|
+
case "cascade":
|
|
30
|
+
return "cascade"
|
|
31
|
+
case "setNull":
|
|
32
|
+
return "set null"
|
|
33
|
+
case "setDefault":
|
|
34
|
+
return "set default"
|
|
35
|
+
}
|
|
36
|
+
throw new Error(referentialActionError)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const validateReferentialAction = (action: unknown): void => {
|
|
40
|
+
if (action !== undefined) {
|
|
41
|
+
renderReferentialAction(action)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
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
|
+
|
|
18
66
|
export type IndexKeySpec =
|
|
19
67
|
| {
|
|
20
68
|
readonly kind: "column"
|
|
@@ -67,6 +115,7 @@ export type TableOptionSpec =
|
|
|
67
115
|
readonly references: () => {
|
|
68
116
|
readonly tableName: string
|
|
69
117
|
readonly schemaName?: string
|
|
118
|
+
readonly casing?: Casing.Options
|
|
70
119
|
readonly columns: ColumnList
|
|
71
120
|
readonly knownColumns?: readonly string[]
|
|
72
121
|
}
|
|
@@ -107,6 +156,95 @@ type TupleFromColumns<Columns> = Columns extends readonly [infer Head extends st
|
|
|
107
156
|
? readonly [Columns]
|
|
108
157
|
: never
|
|
109
158
|
|
|
159
|
+
export type NonEmptyColumnInput<Columns extends string | readonly string[]> =
|
|
160
|
+
TupleFromColumns<Columns> extends never ? never : Columns
|
|
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
|
+
|
|
239
|
+
export type MatchingColumnArityInput<
|
|
240
|
+
Left extends string | readonly string[],
|
|
241
|
+
Right extends string | readonly string[]
|
|
242
|
+
> = TupleFromColumns<Left>["length"] extends TupleFromColumns<Right>["length"]
|
|
243
|
+
? TupleFromColumns<Right>["length"] extends TupleFromColumns<Left>["length"]
|
|
244
|
+
? unknown
|
|
245
|
+
: never
|
|
246
|
+
: never
|
|
247
|
+
|
|
110
248
|
type AssertKnownColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = Exclude<
|
|
111
249
|
Columns[number],
|
|
112
250
|
ColumnNameUnion<Fields>
|
|
@@ -114,6 +252,47 @@ type AssertKnownColumns<Fields extends TableFieldMap, Columns extends readonly s
|
|
|
114
252
|
? Columns
|
|
115
253
|
: never
|
|
116
254
|
|
|
255
|
+
type IndexKeyColumnNames<Keys> = Keys extends readonly (infer Key)[]
|
|
256
|
+
? Key extends { readonly kind: "column"; readonly column: infer Column extends string }
|
|
257
|
+
? Column
|
|
258
|
+
: never
|
|
259
|
+
: never
|
|
260
|
+
|
|
261
|
+
type IndexOptionColumnNames<Spec> =
|
|
262
|
+
| (Spec extends { readonly columns: infer Columns extends readonly string[] } ? Columns[number] : never)
|
|
263
|
+
| (Spec extends { readonly include: infer Include extends readonly string[] } ? Include[number] : never)
|
|
264
|
+
| (Spec extends { readonly keys: infer Keys } ? IndexKeyColumnNames<Keys> : never)
|
|
265
|
+
|
|
266
|
+
type ForeignKeyReferencedColumnNames<Spec> = Spec extends { readonly references: () => infer Reference }
|
|
267
|
+
? Reference extends { readonly columns: infer Columns extends readonly string[] }
|
|
268
|
+
? Columns[number]
|
|
269
|
+
: never
|
|
270
|
+
: never
|
|
271
|
+
|
|
272
|
+
type ForeignKeyKnownReferencedColumnNames<Spec> = Spec extends { readonly references: () => infer Reference }
|
|
273
|
+
? Reference extends { readonly knownColumns: infer KnownColumns extends readonly string[] }
|
|
274
|
+
? KnownColumns[number]
|
|
275
|
+
: string
|
|
276
|
+
: string
|
|
277
|
+
|
|
278
|
+
type AssertKnownColumnNames<Fields extends TableFieldMap, Columns extends string> = [Columns] extends [never]
|
|
279
|
+
? true
|
|
280
|
+
: string extends Columns
|
|
281
|
+
? true
|
|
282
|
+
: Exclude<Columns, ColumnNameUnion<Fields>> extends never
|
|
283
|
+
? true
|
|
284
|
+
: false
|
|
285
|
+
|
|
286
|
+
type AssertKnownReferenceColumnNames<KnownColumns extends string, Columns extends string> = [Columns] extends [never]
|
|
287
|
+
? true
|
|
288
|
+
: string extends Columns
|
|
289
|
+
? true
|
|
290
|
+
: string extends KnownColumns
|
|
291
|
+
? true
|
|
292
|
+
: Exclude<Columns, KnownColumns> extends never
|
|
293
|
+
? true
|
|
294
|
+
: false
|
|
295
|
+
|
|
117
296
|
type AssertPrimaryKeyColumns<
|
|
118
297
|
Fields extends TableFieldMap,
|
|
119
298
|
Columns extends readonly string[]
|
|
@@ -129,11 +308,10 @@ type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
|
|
|
129
308
|
|
|
130
309
|
/** Normalizes a string or tuple input into a non-empty column list. */
|
|
131
310
|
export const normalizeColumnList = (columns: string | readonly string[]): ColumnList => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
throw new Error("Table options require at least one column")
|
|
311
|
+
if (typeof columns === "string") {
|
|
312
|
+
return [columns]
|
|
135
313
|
}
|
|
136
|
-
return
|
|
314
|
+
return [columns[0] as string, ...columns.slice(1)]
|
|
137
315
|
}
|
|
138
316
|
|
|
139
317
|
/** Converts inline column flags into normalized table option records. */
|
|
@@ -169,6 +347,7 @@ export const collectInlineOptions = <Fields extends TableFieldMap>(
|
|
|
169
347
|
return {
|
|
170
348
|
tableName: bound.baseTableName,
|
|
171
349
|
schemaName: bound.schemaName,
|
|
350
|
+
casing: bound.casing,
|
|
172
351
|
columns: [bound.columnName]
|
|
173
352
|
}
|
|
174
353
|
},
|
|
@@ -208,24 +387,16 @@ export const resolvePrimaryKeyColumns = <Fields extends TableFieldMap>(
|
|
|
208
387
|
const inline = Object.entries(fields)
|
|
209
388
|
.filter(([, column]) => column.metadata.primaryKey)
|
|
210
389
|
.map(([key]) => key) as (keyof Fields & string)[]
|
|
211
|
-
const explicit = declaredOptions
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
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
|
+
})
|
|
217
396
|
if (explicit.length === 0) {
|
|
218
397
|
return inline
|
|
219
398
|
}
|
|
220
399
|
const tablePrimaryKey = [...explicit[0]!] as (keyof Fields & string)[]
|
|
221
|
-
if (inline.length > 0) {
|
|
222
|
-
const same =
|
|
223
|
-
inline.length === tablePrimaryKey.length &&
|
|
224
|
-
inline.every((column) => tablePrimaryKey.includes(column))
|
|
225
|
-
if (!same) {
|
|
226
|
-
throw new Error("Inline primary keys conflict with table-level primary key declaration")
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
400
|
return tablePrimaryKey
|
|
230
401
|
}
|
|
231
402
|
|
|
@@ -233,65 +404,35 @@ export const resolvePrimaryKeyColumns = <Fields extends TableFieldMap>(
|
|
|
233
404
|
export const validateOptions = <Fields extends TableFieldMap>(
|
|
234
405
|
tableName: string,
|
|
235
406
|
fields: Fields,
|
|
236
|
-
options:
|
|
407
|
+
options: unknown
|
|
237
408
|
): void => {
|
|
238
|
-
const
|
|
239
|
-
|
|
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
|
+
}
|
|
240
416
|
switch (option.kind) {
|
|
241
417
|
case "index":
|
|
242
418
|
case "primaryKey":
|
|
243
419
|
case "unique":
|
|
244
420
|
case "foreignKey": {
|
|
245
|
-
const columns = option.kind === "index"
|
|
246
|
-
? option.columns ?? []
|
|
247
|
-
: option.columns
|
|
248
|
-
if (columns.length === 0 && option.kind !== "index") {
|
|
249
|
-
throw new Error(`Option '${option.kind}' on table '${tableName}' requires at least one column`)
|
|
250
|
-
}
|
|
251
|
-
for (const column of columns) {
|
|
252
|
-
if (!knownColumns.has(column)) {
|
|
253
|
-
throw new Error(`Unknown column '${column}' on table '${tableName}'`)
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (option.kind === "foreignKey") {
|
|
257
|
-
const reference = option.references()
|
|
258
|
-
if (reference.columns.length !== columns.length) {
|
|
259
|
-
throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`)
|
|
260
|
-
}
|
|
261
|
-
if (reference.knownColumns) {
|
|
262
|
-
const referenced = new Set(reference.knownColumns)
|
|
263
|
-
for (const column of reference.columns) {
|
|
264
|
-
if (!referenced.has(column)) {
|
|
265
|
-
throw new Error(`Unknown referenced column '${column}' on table '${reference.tableName}'`)
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
421
|
if (option.kind === "index") {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
for (const key of option.keys ?? []) {
|
|
277
|
-
if (key.kind === "column" && !knownColumns.has(key.column)) {
|
|
278
|
-
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
|
|
279
426
|
}
|
|
280
427
|
}
|
|
281
|
-
if (option.columns === undefined && (option.keys === undefined || option.keys.length === 0)) {
|
|
282
|
-
throw new Error(`Index on table '${tableName}' requires at least one column or key`)
|
|
283
|
-
}
|
|
284
428
|
}
|
|
285
429
|
break
|
|
286
430
|
}
|
|
287
431
|
case "check": {
|
|
288
432
|
break
|
|
289
433
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
for (const column of resolvePrimaryKeyColumns(fields, options)) {
|
|
293
|
-
if (fields[column]!.metadata.nullable) {
|
|
294
|
-
throw new Error(`Primary key column '${String(column)}' cannot be nullable`)
|
|
434
|
+
default:
|
|
435
|
+
break
|
|
295
436
|
}
|
|
296
437
|
}
|
|
297
438
|
}
|
|
@@ -308,5 +449,31 @@ export type ValidatePrimaryKeyColumns<
|
|
|
308
449
|
Columns extends readonly string[]
|
|
309
450
|
> = AssertPrimaryKeyColumns<Fields, AssertKnownColumns<Fields, Columns>>
|
|
310
451
|
|
|
452
|
+
/** Compile-time validation that index columns, included columns, and column keys exist on the table. */
|
|
453
|
+
export type ValidateIndexOptionColumns<
|
|
454
|
+
Fields extends TableFieldMap,
|
|
455
|
+
Spec
|
|
456
|
+
> = AssertKnownColumnNames<Fields, IndexOptionColumnNames<Spec>> extends true ? Spec : never
|
|
457
|
+
|
|
458
|
+
/** Compile-time validation that foreign keys reference known local and target columns. */
|
|
459
|
+
export type ValidateForeignKeyOptionColumns<
|
|
460
|
+
Fields extends TableFieldMap,
|
|
461
|
+
Spec
|
|
462
|
+
> = Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
463
|
+
? AssertKnownColumns<Fields, Columns> extends never
|
|
464
|
+
? never
|
|
465
|
+
: AssertKnownReferenceColumnNames<
|
|
466
|
+
ForeignKeyKnownReferencedColumnNames<Spec>,
|
|
467
|
+
ForeignKeyReferencedColumnNames<Spec>
|
|
468
|
+
> extends true
|
|
469
|
+
? Spec
|
|
470
|
+
: never
|
|
471
|
+
: AssertKnownReferenceColumnNames<
|
|
472
|
+
ForeignKeyKnownReferencedColumnNames<Spec>,
|
|
473
|
+
ForeignKeyReferencedColumnNames<Spec>
|
|
474
|
+
> extends true
|
|
475
|
+
? Spec
|
|
476
|
+
: never
|
|
477
|
+
|
|
311
478
|
/** Normalizes a public column input into the internal tuple form. */
|
|
312
479
|
export type NormalizeColumns<Columns extends string | readonly string[]> = TupleFromColumns<Columns>
|
package/src/internal/table.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as Schema from "effect/Schema";
|
|
|
3
3
|
import * as Plan from "./row-set.js";
|
|
4
4
|
import type { TrueFormula } from "./predicate/formula.js";
|
|
5
5
|
import type { BoundColumnFrom } from "./column-state.js";
|
|
6
|
-
import { type DdlExpressionLike, type NormalizeColumns, type TableOptionSpec, type ValidateKnownColumns, type ValidatePrimaryKeyColumns } from "./table-options.js";
|
|
6
|
+
import { type DdlExpressionLike, type NonEmptyStringInput, type NormalizeColumns, type TableOptionSpec, type ValidateKnownColumns, type ValidatePrimaryKeyColumns } from "./table-options.js";
|
|
7
7
|
import { type InsertRow, type SelectRow, type TableFieldMap, type UpdateRow } from "./schema-derivation.js";
|
|
8
8
|
/** Symbol used to attach table-definition metadata. */
|
|
9
9
|
export declare const TypeId: unique symbol;
|
|
@@ -59,13 +59,9 @@ interface TableState<Name extends string, Fields extends TableFieldMap, PrimaryK
|
|
|
59
59
|
readonly primaryKey: readonly PrimaryKeyColumns[];
|
|
60
60
|
readonly kind: Kind;
|
|
61
61
|
}
|
|
62
|
-
/** Namespace-scoped table builder. */
|
|
63
|
-
export interface TableSchemaNamespace<SchemaName extends string> {
|
|
64
|
-
readonly schemaName: SchemaName;
|
|
65
|
-
readonly table: <Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>>(name: Name, fields: Fields, ...options: DeclaredTableOptions) => TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>;
|
|
66
|
-
}
|
|
67
62
|
export type DeclaredTableOptions = readonly TableOptionBuilderLike[];
|
|
68
63
|
export type { DdlExpressionLike, IndexKeySpec, NormalizeColumns, ReferentialAction } from "./table-options.js";
|
|
64
|
+
export type NonEmptySchemaNameInput<Value extends string | undefined> = Value extends string ? NonEmptyStringInput<Value> : Value;
|
|
69
65
|
export type TableDefinition<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>, Kind extends TableKind = "schema", SchemaName extends string | undefined = DefaultSchemaName> = Pipeable & {
|
|
70
66
|
readonly name: Name;
|
|
71
67
|
readonly columns: BoundColumns<Name, Fields>;
|
|
@@ -92,7 +88,10 @@ export type TableClassStatic<Name extends string, Fields extends TableFieldMap,
|
|
|
92
88
|
readonly tableName: Name;
|
|
93
89
|
} & BoundColumns<Name, Fields> & Plan.RowSet<BoundColumns<Name, Fields>, never, Record<Name, Plan.Source<Name, "required", TrueFormula>>, TableDialect<Fields>>;
|
|
94
90
|
/** Minimal structural table-like contract used across helper APIs. */
|
|
95
|
-
export type AnyTable
|
|
91
|
+
export type AnyTable<Dialect extends string = string> = {
|
|
92
|
+
readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>;
|
|
93
|
+
readonly [OptionsSymbol]: readonly TableOptionSpec[];
|
|
94
|
+
} & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>;
|
|
96
95
|
/** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
|
|
97
96
|
export type TableOption<Spec extends TableOptionSpec = TableOptionSpec> = {
|
|
98
97
|
<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>;
|
|
@@ -101,11 +100,7 @@ export type TableOption<Spec extends TableOptionSpec = TableOptionSpec> = {
|
|
|
101
100
|
export declare const option: <Spec extends TableOptionSpec>(spec: Spec) => TableOption<Spec>;
|
|
102
101
|
export declare const optionFromTable: <Spec extends TableOptionSpec>(spec: Spec, resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec) => TableOption<Spec>;
|
|
103
102
|
/** Creates a table definition from a name and field map. */
|
|
104
|
-
export declare function make<Name extends string, Fields extends TableFieldMap, SchemaName extends string | undefined = DefaultSchemaName>(name: Name
|
|
105
|
-
/**
|
|
106
|
-
* Creates a namespace-scoped builder for a concrete SQL schema/database.
|
|
107
|
-
*/
|
|
108
|
-
export declare const schema: <SchemaName extends string>(schemaName: SchemaName) => TableSchemaNamespace<SchemaName>;
|
|
103
|
+
export declare function make<Name extends string, Fields extends TableFieldMap, const SchemaName extends string | undefined = DefaultSchemaName>(name: NonEmptyStringInput<Name>, fields: Fields, schemaName?: NonEmptySchemaNameInput<SchemaName>): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", SchemaName>;
|
|
109
104
|
/**
|
|
110
105
|
* Creates an aliased source from an existing table definition.
|
|
111
106
|
*
|
|
@@ -114,13 +109,21 @@ export declare const schema: <SchemaName extends string>(schemaName: SchemaName)
|
|
|
114
109
|
* downstream SQL rendering work.
|
|
115
110
|
*/
|
|
116
111
|
export declare const alias: <Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string, SchemaName extends string, AliasName extends string>(table: TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName> | TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName>, aliasName: AliasName) => TableDefinition<AliasName, Fields, PrimaryKeyColumns, "alias", SchemaName>;
|
|
112
|
+
/** Returns the lazily derived select schema for a table. */
|
|
113
|
+
export declare function selectSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Schema<SelectRow<Name, Fields>>;
|
|
114
|
+
/** Returns the lazily derived insert schema for a table. */
|
|
115
|
+
export declare function insertSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Schema<InsertRow<Name, Fields>>;
|
|
116
|
+
/** Returns the lazily derived update schema for a table. */
|
|
117
|
+
export declare function updateSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>;
|
|
117
118
|
/**
|
|
118
119
|
* Class-based table constructor mirroring `Schema.Class`.
|
|
119
120
|
*
|
|
120
121
|
* The returned base class can be extended and configured with
|
|
121
122
|
* `static readonly [Table.options]`.
|
|
122
123
|
*/
|
|
123
|
-
export declare function Class<Self = never
|
|
124
|
+
export declare function Class<Self = never>(name: "", schemaName?: string | undefined): never;
|
|
125
|
+
export declare function Class<Self = never>(name: string, schemaName: ""): never;
|
|
126
|
+
export declare function Class<Self = never, const SchemaName extends string | undefined = DefaultSchemaName, const Name extends string = string>(name: NonEmptyStringInput<Name>, schemaName?: NonEmptySchemaNameInput<SchemaName>): <Fields extends TableFieldMap>(fields: Fields) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Table.Class<Self>(...) {}`" : TableClassStatic<Name, Fields, Extract<{ [K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never; }[keyof Fields], string>, SchemaName>;
|
|
124
127
|
/** Declares a table-level primary key. */
|
|
125
128
|
export declare const primaryKey: <const Columns extends string | readonly string[]>(columns: Columns) => TableOption<{
|
|
126
129
|
readonly kind: "primaryKey";
|
|
@@ -148,26 +151,24 @@ export declare const foreignKey: <const LocalColumns extends string | readonly s
|
|
|
148
151
|
};
|
|
149
152
|
}>;
|
|
150
153
|
/** Declares a check constraint expression. */
|
|
151
|
-
export declare const check: <Name extends string>(name: Name
|
|
154
|
+
export declare const check: <const Name extends string>(name: NonEmptyStringInput<Name>, predicate: DdlExpressionLike) => TableOption<{
|
|
152
155
|
readonly kind: "check";
|
|
153
156
|
readonly name: Name;
|
|
154
157
|
readonly predicate: DdlExpressionLike;
|
|
155
158
|
}>;
|
|
156
|
-
/** Extracts the row type
|
|
157
|
-
export type SelectOf<Table extends {
|
|
158
|
-
readonly
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
readonly
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
readonly
|
|
171
|
-
|
|
172
|
-
};
|
|
173
|
-
}> = Schema.Schema.Type<Table["schemas"]["update"]>;
|
|
159
|
+
/** Extracts the row type produced by `selectSchema(table)`. */
|
|
160
|
+
export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
161
|
+
readonly name: infer Name extends string;
|
|
162
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
163
|
+
} ? SelectRow<Name, Fields> : never;
|
|
164
|
+
/** Extracts the payload type produced by `insertSchema(table)`. */
|
|
165
|
+
export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
166
|
+
readonly name: infer Name extends string;
|
|
167
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
168
|
+
} ? InsertRow<Name, Fields> : never;
|
|
169
|
+
/** Extracts the payload type produced by `updateSchema(table)`. */
|
|
170
|
+
export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
171
|
+
readonly name: infer Name extends string;
|
|
172
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
173
|
+
readonly primaryKey: readonly (infer PrimaryKeyColumns)[];
|
|
174
|
+
} ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never;
|