@thomasfosterau/effect-drizzle-ext 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +508 -2
- package/dist/columns.d.ts +113 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +146 -0
- package/dist/columns.js.map +1 -0
- package/dist/constraints.d.ts +117 -0
- package/dist/constraints.d.ts.map +1 -0
- package/dist/constraints.js +93 -0
- package/dist/constraints.js.map +1 -0
- package/dist/database.d.ts +189 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +51 -0
- package/dist/database.js.map +1 -0
- package/dist/derive.d.ts +97 -0
- package/dist/derive.d.ts.map +1 -0
- package/dist/derive.js +142 -0
- package/dist/derive.js.map +1 -0
- package/dist/errors.d.ts +157 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +287 -0
- package/dist/errors.js.map +1 -0
- package/dist/index-CFhgcF4N.d.ts +418 -0
- package/dist/index-CFhgcF4N.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/jsonapi/derive.d.ts +28 -0
- package/dist/jsonapi/derive.d.ts.map +1 -0
- package/dist/jsonapi/derive.js +28 -0
- package/dist/jsonapi/derive.js.map +1 -0
- package/dist/jsonapi/index.d.ts +189 -0
- package/dist/jsonapi/index.d.ts.map +1 -0
- package/dist/jsonapi/index.js +164 -0
- package/dist/jsonapi/index.js.map +1 -0
- package/dist/query.d.ts +111 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +142 -0
- package/dist/query.js.map +1 -0
- package/dist/references.d.ts +38 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +60 -0
- package/dist/references.js.map +1 -0
- package/dist/sort.d.ts +129 -0
- package/dist/sort.d.ts.map +1 -0
- package/dist/sort.js +225 -0
- package/dist/sort.js.map +1 -0
- package/dist/src-CBeuhy5b.js +478 -0
- package/dist/src-CBeuhy5b.js.map +1 -0
- package/dist/update.d.ts +61 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +64 -0
- package/dist/update.js.map +1 -0
- package/dist/versioned-chain.d.ts +524 -0
- package/dist/versioned-chain.d.ts.map +1 -0
- package/dist/versioned-chain.js +298 -0
- package/dist/versioned-chain.js.map +1 -0
- package/package.json +102 -4
- package/src/columns.ts +186 -0
- package/src/constraints.ts +225 -0
- package/src/database.ts +273 -0
- package/src/derivation-error.ts +27 -0
- package/src/derive.ts +320 -0
- package/src/errors.ts +466 -0
- package/src/index.ts +653 -0
- package/src/jsonapi/derive.ts +74 -0
- package/src/jsonapi/index.ts +355 -0
- package/src/query.ts +183 -0
- package/src/references.ts +103 -0
- package/src/sort.ts +368 -0
- package/src/tree.ts +367 -0
- package/src/update.ts +88 -0
- package/src/versioned-chain.ts +1027 -0
package/src/derive.ts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Thomas Foster
|
|
3
|
+
*
|
|
4
|
+
* **Effect Schema → Drizzle derivation: the derivation entry (Drizzle).**
|
|
5
|
+
*
|
|
6
|
+
* Reads the {@link DbColumn} metadata a schema declaration carries (via
|
|
7
|
+
* {@link fieldColumns} from the {@link ./index.ts} annotation entry, or via any
|
|
8
|
+
* other projection that yields a `Record<string, DbColumn>`) and emits the
|
|
9
|
+
* matching Drizzle column builders. Depends on Drizzle, so a model / client
|
|
10
|
+
* layer importing only the annotation entry never pulls the ORM.
|
|
11
|
+
*
|
|
12
|
+
* **Extensible column kinds.** The kind → builder mapping is *injected*, not
|
|
13
|
+
* baked in: a consumer passes a builder registry (a record from its own kind
|
|
14
|
+
* union to a Drizzle column builder) to {@link makeDeriveColumns}, and the
|
|
15
|
+
* derivation preserves each column's precise builder type — so the derived
|
|
16
|
+
* column map keeps `$inferSelect` typed — by reading the type-level phantom
|
|
17
|
+
* `dbColumn` stamps alongside the runtime annotation.
|
|
18
|
+
*
|
|
19
|
+
* **Two entry shapes, one interpreter.** {@link makeDeriveColumns} returns both
|
|
20
|
+
* `fromFields` (a `Schema.Struct`'s fields, the generic source) and `fromMeta`
|
|
21
|
+
* (an already-projected metadata map, the seam the `./jsonapi/derive` entry and
|
|
22
|
+
* any other projection build on). They share one builder loop.
|
|
23
|
+
*
|
|
24
|
+
* **Failures here are THROWN, not Effect failures.** Everything in this module
|
|
25
|
+
* runs at *module load*, while a consumer's table modules are being evaluated —
|
|
26
|
+
* before any Effect runtime exists to run a failure in, and before any query
|
|
27
|
+
* can be issued. A misdeclared table must fail at `import`, not at first
|
|
28
|
+
* insert, so a missing builder / a missing reference hook / bounds on a column
|
|
29
|
+
* the table does not carry throw {@link DerivationError}. Runtime query
|
|
30
|
+
* failures are the opposite and are never thrown: they travel in the Effect
|
|
31
|
+
* error channel as the tagged errors of the `./errors` entry.
|
|
32
|
+
*
|
|
33
|
+
* @module derive
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { sql, type ColumnBuilderBase, type SQL } from "drizzle-orm";
|
|
37
|
+
import {
|
|
38
|
+
check,
|
|
39
|
+
type AnyPgColumn,
|
|
40
|
+
type ExtraConfigColumn,
|
|
41
|
+
type PgTableExtraConfigValue,
|
|
42
|
+
} from "drizzle-orm/pg-core";
|
|
43
|
+
import * as Arr from "effect/Array";
|
|
44
|
+
import * as R from "effect/Record";
|
|
45
|
+
import * as Schema from "effect/Schema";
|
|
46
|
+
import { DerivationError } from "./derivation-error.ts";
|
|
47
|
+
import {
|
|
48
|
+
fieldColumnBounds,
|
|
49
|
+
fieldColumns,
|
|
50
|
+
type ColumnBounds,
|
|
51
|
+
type DbColumn,
|
|
52
|
+
type DbColumnReference,
|
|
53
|
+
type FieldColumnsMetaOf,
|
|
54
|
+
} from "./index.ts";
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A construction-time derivation failure, thrown at module load when a table
|
|
58
|
+
* cannot be built from its declarations. The same class the Drizzle-free `.`
|
|
59
|
+
* entry exports (for `defineTree`), re-exported here for the table derivations.
|
|
60
|
+
*/
|
|
61
|
+
export { DerivationError };
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A registry mapping column kinds to Drizzle column builders — one builder per
|
|
65
|
+
* kind, taking the column name and returning a fresh (nullable) builder. The
|
|
66
|
+
* consumer supplies this; the package provides no fixed set.
|
|
67
|
+
*/
|
|
68
|
+
export type ColumnBuilders<Kind extends string = string> = Record<
|
|
69
|
+
Kind,
|
|
70
|
+
(column: string) => ColumnBuilderBase
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
/** The (nullable) builder a kind produces in registry `B`. */
|
|
74
|
+
type Builder<B extends ColumnBuilders, P extends keyof B> = ReturnType<B[P]>;
|
|
75
|
+
|
|
76
|
+
/** The `.notNull()` form of a builder. */
|
|
77
|
+
type NotNull<X> = X extends { notNull(): infer R } ? R : X;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The Drizzle column builder a single db-column annotation produces against
|
|
81
|
+
* registry `B`. Total over any `M` (a widened `unknown` metadata falls back to
|
|
82
|
+
* the base builder type), computing the precise builder type for a concrete
|
|
83
|
+
* `{ pg, notNull }` metadata.
|
|
84
|
+
*
|
|
85
|
+
* Exported so a projection-specific derivation (the `./jsonapi/derive` entry)
|
|
86
|
+
* can name this type without restating it.
|
|
87
|
+
*/
|
|
88
|
+
export type BuilderFor<M, B extends ColumnBuilders> = M extends {
|
|
89
|
+
readonly pg: infer P;
|
|
90
|
+
readonly notNull: infer N;
|
|
91
|
+
}
|
|
92
|
+
? P extends keyof B
|
|
93
|
+
? N extends true
|
|
94
|
+
? NotNull<Builder<B, P>>
|
|
95
|
+
: Builder<B, P>
|
|
96
|
+
: ColumnBuilderBase
|
|
97
|
+
: ColumnBuilderBase;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The Drizzle column builders a db-column metadata map produces against
|
|
101
|
+
* registry `B`, keyed and typed per entry — the type-level counterpart of the
|
|
102
|
+
* builder loop {@link makeDeriveColumns} returns.
|
|
103
|
+
*/
|
|
104
|
+
export type DerivedColumns<Meta, B extends ColumnBuilders> = {
|
|
105
|
+
readonly [K in keyof Meta]: BuilderFor<Meta[K], B>;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
* **The one statement of the `?: T | undefined` rule.** Every optional member
|
|
110
|
+
* of a config type this library hands to Drizzle — `resolveReference` below,
|
|
111
|
+
* `DiscriminatorNames`' templates in ./constraints.ts, the annotation entry's
|
|
112
|
+
* `DbColumn.default` / `.references` / `.checkName` — is spelled
|
|
113
|
+
* `?: T | undefined`, never `Option`. Drizzle reads `undefined` as "not
|
|
114
|
+
* supplied"; handed an `Option` it would emit the wrapper object as a literal
|
|
115
|
+
* value (a DEFAULT of `{_tag: "None"}`, a referential action of `[Object]`) —
|
|
116
|
+
* wrong DDL that no type error and no unit test catches, because Drizzle's
|
|
117
|
+
* config members are typed loosely enough to accept it. Readers this library
|
|
118
|
+
* owns (`readDbColumn`, `readDbTable`, `findPgError`, …) return `Option`; the
|
|
119
|
+
* conversion happens at their boundary, not in Drizzle-facing config.
|
|
120
|
+
*/
|
|
121
|
+
/* oxlint-disable effect/prefer-option-over-null -- Drizzle-facing config: Drizzle reads `undefined` as "not supplied" */
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Optional hooks for {@link makeDeriveColumns}. `resolveReference` turns a
|
|
125
|
+
* column's {@link DbColumnReference} name pair into the Drizzle column thunk
|
|
126
|
+
* `.references()` needs — the seam that lets FK-backed attributes derive their
|
|
127
|
+
* column instead of being hand-authored. Without it, a `references` annotation
|
|
128
|
+
* is a configuration error (throws), so a consumer only wires it when it
|
|
129
|
+
* declares FK columns. The `./references` entry ships one implementation.
|
|
130
|
+
*/
|
|
131
|
+
export interface DeriveOptions {
|
|
132
|
+
readonly resolveReference?: ((reference: DbColumnReference) => () => AnyPgColumn) | undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* oxlint-enable effect/prefer-option-over-null */
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A fluent view of a Drizzle column builder — the chainable `.notNull()` /
|
|
139
|
+
* `.default()` / `.references()` methods the registry's widened
|
|
140
|
+
* `ColumnBuilderBase` return type hides. Runtime-real; used only to type the
|
|
141
|
+
* dynamic build chain. Typed to exactly what the chain passes.
|
|
142
|
+
*/
|
|
143
|
+
interface FluentColumn extends ColumnBuilderBase {
|
|
144
|
+
notNull(): FluentColumn;
|
|
145
|
+
default(value: NonNullable<DbColumn["default"]>): FluentColumn;
|
|
146
|
+
references(
|
|
147
|
+
ref: () => AnyPgColumn,
|
|
148
|
+
actions: Pick<DbColumnReference, "onDelete" | "onUpdate">,
|
|
149
|
+
): FluentColumn;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The derivation pair {@link makeDeriveColumns} returns for builder registry
|
|
154
|
+
* `B`: `fromMeta` over an already-projected metadata map, `fromFields` over a
|
|
155
|
+
* `Schema.Struct`'s fields. Both throw {@link DerivationError} at module load
|
|
156
|
+
* on a misdeclared column.
|
|
157
|
+
*/
|
|
158
|
+
export interface DeriveColumns<B extends ColumnBuilders> {
|
|
159
|
+
/** Derive the builders an already-projected metadata map declares. */
|
|
160
|
+
readonly fromMeta: <Meta extends Record<string, DbColumn>>(
|
|
161
|
+
metas: Meta,
|
|
162
|
+
) => DerivedColumns<Meta, B>;
|
|
163
|
+
/** Derive the builders a `Schema.Struct`'s annotated fields declare. */
|
|
164
|
+
readonly fromFields: <F extends Schema.Struct.Fields>(
|
|
165
|
+
fields: F,
|
|
166
|
+
) => DerivedColumns<FieldColumnsMetaOf<F>, B>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Build a derivation bound to a specific builder registry. The returned pair
|
|
171
|
+
* interprets per-column `dbColumn` metadata into the Drizzle column builders a
|
|
172
|
+
* table factory's `columns` expects:
|
|
173
|
+
*
|
|
174
|
+
* - `fromFields` takes a `Schema.Struct`'s fields directly (peeling the
|
|
175
|
+
* `optional` / `NullOr` wrappers via {@link fieldColumns});
|
|
176
|
+
* - `fromMeta` takes an already-projected metadata map, for a projection this
|
|
177
|
+
* entry knows nothing about (the `./jsonapi/derive` entry is one).
|
|
178
|
+
*/
|
|
179
|
+
export const makeDeriveColumns = <B extends ColumnBuilders>(
|
|
180
|
+
builders: B,
|
|
181
|
+
options: DeriveOptions = {},
|
|
182
|
+
): DeriveColumns<B> => {
|
|
183
|
+
const buildColumn = (meta: DbColumn): ColumnBuilderBase => {
|
|
184
|
+
const build = builders[meta.pg];
|
|
185
|
+
if (build === undefined) {
|
|
186
|
+
throw new DerivationError({
|
|
187
|
+
message: `no builder registered for column kind '${meta.pg}'`,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// SAFETY: the registry widens each builder's return to `ColumnBuilderBase`,
|
|
191
|
+
// hiding the fluent `.notNull()` / `.default()` / `.references()` methods;
|
|
192
|
+
// the runtime builders are the real Drizzle ones, which carry them.
|
|
193
|
+
let column = build(meta.column) as FluentColumn;
|
|
194
|
+
if (meta.notNull) column = column.notNull();
|
|
195
|
+
if (meta.default !== undefined) column = column.default(meta.default);
|
|
196
|
+
if (meta.references !== undefined) {
|
|
197
|
+
if (options.resolveReference === undefined) {
|
|
198
|
+
throw new DerivationError({
|
|
199
|
+
message: `column '${meta.column}' declares a reference but no resolveReference hook was provided`,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const target = options.resolveReference(meta.references);
|
|
203
|
+
column = column.references(target, {
|
|
204
|
+
onDelete: meta.references.onDelete,
|
|
205
|
+
onUpdate: meta.references.onUpdate,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return column;
|
|
209
|
+
};
|
|
210
|
+
const buildColumns = (metas: Record<string, DbColumn>): Record<string, ColumnBuilderBase> =>
|
|
211
|
+
R.fromEntries(
|
|
212
|
+
Arr.map(R.toEntries(metas), ([name, meta]) => [name, buildColumn(meta)] as const),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
fromMeta: <Meta extends Record<string, DbColumn>>(metas: Meta): DerivedColumns<Meta, B> =>
|
|
217
|
+
// SAFETY: `buildColumns` maps every key of `metas` to the builder its
|
|
218
|
+
// `pg` kind selects, with `.notNull()` applied exactly when `notNull`
|
|
219
|
+
// is true — the per-entry computation `DerivedColumns` describes.
|
|
220
|
+
buildColumns(metas) as DerivedColumns<Meta, B>,
|
|
221
|
+
fromFields: <F extends Schema.Struct.Fields>(
|
|
222
|
+
fields: F,
|
|
223
|
+
): DerivedColumns<FieldColumnsMetaOf<F>, B> =>
|
|
224
|
+
// SAFETY: `fieldColumns` projects exactly the annotated fields
|
|
225
|
+
// `FieldColumnsMetaOf` keys, and `buildColumns` maps each as in `fromMeta`.
|
|
226
|
+
buildColumns(fieldColumns(fields)) as DerivedColumns<FieldColumnsMetaOf<F>, B>,
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// ── CHECK-constraint derivation ───────────────────────────────────────
|
|
231
|
+
|
|
232
|
+
/** A number rendered inline into the CHECK expression (never a bind parameter). */
|
|
233
|
+
const literal = (value: number): SQL => sql.raw(String(value));
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* The canonical constraint-name suffix a set of bounds earns: `range` when
|
|
237
|
+
* bounded on both sides; `non_negative` for the sole inclusive-minimum-of-`0`
|
|
238
|
+
* case (the established naming for count/duration columns); `min` / `max` for
|
|
239
|
+
* the remaining one-sided bounds.
|
|
240
|
+
*/
|
|
241
|
+
const boundSuffix = (bounds: ColumnBounds): string => {
|
|
242
|
+
const hasMin = bounds.minimum !== undefined || bounds.exclusiveMinimum !== undefined;
|
|
243
|
+
const hasMax = bounds.maximum !== undefined || bounds.exclusiveMaximum !== undefined;
|
|
244
|
+
if (hasMin && hasMax) return "range";
|
|
245
|
+
if (!hasMin) return "max";
|
|
246
|
+
return bounds.minimum === 0 ? "non_negative" : "min";
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/** The per-side comparisons for a bound set (exclusive bounds win their side). */
|
|
250
|
+
const comparisonParts = (column: ExtraConfigColumn, bounds: ColumnBounds): SQL[] => {
|
|
251
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum } = bounds;
|
|
252
|
+
const parts: SQL[] = [];
|
|
253
|
+
if (exclusiveMinimum !== undefined) parts.push(sql`${column} > ${literal(exclusiveMinimum)}`);
|
|
254
|
+
else if (minimum !== undefined) parts.push(sql`${column} >= ${literal(minimum)}`);
|
|
255
|
+
if (exclusiveMaximum !== undefined) parts.push(sql`${column} < ${literal(exclusiveMaximum)}`);
|
|
256
|
+
else if (maximum !== undefined) parts.push(sql`${column} <= ${literal(maximum)}`);
|
|
257
|
+
return parts;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The bound expression for one column (without the nullability guard): a
|
|
262
|
+
* both-sides-inclusive bound renders as `col BETWEEN min AND max` — matching
|
|
263
|
+
* the hand-authored year-range constraints in the consuming applications — and
|
|
264
|
+
* anything else as the {@link comparisonParts} joined with `AND`.
|
|
265
|
+
*/
|
|
266
|
+
const boundExpression = (column: ExtraConfigColumn, bounds: ColumnBounds): SQL =>
|
|
267
|
+
bounds.minimum !== undefined && bounds.maximum !== undefined
|
|
268
|
+
? sql`${column} BETWEEN ${literal(bounds.minimum)} AND ${literal(bounds.maximum)}`
|
|
269
|
+
: sql.join(comparisonParts(column, bounds), sql` AND `);
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Derive the SQL `CHECK` constraints an already-projected bounds map implies —
|
|
273
|
+
* the third leg of annotation-driven columns, after the column itself and the
|
|
274
|
+
* read-view selection. Emits one Drizzle `check()` per bounded column, named
|
|
275
|
+
* `${tableName}_${column}_${suffix}` (see {@link boundSuffix} for the canonical
|
|
276
|
+
* suffixes) unless the column annotation pins a `checkName`. A nullable
|
|
277
|
+
* column's expression is guarded with `col IS NULL OR …`, matching the
|
|
278
|
+
* hand-authored precedents.
|
|
279
|
+
*
|
|
280
|
+
* Returns a callback shaped for a table factory's `extraConstraints` seam: it
|
|
281
|
+
* receives the table's columns keyed by **attribute** name (not SQL column
|
|
282
|
+
* name). A bounded attribute whose column is absent from the table is a
|
|
283
|
+
* configuration error ({@link DerivationError}) — bounds on a column the table
|
|
284
|
+
* doesn't carry cannot be enforced.
|
|
285
|
+
*/
|
|
286
|
+
export const deriveCheckConstraintsFrom =
|
|
287
|
+
(bounds: Record<string, ColumnBounds>, tableName: string) =>
|
|
288
|
+
(table: Record<string, ExtraConfigColumn>): PgTableExtraConfigValue[] =>
|
|
289
|
+
Arr.map(R.toEntries(bounds), ([attribute, columnBounds]) => {
|
|
290
|
+
const column = table[attribute];
|
|
291
|
+
if (column === undefined) {
|
|
292
|
+
throw new DerivationError({
|
|
293
|
+
message:
|
|
294
|
+
`attribute '${attribute}' declares numeric bounds but ` +
|
|
295
|
+
`table '${tableName}' has no column for it`,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
const expression = boundExpression(column, columnBounds);
|
|
299
|
+
const guarded = columnBounds.column.notNull
|
|
300
|
+
? expression
|
|
301
|
+
: sql`${column} IS NULL OR ${expression}`;
|
|
302
|
+
const name =
|
|
303
|
+
columnBounds.column.checkName ??
|
|
304
|
+
`${tableName}_${columnBounds.column.column}_${boundSuffix(columnBounds)}`;
|
|
305
|
+
return check(name, guarded);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* {@link deriveCheckConstraintsFrom} over a `Schema.Struct`'s fields: the
|
|
310
|
+
* bounds a model's `Schema.isGreaterThanOrEqualTo` / `isBetween` checks declare
|
|
311
|
+
* ({@link fieldColumnBounds}) become the table's CHECK constraints. One
|
|
312
|
+
* declaration drives wire validation and the database constraint.
|
|
313
|
+
*
|
|
314
|
+
* The projection is deferred to the returned callback, so this composes inside
|
|
315
|
+
* a `pgTable(...)` call whose fields are still being assembled.
|
|
316
|
+
*/
|
|
317
|
+
export const deriveFieldCheckConstraints =
|
|
318
|
+
(fields: Schema.Struct.Fields, tableName: string) =>
|
|
319
|
+
(table: Record<string, ExtraConfigColumn>): PgTableExtraConfigValue[] =>
|
|
320
|
+
deriveCheckConstraintsFrom(fieldColumnBounds(fields), tableName)(table);
|