effect-qb 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/mysql.js +61555 -4252
  2. package/dist/postgres/metadata.js +728 -104
  3. package/dist/postgres.js +6906 -4023
  4. package/package.json +15 -2
  5. package/src/internal/aggregation-validation.ts +3 -3
  6. package/src/internal/case-analysis.d.ts +18 -0
  7. package/src/internal/case-analysis.ts +4 -4
  8. package/src/internal/coercion/analysis.d.ts +7 -0
  9. package/src/internal/{coercion-analysis.ts → coercion/analysis.ts} +3 -3
  10. package/src/internal/coercion/errors.d.ts +17 -0
  11. package/src/internal/{coercion-errors.ts → coercion/errors.ts} +1 -1
  12. package/src/internal/coercion/kind.d.ts +4 -0
  13. package/src/internal/{coercion-kind.ts → coercion/kind.ts} +2 -2
  14. package/src/internal/{coercion-normalize.ts → coercion/normalize.ts} +1 -1
  15. package/src/internal/coercion/rules.d.ts +6 -0
  16. package/src/internal/{coercion-rules.ts → coercion/rules.ts} +2 -2
  17. package/src/internal/column-state.d.ts +190 -0
  18. package/src/internal/column-state.ts +43 -47
  19. package/src/internal/column.ts +43 -305
  20. package/src/internal/datatypes/define.d.ts +17 -0
  21. package/src/internal/datatypes/define.ts +18 -4
  22. package/src/internal/datatypes/lookup.d.ts +44 -0
  23. package/src/internal/datatypes/lookup.ts +61 -152
  24. package/src/internal/datatypes/shape.d.ts +16 -0
  25. package/src/internal/datatypes/shape.ts +1 -1
  26. package/src/internal/derived-table.d.ts +4 -0
  27. package/src/internal/derived-table.ts +21 -16
  28. package/src/internal/dialect.ts +12 -1
  29. package/src/internal/dsl-mutation-runtime.ts +378 -0
  30. package/src/internal/dsl-plan-runtime.ts +387 -0
  31. package/src/internal/dsl-query-runtime.ts +160 -0
  32. package/src/internal/dsl-transaction-ddl-runtime.ts +263 -0
  33. package/src/internal/executor.ts +146 -34
  34. package/src/internal/expression-ast.ts +15 -5
  35. package/src/internal/grouping-key.d.ts +3 -0
  36. package/src/internal/grouping-key.ts +1 -1
  37. package/src/internal/implication-runtime.d.ts +15 -0
  38. package/src/internal/implication-runtime.ts +4 -4
  39. package/src/internal/json/ast.d.ts +30 -0
  40. package/src/internal/json/ast.ts +1 -1
  41. package/src/internal/json/errors.d.ts +8 -0
  42. package/src/internal/json/path.d.ts +75 -0
  43. package/src/internal/json/path.ts +1 -1
  44. package/src/internal/json/types.d.ts +62 -0
  45. package/src/internal/predicate/analysis.d.ts +20 -0
  46. package/src/internal/predicate/analysis.ts +183 -0
  47. package/src/internal/predicate/atom.d.ts +28 -0
  48. package/src/internal/{predicate-atom.ts → predicate/atom.ts} +7 -0
  49. package/src/internal/{predicate-branches.ts → predicate/branches.ts} +2 -2
  50. package/src/internal/predicate/context.d.ts +67 -0
  51. package/src/internal/{predicate-context.ts → predicate/context.ts} +163 -20
  52. package/src/internal/predicate/formula.d.ts +35 -0
  53. package/src/internal/{predicate-formula.ts → predicate/formula.ts} +1 -1
  54. package/src/internal/predicate/key.d.ts +11 -0
  55. package/src/internal/predicate/key.ts +73 -0
  56. package/src/internal/{predicate-nnf.ts → predicate/nnf.ts} +2 -2
  57. package/src/internal/predicate/normalize.d.ts +53 -0
  58. package/src/internal/{predicate-normalize.ts → predicate/normalize.ts} +130 -49
  59. package/src/internal/predicate/runtime.d.ts +31 -0
  60. package/src/internal/{predicate-runtime.ts → predicate/runtime.ts} +127 -17
  61. package/src/internal/projection-alias.d.ts +13 -0
  62. package/src/internal/projections.d.ts +31 -0
  63. package/src/internal/projections.ts +1 -1
  64. package/src/internal/query-ast.d.ts +217 -0
  65. package/src/internal/query-ast.ts +1 -1
  66. package/src/internal/query-requirements.d.ts +20 -0
  67. package/src/internal/query.d.ts +775 -0
  68. package/src/internal/query.ts +683 -369
  69. package/src/internal/renderer.ts +11 -21
  70. package/src/internal/row-set.d.ts +53 -0
  71. package/src/internal/{plan.ts → row-set.ts} +11 -9
  72. package/src/internal/runtime/driver-value-mapping.ts +186 -0
  73. package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
  74. package/src/internal/{runtime-schema.ts → runtime/schema.ts} +13 -38
  75. package/src/internal/runtime/value.d.ts +22 -0
  76. package/src/internal/{runtime-value.ts → runtime/value.ts} +2 -2
  77. package/src/internal/scalar.d.ts +107 -0
  78. package/src/internal/scalar.ts +202 -0
  79. package/src/internal/schema-derivation.d.ts +105 -0
  80. package/src/internal/schema-expression.d.ts +18 -0
  81. package/src/internal/schema-expression.ts +38 -7
  82. package/src/internal/table-options.d.ts +94 -0
  83. package/src/internal/table-options.ts +8 -2
  84. package/src/internal/table.d.ts +173 -0
  85. package/src/internal/table.ts +32 -14
  86. package/src/mysql/column.ts +95 -18
  87. package/src/mysql/datatypes/index.ts +47 -7
  88. package/src/mysql/errors/generated.ts +57336 -0
  89. package/src/mysql/errors/index.ts +1 -0
  90. package/src/mysql/errors/normalize.ts +55 -53
  91. package/src/mysql/errors/types.ts +74 -0
  92. package/src/mysql/executor.ts +88 -11
  93. package/src/mysql/function/aggregate.ts +1 -5
  94. package/src/mysql/function/core.ts +1 -4
  95. package/src/mysql/function/index.ts +0 -1
  96. package/src/mysql/function/string.ts +1 -5
  97. package/src/mysql/function/temporal.ts +12 -15
  98. package/src/mysql/function/window.ts +1 -6
  99. package/src/{internal/mysql-dialect.ts → mysql/internal/dialect.ts} +12 -6
  100. package/src/{internal/mysql-query.ts → mysql/internal/dsl.ts} +1299 -2143
  101. package/src/mysql/internal/renderer.ts +46 -0
  102. package/src/mysql/internal/sql-expression-renderer.ts +1501 -0
  103. package/src/mysql/json.ts +2 -0
  104. package/src/mysql/query.ts +111 -91
  105. package/src/mysql/renderer.ts +8 -3
  106. package/src/mysql/table.ts +1 -1
  107. package/src/mysql.ts +6 -4
  108. package/src/postgres/cast.ts +30 -16
  109. package/src/postgres/column.ts +179 -46
  110. package/src/postgres/datatypes/index.d.ts +515 -0
  111. package/src/postgres/datatypes/index.ts +22 -13
  112. package/src/postgres/datatypes/spec.d.ts +412 -0
  113. package/src/postgres/errors/generated.ts +2636 -0
  114. package/src/postgres/errors/index.ts +1 -0
  115. package/src/postgres/errors/normalize.ts +47 -62
  116. package/src/postgres/errors/types.ts +92 -34
  117. package/src/postgres/executor.ts +54 -7
  118. package/src/postgres/function/aggregate.ts +1 -5
  119. package/src/postgres/function/core.ts +12 -6
  120. package/src/postgres/function/index.ts +0 -1
  121. package/src/postgres/function/string.ts +1 -5
  122. package/src/postgres/function/temporal.ts +12 -15
  123. package/src/postgres/function/window.ts +1 -6
  124. package/src/{internal/postgres-dialect.ts → postgres/internal/dialect.ts} +12 -6
  125. package/src/{internal/postgres-query.ts → postgres/internal/dsl.ts} +1356 -2133
  126. package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +17 -8
  127. package/src/postgres/internal/schema-ddl.ts +108 -0
  128. package/src/{internal/postgres-schema-model.ts → postgres/internal/schema-model.ts} +12 -6
  129. package/src/{internal → postgres/internal}/sql-expression-renderer.ts +79 -25
  130. package/src/postgres/{function/json.ts → json.ts} +77 -85
  131. package/src/postgres/metadata.ts +2 -2
  132. package/src/postgres/query.ts +113 -89
  133. package/src/postgres/renderer.ts +8 -13
  134. package/src/postgres/schema-expression.ts +2 -1
  135. package/src/postgres/schema-management.ts +1 -1
  136. package/src/postgres/table.ts +12 -4
  137. package/src/postgres/type.ts +33 -2
  138. package/src/postgres.ts +6 -4
  139. package/src/internal/expression.ts +0 -327
  140. package/src/internal/mysql-renderer.ts +0 -37
  141. package/src/internal/predicate-analysis.ts +0 -81
  142. package/src/internal/predicate-key.ts +0 -28
  143. package/src/internal/schema-ddl.ts +0 -55
  144. package/src/mysql/function/json.ts +0 -4
  145. package/src/mysql/private/query.ts +0 -1
  146. package/src/postgres/private/query.ts +0 -1
@@ -0,0 +1,107 @@
1
+ import type { Pipeable } from "effect/Pipeable";
2
+ import type * as Schema from "effect/Schema";
3
+ import type { RuntimeOfDbType as RuntimeOfDbTypeLookup } from "./datatypes/lookup.js";
4
+ import type { DatatypeTraits, RuntimeTag } from "./datatypes/shape.js";
5
+ export type { BigIntString, DecimalString, InstantString, JsonPrimitive, JsonValue, LocalDateString, LocalDateTimeString, LocalTimeString, OffsetTimeString, YearString } from "./runtime/value.js";
6
+ /** Symbol used to attach expression metadata to runtime values. */
7
+ export declare const TypeId: unique symbol;
8
+ export type TypeId = typeof TypeId;
9
+ /** Scope-local binding identifier used for dependency tracking. */
10
+ export type BindingId = string;
11
+ /**
12
+ * Three-state nullability lattice.
13
+ *
14
+ * `"never"` means non-null, `"maybe"` means nullable, and `"always"` means the
15
+ * expression is known to be `null`.
16
+ */
17
+ export type Nullability = "never" | "maybe" | "always";
18
+ /**
19
+ * High-level classification of an expression.
20
+ *
21
+ * - `scalar`: regular per-row expression
22
+ * - `aggregate`: grouped expression such as `count(*)`
23
+ * - `window`: windowed expression such as `row_number() over (...)`
24
+ */
25
+ export type ScalarKind = "scalar" | "aggregate" | "window";
26
+ /** Database-type descriptors carried alongside decoded runtime types. */
27
+ export declare namespace DbType {
28
+ /** Base SQL type descriptor. */
29
+ interface Base<Dialect extends string, Kind extends string> {
30
+ readonly dialect: Dialect;
31
+ readonly kind: Kind;
32
+ readonly family?: string;
33
+ readonly runtime?: RuntimeTag;
34
+ readonly compareGroup?: string;
35
+ readonly castTargets?: readonly string[];
36
+ readonly traits?: DatatypeTraits;
37
+ }
38
+ /** JSON-like database type. */
39
+ interface Json<Dialect extends string = string, SchemaName extends string = "json"> extends Base<Dialect, SchemaName> {
40
+ readonly variant: SchemaName extends "jsonb" ? "jsonb" : "json";
41
+ }
42
+ /** Array database type. */
43
+ interface Array<Dialect extends string = string, Element extends Any = any, Kind extends string = string> extends Base<Dialect, Kind> {
44
+ readonly element: Element;
45
+ }
46
+ /** Range database type. */
47
+ interface Range<Dialect extends string = string, Subtype extends Any = any, Kind extends string = string> extends Base<Dialect, Kind> {
48
+ readonly subtype: Subtype;
49
+ }
50
+ /** Multirange database type. */
51
+ interface Multirange<Dialect extends string = string, Subtype extends Any = any, Kind extends string = string> extends Base<Dialect, Kind> {
52
+ readonly subtype: Subtype;
53
+ }
54
+ /** Composite/record database type. */
55
+ interface Composite<Dialect extends string = string, Fields extends Record<string, Any> = Record<string, any>, Kind extends string = string> extends Base<Dialect, Kind> {
56
+ readonly fields: Fields;
57
+ }
58
+ /** Named domain database type. */
59
+ interface Domain<Dialect extends string = string, BaseType extends Any = any, Kind extends string = string> extends Base<Dialect, Kind> {
60
+ readonly base: BaseType;
61
+ }
62
+ /** Enumeration database type. */
63
+ interface Enum<Dialect extends string = string, Kind extends string = string> extends Base<Dialect, Kind> {
64
+ readonly variant: "enum";
65
+ }
66
+ /** Set database type. */
67
+ interface Set<Dialect extends string = string, Kind extends string = string> extends Base<Dialect, Kind> {
68
+ readonly variant: "set";
69
+ }
70
+ type Any = Json | Base<string, string> | Array<string, any, string> | Range<string, any, string> | Multirange<string, any, string> | Composite<string, Record<string, any>, string> | Domain<string, any, string> | Enum<string, string> | Set<string, string>;
71
+ }
72
+ /** Canonical static metadata stored on an expression. */
73
+ export interface State<Runtime, Db extends DbType.Any, Nullable extends Nullability, Dialect extends string, Kind extends ScalarKind, Deps extends BindingId = never> {
74
+ readonly runtime: Runtime;
75
+ readonly dbType: Db;
76
+ readonly runtimeSchema?: Schema.Schema.Any;
77
+ readonly nullability: Nullable;
78
+ readonly dialect: Dialect;
79
+ readonly kind: Kind;
80
+ readonly dependencies: Record<string, true>;
81
+ }
82
+ /**
83
+ * A typed scalar SQL expression.
84
+ *
85
+ * `Runtime` is the decoded TypeScript type while `Db` captures the SQL-level
86
+ * type identity. Both are needed: multiple SQL types may decode to the same
87
+ * runtime type but still have different comparison/cast semantics.
88
+ */
89
+ export interface Scalar<Runtime, Db extends DbType.Any, Nullable extends Nullability = "never", Dialect extends string = Db["dialect"], Kind extends ScalarKind = "scalar", Deps extends BindingId = never, GroupKey extends string = string> extends Pipeable {
90
+ readonly [TypeId]: State<Runtime, Db, Nullable, Dialect, Kind, Deps>;
91
+ }
92
+ /** Convenience alias for any expression-like value. */
93
+ export type Any = Scalar<any, DbType.Any, Nullability, string, ScalarKind, BindingId, string>;
94
+ /** Extracts an expression's decoded runtime type. */
95
+ export type RuntimeOf<Value extends Any> = Value[typeof TypeId]["runtime"];
96
+ /** Extracts an expression's database-type descriptor. */
97
+ export type DbTypeOf<Value extends Any> = Value[typeof TypeId]["dbType"];
98
+ /** Extracts an expression's nullability state. */
99
+ export type NullabilityOf<Value extends Any> = Value[typeof TypeId]["nullability"];
100
+ /** Extracts an expression's kind. */
101
+ export type KindOf<Value extends Any> = Value[typeof TypeId]["kind"];
102
+ /** Extracts an expression's source dependency union. */
103
+ export type DependenciesOf<Value extends Any> = Value extends Scalar<any, any, any, any, any, infer Deps> ? Deps : never;
104
+ /** Extracts an expression's grouping identity. */
105
+ export type GroupKeyOf<Value extends Any> = Value extends Scalar<any, any, any, any, any, any, infer GroupKey> ? GroupKey : never;
106
+ /** Maps a database type descriptor back to its decoded runtime type. */
107
+ export type RuntimeOfDbType<Db extends DbType.Any> = RuntimeOfDbTypeLookup<Db>;
@@ -0,0 +1,202 @@
1
+ import type { Pipeable } from "effect/Pipeable"
2
+ import type * as Schema from "effect/Schema"
3
+ import type { RuntimeOfDbType as RuntimeOfDbTypeLookup } from "./datatypes/lookup.js"
4
+ import type { DatatypeTraits, RuntimeTag } from "./datatypes/shape.js"
5
+
6
+ export type {
7
+ BigIntString,
8
+ DecimalString,
9
+ InstantString,
10
+ JsonPrimitive,
11
+ JsonValue,
12
+ LocalDateString,
13
+ LocalDateTimeString,
14
+ LocalTimeString,
15
+ OffsetTimeString,
16
+ YearString
17
+ } from "./runtime/value.js"
18
+
19
+ /** Symbol used to attach expression metadata to runtime values. */
20
+ export const TypeId: unique symbol = Symbol.for("effect-qb/Expression")
21
+
22
+ export type TypeId = typeof TypeId
23
+
24
+ /** Scope-local binding identifier used for dependency tracking. */
25
+ export type BindingId = string
26
+ /**
27
+ * Three-state nullability lattice.
28
+ *
29
+ * `"never"` means non-null, `"maybe"` means nullable, and `"always"` means the
30
+ * expression is known to be `null`.
31
+ */
32
+ export type Nullability = "never" | "maybe" | "always"
33
+
34
+ /**
35
+ * High-level classification of an expression.
36
+ *
37
+ * - `scalar`: regular per-row expression
38
+ * - `aggregate`: grouped expression such as `count(*)`
39
+ * - `window`: windowed expression such as `row_number() over (...)`
40
+ */
41
+ export type ScalarKind = "scalar" | "aggregate" | "window"
42
+
43
+ /** Database-type descriptors carried alongside decoded runtime types. */
44
+ export declare namespace DbType {
45
+ /** Base SQL type descriptor. */
46
+ export interface Base<Dialect extends string, Kind extends string> {
47
+ readonly dialect: Dialect
48
+ readonly kind: Kind
49
+ readonly family?: string
50
+ readonly runtime?: RuntimeTag
51
+ readonly compareGroup?: string
52
+ readonly castTargets?: readonly string[]
53
+ readonly traits?: DatatypeTraits
54
+ readonly driverValueMapping?: DriverValueMapping
55
+ }
56
+
57
+ /** JSON-like database type. */
58
+ export interface Json<
59
+ Dialect extends string = string,
60
+ SchemaName extends string = "json"
61
+ > extends Base<Dialect, SchemaName>
62
+ {
63
+ readonly variant: SchemaName extends "jsonb" ? "jsonb" : "json"
64
+ }
65
+
66
+ /** Array database type. */
67
+ export interface Array<
68
+ Dialect extends string = string,
69
+ Element extends Any = any,
70
+ Kind extends string = string
71
+ > extends Base<Dialect, Kind> {
72
+ readonly element: Element
73
+ }
74
+
75
+ /** Range database type. */
76
+ export interface Range<
77
+ Dialect extends string = string,
78
+ Subtype extends Any = any,
79
+ Kind extends string = string
80
+ > extends Base<Dialect, Kind> {
81
+ readonly subtype: Subtype
82
+ }
83
+
84
+ /** Multirange database type. */
85
+ export interface Multirange<
86
+ Dialect extends string = string,
87
+ Subtype extends Any = any,
88
+ Kind extends string = string
89
+ > extends Base<Dialect, Kind> {
90
+ readonly subtype: Subtype
91
+ }
92
+
93
+ /** Composite/record database type. */
94
+ export interface Composite<
95
+ Dialect extends string = string,
96
+ Fields extends Record<string, Any> = Record<string, any>,
97
+ Kind extends string = string
98
+ > extends Base<Dialect, Kind> {
99
+ readonly fields: Fields
100
+ }
101
+
102
+ /** Named domain database type. */
103
+ export interface Domain<
104
+ Dialect extends string = string,
105
+ BaseType extends Any = any,
106
+ Kind extends string = string
107
+ > extends Base<Dialect, Kind> {
108
+ readonly base: BaseType
109
+ }
110
+
111
+ /** Enumeration database type. */
112
+ export interface Enum<
113
+ Dialect extends string = string,
114
+ Kind extends string = string
115
+ > extends Base<Dialect, Kind> {
116
+ readonly variant: "enum"
117
+ }
118
+
119
+ /** Set database type. */
120
+ export interface Set<
121
+ Dialect extends string = string,
122
+ Kind extends string = string
123
+ > extends Base<Dialect, Kind> {
124
+ readonly variant: "set"
125
+ }
126
+
127
+ export type Any =
128
+ | Json
129
+ | Base<string, string>
130
+ | Array<string, any, string>
131
+ | Range<string, any, string>
132
+ | Multirange<string, any, string>
133
+ | Composite<string, Record<string, any>, string>
134
+ | Domain<string, any, string>
135
+ | Enum<string, string>
136
+ | Set<string, string>
137
+ }
138
+
139
+ export interface DriverValueMapping {
140
+ readonly fromDriver?: (value: unknown, dbType: DbType.Any) => unknown
141
+ readonly toDriver?: (value: unknown, dbType: DbType.Any) => unknown
142
+ readonly selectSql?: (sql: string, dbType: DbType.Any) => string
143
+ readonly jsonSelectSql?: (sql: string, dbType: DbType.Any) => string
144
+ }
145
+
146
+ export type DriverValueMappings = Readonly<Record<string, DriverValueMapping | undefined>>
147
+
148
+ /** Canonical static metadata stored on an expression. */
149
+ export interface State<
150
+ Runtime,
151
+ Db extends DbType.Any,
152
+ Nullable extends Nullability,
153
+ Dialect extends string,
154
+ Kind extends ScalarKind,
155
+ Deps extends BindingId = never
156
+ > {
157
+ readonly runtime: Runtime
158
+ readonly dbType: Db
159
+ readonly runtimeSchema?: Schema.Schema.Any
160
+ readonly driverValueMapping?: DriverValueMapping
161
+ readonly nullability: Nullable
162
+ readonly dialect: Dialect
163
+ readonly kind: Kind
164
+ readonly dependencies: Record<string, true>
165
+ }
166
+
167
+ /**
168
+ * A typed scalar SQL expression.
169
+ *
170
+ * `Runtime` is the decoded TypeScript type while `Db` captures the SQL-level
171
+ * type identity. Both are needed: multiple SQL types may decode to the same
172
+ * runtime type but still have different comparison/cast semantics.
173
+ */
174
+ export interface Scalar<
175
+ Runtime,
176
+ Db extends DbType.Any,
177
+ Nullable extends Nullability = "never",
178
+ Dialect extends string = Db["dialect"],
179
+ Kind extends ScalarKind = "scalar",
180
+ Deps extends BindingId = never,
181
+ GroupKey extends string = string
182
+ > extends Pipeable {
183
+ readonly [TypeId]: State<Runtime, Db, Nullable, Dialect, Kind, Deps>
184
+ }
185
+
186
+ /** Convenience alias for any expression-like value. */
187
+ export type Any = Scalar<any, DbType.Any, Nullability, string, ScalarKind, BindingId, string>
188
+ /** Extracts an expression's decoded runtime type. */
189
+ export type RuntimeOf<Value extends Any> = Value[typeof TypeId]["runtime"]
190
+ /** Extracts an expression's database-type descriptor. */
191
+ export type DbTypeOf<Value extends Any> = Value[typeof TypeId]["dbType"]
192
+ /** Extracts an expression's nullability state. */
193
+ export type NullabilityOf<Value extends Any> = Value[typeof TypeId]["nullability"]
194
+ /** Extracts an expression's kind. */
195
+ export type KindOf<Value extends Any> = Value[typeof TypeId]["kind"]
196
+ /** Extracts an expression's source dependency union. */
197
+ export type DependenciesOf<Value extends Any> = Value extends Scalar<any, any, any, any, any, infer Deps> ? Deps : never
198
+ /** Extracts an expression's grouping identity. */
199
+ export type GroupKeyOf<Value extends Any> = Value extends Scalar<any, any, any, any, any, any, infer GroupKey> ? GroupKey : never
200
+
201
+ /** Maps a database type descriptor back to its decoded runtime type. */
202
+ export type RuntimeOfDbType<Db extends DbType.Any> = RuntimeOfDbTypeLookup<Db>
@@ -0,0 +1,105 @@
1
+ import * as VariantSchema from "@effect/experimental/VariantSchema";
2
+ import type * as Brand from "effect/Brand";
3
+ import * as Schema from "effect/Schema";
4
+ import { type AnyColumnDefinition, type HasDefault, type InsertType, type IsGenerated, type IsNullable, type SelectType, type UpdateType } from "./column-state.js";
5
+ /** Variant-schema helper used to derive select / insert / update schemas. */
6
+ export declare const TableSchema: {
7
+ readonly Struct: <const A extends VariantSchema.Struct.Fields>(fields: A & VariantSchema.Struct.Validate<A, "insert" | "select" | "update">) => VariantSchema.Struct<A>;
8
+ readonly Field: <const A extends VariantSchema.Field.ConfigWithKeys<"insert" | "select" | "update">>(config: A & { readonly [K in Exclude<keyof A, "insert" | "select" | "update">]: never; }) => VariantSchema.Field<A>;
9
+ readonly FieldOnly: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Keys[number]]: S; }>;
10
+ readonly FieldExcept: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Exclude<"insert", Keys[number]> | Exclude<"select", Keys[number]> | Exclude<"update", Keys[number]>]: S; }>;
11
+ readonly fieldEvolve: {
12
+ <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
13
+ readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
14
+ readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
15
+ readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
16
+ }>(f: Mapping): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping ? Mapping[K] extends (arg: any) => any ? ReturnType<Mapping[K]> : S_1[K] : S_1[K]; } : {
17
+ readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping ? Mapping[T] extends (arg: any) => any ? ReturnType<Mapping[T]> : Self : Self : never : never;
18
+ readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping ? Mapping[T_1] extends (arg: any) => any ? ReturnType<Mapping[T_1]> : Self : Self : never : never;
19
+ readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping ? Mapping[T_2] extends (arg: any) => any ? ReturnType<Mapping[T_2]> : Self : Self : never : never;
20
+ }>;
21
+ <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_1 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
22
+ readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
23
+ readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
24
+ readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
25
+ }>(self: Self, f: Mapping_1): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_1 ? Mapping_1[K] extends (arg: any) => any ? ReturnType<Mapping_1[K]> : S_1[K] : S_1[K]; } : {
26
+ readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_1 ? Mapping_1[T] extends (arg: any) => any ? ReturnType<Mapping_1[T]> : Self : Self : never : never;
27
+ readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_1 ? Mapping_1[T_1] extends (arg: any) => any ? ReturnType<Mapping_1[T_1]> : Self : Self : never : never;
28
+ readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_1 ? Mapping_1[T_2] extends (arg: any) => any ? ReturnType<Mapping_1[T_2]> : Self : Self : never : never;
29
+ }>;
30
+ };
31
+ readonly fieldFromKey: {
32
+ <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_2 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
33
+ readonly insert?: string | undefined;
34
+ readonly select?: string | undefined;
35
+ readonly update?: string | undefined;
36
+ }>(mapping: Mapping_2): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_2 ? Mapping_2[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_2[K]> : S_1[K] : S_1[K]; } : {
37
+ readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_2 ? Mapping_2[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T]> : Self : Self : never : never;
38
+ readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_2 ? Mapping_2[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_1]> : Self : Self : never : never;
39
+ readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_2 ? Mapping_2[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_2]> : Self : Self : never : never;
40
+ }>;
41
+ <Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_3 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
42
+ readonly insert?: string | undefined;
43
+ readonly select?: string | undefined;
44
+ readonly update?: string | undefined;
45
+ }>(self: Self, mapping: Mapping_3): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_3 ? Mapping_3[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_3[K]> : S_1[K] : S_1[K]; } : {
46
+ readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_3 ? Mapping_3[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T]> : Self : Self : never : never;
47
+ readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_3 ? Mapping_3[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_1]> : Self : Self : never : never;
48
+ readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_3 ? Mapping_3[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_2]> : Self : Self : never : never;
49
+ }>;
50
+ };
51
+ readonly Class: <Self = never>(identifier: string) => <const Fields extends VariantSchema.Struct.Fields>(fields: Fields & VariantSchema.Struct.Validate<Fields, "insert" | "select" | "update">, annotations?: Schema.Annotations.Schema<Self, readonly []> | undefined) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Class<Self>()({ ... })`" : VariantSchema.Class<Self, Fields, VariantSchema.ExtractFields<"select", Fields, true>, Schema.Struct.Type<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Struct.Encoded<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Schema.Context<VariantSchema.ExtractFields<"select", Fields, true>[keyof VariantSchema.ExtractFields<"select", Fields, true>]>, Schema.Struct.Constructor<VariantSchema.ExtractFields<"select", Fields, true>>> & {
52
+ readonly insert: Schema.Struct<VariantSchema.ExtractFields<"insert", Fields, false> extends infer T ? { [K in keyof T]: T[K]; } : never>;
53
+ readonly select: Schema.Struct<VariantSchema.ExtractFields<"select", Fields, false> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never>;
54
+ readonly update: Schema.Struct<VariantSchema.ExtractFields<"update", Fields, false> extends infer T_2 ? { [K in keyof T_2]: T_2[K]; } : never>;
55
+ };
56
+ readonly Union: <const Members extends readonly VariantSchema.Struct<any>[]>(...members: Members) => VariantSchema.Union<Members> & VariantSchema.Union.Variants<Members, "insert" | "select" | "update">;
57
+ readonly extract: {
58
+ <V extends "insert" | "select" | "update">(variant: V): <A extends VariantSchema.Struct<any>>(self: A) => VariantSchema.Extract<V, A, V extends "select" ? true : false>;
59
+ <V extends "insert" | "select" | "update", A extends VariantSchema.Struct<any>>(self: A, variant: V): VariantSchema.Extract<V, A, V extends "select" ? true : false>;
60
+ };
61
+ };
62
+ /** Normalized field map used by table definitions. */
63
+ export type TableFieldMap = Record<string, AnyColumnDefinition>;
64
+ type GeneratedKeys<Fields extends TableFieldMap> = {
65
+ [K in keyof Fields]: IsGenerated<Fields[K]> extends true ? K : never;
66
+ }[keyof Fields];
67
+ type OptionalInsertKeys<Fields extends TableFieldMap> = {
68
+ [K in keyof Fields]: IsGenerated<Fields[K]> extends true ? never : IsNullable<Fields[K]> extends true ? K : HasDefault<Fields[K]> extends true ? K : never;
69
+ }[keyof Fields];
70
+ type RequiredInsertKeys<Fields extends TableFieldMap> = Exclude<keyof Fields, GeneratedKeys<Fields> | OptionalInsertKeys<Fields>>;
71
+ type UpdateKeys<Fields extends TableFieldMap, PrimaryKey extends keyof Fields> = Exclude<keyof Fields, GeneratedKeys<Fields> | PrimaryKey>;
72
+ type Simplify<T> = {
73
+ [K in keyof T]: T[K];
74
+ } & {};
75
+ type BrandedValue<Value, BrandName extends string> = [Extract<Value, null | undefined>] extends [never] ? Value & Brand.Brand<BrandName> : (Exclude<Value, null | undefined> & Brand.Brand<BrandName>) | Extract<Value, null | undefined>;
76
+ type BrandNameOf<TableName extends string, ColumnName extends string> = `${TableName}.${ColumnName}`;
77
+ type BrandedSelectType<Column extends AnyColumnDefinition, TableName extends string, ColumnName extends string> = Column["metadata"]["brand"] extends true ? BrandedValue<SelectType<Column>, BrandNameOf<TableName, ColumnName>> : SelectType<Column>;
78
+ type BrandedInsertType<Column extends AnyColumnDefinition, TableName extends string, ColumnName extends string> = Column["metadata"]["brand"] extends true ? BrandedValue<InsertType<Column>, BrandNameOf<TableName, ColumnName>> : InsertType<Column>;
79
+ type BrandedUpdateType<Column extends AnyColumnDefinition, TableName extends string, ColumnName extends string> = Column["metadata"]["brand"] extends true ? BrandedValue<UpdateType<Column>, BrandNameOf<TableName, ColumnName>> : UpdateType<Column>;
80
+ /** Row shape returned by selecting from a table. */
81
+ export type SelectRow<TableName extends string, Fields extends TableFieldMap> = Simplify<{
82
+ [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>;
83
+ }>;
84
+ /** Insert payload derived from a table field map. */
85
+ export type InsertRow<TableName extends string, Fields extends TableFieldMap> = Simplify<{
86
+ [K in RequiredInsertKeys<Fields>]: BrandedInsertType<Fields[K], TableName, Extract<K, string>>;
87
+ } & {
88
+ [K in OptionalInsertKeys<Fields>]?: BrandedInsertType<Fields[K], TableName, Extract<K, string>>;
89
+ }>;
90
+ /** Update payload derived from a table field map and primary key. */
91
+ export type UpdateRow<TableName extends string, Fields extends TableFieldMap, PrimaryKey extends keyof Fields> = Simplify<Partial<{
92
+ [K in UpdateKeys<Fields, PrimaryKey>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>;
93
+ }>>;
94
+ /**
95
+ * Derives the `select`, `insert`, and `update` schemas for a table.
96
+ *
97
+ * This is the central place where the column capability flags are turned into
98
+ * real runtime schemas.
99
+ */
100
+ export declare const deriveSchemas: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => {
101
+ readonly select: Schema.Schema<{ [K in keyof { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }]: { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }[K]; }, { [K in keyof { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }]: { [K in keyof Fields]: BrandedSelectType<Fields[K], TableName, Extract<K, string>>; }[K]; }, never>;
102
+ readonly insert: Schema.Schema<{ [K in Exclude<keyof Fields, GeneratedKeys<Fields> | OptionalInsertKeys<Fields>>]: BrandedInsertType<Fields[K], TableName, Extract<K, string>>; } & { [K in OptionalInsertKeys<Fields>]?: BrandedInsertType<Fields[K], TableName, Extract<K, string>> | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never, { [K in Exclude<keyof Fields, GeneratedKeys<Fields> | OptionalInsertKeys<Fields>>]: BrandedInsertType<Fields[K], TableName, Extract<K, string>>; } & { [K in OptionalInsertKeys<Fields>]?: BrandedInsertType<Fields[K], TableName, Extract<K, string>> | undefined; } extends infer T ? { [K in keyof T]: T[K]; } : never, never>;
103
+ readonly update: Schema.Schema<Partial<{ [K in Exclude<keyof Fields, PrimaryKeyColumns | GeneratedKeys<Fields>>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>; }> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never, Partial<{ [K in Exclude<keyof Fields, PrimaryKeyColumns | GeneratedKeys<Fields>>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>; }> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never, never>;
104
+ };
105
+ export {};
@@ -0,0 +1,18 @@
1
+ import { type Expr } from "pgsql-ast-parser";
2
+ import { type Pipeable } from "effect/Pipeable";
3
+ export declare const TypeId: unique symbol;
4
+ export type TypeId = typeof TypeId;
5
+ export interface SchemaExpression extends Pipeable {
6
+ readonly [TypeId]: {
7
+ readonly ast?: Expr;
8
+ readonly sql?: string;
9
+ };
10
+ }
11
+ export type Any = SchemaExpression;
12
+ export declare const isSchemaExpression: (value: unknown) => value is SchemaExpression;
13
+ export declare const fromAst: (ast: Expr) => SchemaExpression;
14
+ export declare const fromSql: (sql: string) => SchemaExpression;
15
+ export declare const parseExpression: (sql: string) => SchemaExpression;
16
+ export declare const toAst: (expression: SchemaExpression) => Expr;
17
+ export declare const render: (expression: SchemaExpression) => string;
18
+ export declare const normalize: (expression: SchemaExpression) => SchemaExpression;
@@ -11,10 +11,21 @@ const SchemaExpressionProto = {
11
11
  }
12
12
  }
13
13
 
14
+ const attachPipe = <Value extends object>(value: Value): Value => {
15
+ Object.defineProperty(value, "pipe", {
16
+ configurable: true,
17
+ writable: true,
18
+ value: function(this: unknown) {
19
+ return pipeArguments(value, arguments)
20
+ }
21
+ })
22
+ return value
23
+ }
24
+
14
25
  export interface SchemaExpression extends Pipeable {
15
26
  readonly [TypeId]: {
16
- readonly dialect: "postgres"
17
- readonly ast: Expr
27
+ readonly ast?: Expr
28
+ readonly sql?: string
18
29
  }
19
30
  }
20
31
 
@@ -24,21 +35,41 @@ export const isSchemaExpression = (value: unknown): value is SchemaExpression =>
24
35
  typeof value === "object" && value !== null && TypeId in value
25
36
 
26
37
  export const fromAst = (ast: Expr): SchemaExpression => {
27
- const expression = Object.create(SchemaExpressionProto)
38
+ const expression = attachPipe(Object.create(SchemaExpressionProto))
28
39
  expression[TypeId] = {
29
- dialect: "postgres",
30
40
  ast
31
41
  }
32
42
  return expression
33
43
  }
34
44
 
45
+ export const fromSql = (sql: string): SchemaExpression => {
46
+ const expression = attachPipe(Object.create(SchemaExpressionProto))
47
+ expression[TypeId] = {
48
+ sql: sql.trim()
49
+ }
50
+ return expression
51
+ }
52
+
35
53
  export const parseExpression = (sql: string): SchemaExpression =>
36
54
  fromAst(parse(sql, "expr"))
37
55
 
38
- export const toAst = (expression: SchemaExpression): Expr => expression[TypeId].ast
56
+ export const toAst = (expression: SchemaExpression): Expr => {
57
+ const ast = expression[TypeId].ast
58
+ if (ast !== undefined) {
59
+ return ast
60
+ }
61
+ return parse(render(expression), "expr")
62
+ }
39
63
 
40
64
  export const render = (expression: SchemaExpression): string =>
41
- toSql.expr(expression[TypeId].ast)
65
+ expression[TypeId].sql ?? toSql.expr(toAst(expression))
42
66
 
43
67
  export const normalize = (expression: SchemaExpression): SchemaExpression =>
44
- parseExpression(render(expression))
68
+ (() => {
69
+ const sql = render(expression)
70
+ try {
71
+ return parseExpression(sql)
72
+ } catch {
73
+ return fromSql(sql)
74
+ }
75
+ })()
@@ -0,0 +1,94 @@
1
+ import { type AnyColumnDefinition, type IsNullable } from "./column-state.js";
2
+ import type { Any as AnyExpression } from "./scalar.js";
3
+ import type { Any as AnySchemaExpression } from "./schema-expression.js";
4
+ import type { TableFieldMap } from "./schema-derivation.js";
5
+ /** Non-empty list of column names. */
6
+ export type ColumnList = readonly [string, ...string[]];
7
+ export type DdlExpressionLike = AnyExpression | AnySchemaExpression;
8
+ export type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault";
9
+ export type IndexKeySpec = {
10
+ readonly kind: "column";
11
+ readonly column: string;
12
+ readonly order?: "asc" | "desc";
13
+ readonly nulls?: "first" | "last";
14
+ readonly operatorClass?: string;
15
+ readonly collation?: string;
16
+ } | {
17
+ readonly kind: "expression";
18
+ readonly expression: DdlExpressionLike;
19
+ readonly order?: "asc" | "desc";
20
+ readonly nulls?: "first" | "last";
21
+ readonly operatorClass?: string;
22
+ readonly collation?: string;
23
+ };
24
+ /** Normalized table-level option record. */
25
+ export type TableOptionSpec = {
26
+ readonly kind: "index";
27
+ readonly columns?: ColumnList;
28
+ readonly name?: string;
29
+ readonly unique?: boolean;
30
+ readonly method?: string;
31
+ readonly include?: readonly string[];
32
+ readonly predicate?: DdlExpressionLike;
33
+ readonly keys?: readonly [IndexKeySpec, ...IndexKeySpec[]];
34
+ } | {
35
+ readonly kind: "unique";
36
+ readonly columns: ColumnList;
37
+ readonly name?: string;
38
+ readonly nullsNotDistinct?: boolean;
39
+ readonly deferrable?: boolean;
40
+ readonly initiallyDeferred?: boolean;
41
+ } | {
42
+ readonly kind: "primaryKey";
43
+ readonly columns: ColumnList;
44
+ readonly name?: string;
45
+ readonly deferrable?: boolean;
46
+ readonly initiallyDeferred?: boolean;
47
+ } | {
48
+ readonly kind: "foreignKey";
49
+ readonly columns: ColumnList;
50
+ readonly name?: string;
51
+ readonly references: () => {
52
+ readonly tableName: string;
53
+ readonly schemaName?: string;
54
+ readonly columns: ColumnList;
55
+ readonly knownColumns?: readonly string[];
56
+ };
57
+ readonly onUpdate?: ReferentialAction;
58
+ readonly onDelete?: ReferentialAction;
59
+ readonly deferrable?: boolean;
60
+ readonly initiallyDeferred?: boolean;
61
+ } | {
62
+ readonly kind: "check";
63
+ readonly name: string;
64
+ readonly predicate: DdlExpressionLike;
65
+ readonly noInherit?: boolean;
66
+ };
67
+ /** Thin wrapper used by the public `Table.*` option builders. */
68
+ export interface TableOptionBuilder<Spec extends TableOptionSpec = TableOptionSpec> {
69
+ readonly option: Spec;
70
+ }
71
+ /** Collection of declared table options. */
72
+ export type DeclaredTableOptions = readonly TableOptionBuilder[];
73
+ type ColumnNameUnion<Fields extends TableFieldMap> = Extract<keyof Fields, string>;
74
+ type NullableColumnNames<Fields extends TableFieldMap> = {
75
+ [K in keyof Fields]: Fields[K] extends AnyColumnDefinition ? IsNullable<Fields[K]> extends true ? K : never : never;
76
+ }[keyof Fields];
77
+ type TupleFromColumns<Columns> = Columns extends readonly [infer Head extends string, ...infer Tail extends string[]] ? readonly [Head, ...Tail] : Columns extends readonly string[] ? Columns extends readonly [string, ...string[]] ? Columns : never : Columns extends string ? readonly [Columns] : never;
78
+ type AssertKnownColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = Exclude<Columns[number], ColumnNameUnion<Fields>> extends never ? Columns : never;
79
+ type AssertPrimaryKeyColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = Extract<Columns[number], NullableColumnNames<Fields>> extends never ? Columns : never;
80
+ /** Normalizes a string or tuple input into a non-empty column list. */
81
+ export declare const normalizeColumnList: (columns: string | readonly string[]) => ColumnList;
82
+ /** Converts inline column flags into normalized table option records. */
83
+ export declare const collectInlineOptions: <Fields extends TableFieldMap>(fields: Fields) => readonly TableOptionSpec[];
84
+ /** Resolves the effective primary-key columns for a table. */
85
+ export declare const resolvePrimaryKeyColumns: <Fields extends TableFieldMap>(fields: Fields, declaredOptions: readonly TableOptionSpec[]) => readonly (keyof Fields & string)[];
86
+ /** Validates that options reference known, legal columns for the table. */
87
+ export declare const validateOptions: <Fields extends TableFieldMap>(tableName: string, fields: Fields, options: readonly TableOptionSpec[]) => void;
88
+ /** Compile-time validation that option columns exist on the table. */
89
+ export type ValidateKnownColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = AssertKnownColumns<Fields, Columns>;
90
+ /** Compile-time validation that primary-key columns are known and non-nullable. */
91
+ export type ValidatePrimaryKeyColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = AssertPrimaryKeyColumns<Fields, AssertKnownColumns<Fields, Columns>>;
92
+ /** Normalizes a public column input into the internal tuple form. */
93
+ export type NormalizeColumns<Columns extends string | readonly string[]> = TupleFromColumns<Columns>;
94
+ export {};
@@ -4,7 +4,7 @@ import {
4
4
  type AnyColumnDefinition,
5
5
  type IsNullable
6
6
  } from "./column-state.js"
7
- import type { Any as AnyExpression } from "./expression.js"
7
+ import type { Any as AnyExpression } from "./scalar.js"
8
8
  import type { Any as AnySchemaExpression } from "./schema-expression.js"
9
9
  import type { TableFieldMap } from "./schema-derivation.js"
10
10
 
@@ -21,12 +21,16 @@ export type IndexKeySpec =
21
21
  readonly column: string
22
22
  readonly order?: "asc" | "desc"
23
23
  readonly nulls?: "first" | "last"
24
+ readonly operatorClass?: string
25
+ readonly collation?: string
24
26
  }
25
27
  | {
26
28
  readonly kind: "expression"
27
29
  readonly expression: DdlExpressionLike
28
30
  readonly order?: "asc" | "desc"
29
31
  readonly nulls?: "first" | "last"
32
+ readonly operatorClass?: string
33
+ readonly collation?: string
30
34
  }
31
35
 
32
36
  /** Normalized table-level option record. */
@@ -182,7 +186,9 @@ export const collectInlineOptions = <Fields extends TableFieldMap>(
182
186
  kind: "column",
183
187
  column: columnName,
184
188
  order: column.metadata.index.order,
185
- nulls: column.metadata.index.nulls
189
+ nulls: column.metadata.index.nulls,
190
+ operatorClass: column.metadata.index.operatorClass,
191
+ collation: column.metadata.index.collation
186
192
  }],
187
193
  name: column.metadata.index.name,
188
194
  method: column.metadata.index.method,