@drzl/validation-core 2.1.0 → 3.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/dist/acorn-XYPTJ6WH.js +3181 -0
- package/dist/angular-YPOYMZ5Z.js +3629 -0
- package/dist/babel-3Y2WL4BG.js +7335 -0
- package/dist/chunk-ZZGILH5A.js +24 -0
- package/dist/estree-PS47G6OA.js +4955 -0
- package/dist/flow-7NIIFLZC.js +4998 -0
- package/dist/{glimmer-MBEW7BEA.js → glimmer-HA3GA4CF.js} +1235 -1154
- package/dist/graphql-3AZLP5TQ.js +1289 -0
- package/dist/html-WHLWODCM.js +3218 -0
- package/dist/index.cjs +62660 -78352
- package/dist/index.d.cts +66 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +44 -6
- package/dist/markdown-Q4JIPTFK.js +6803 -0
- package/dist/meriyah-PDYHQKRL.js +2737 -0
- package/dist/{postcss-Y427BJX7.js → postcss-66ZEKHWQ.js} +1897 -1745
- package/dist/{prettier-Y62OQ7O7.js → prettier-LT6G5PW7.js} +11352 -11114
- package/dist/typescript-Z6ME4ZZC.js +13435 -0
- package/dist/yaml-QEX7HYMI.js +4833 -0
- package/package.json +4 -4
- package/dist/acorn-INHVMR4C.js +0 -3152
- package/dist/angular-PLJ22ADZ.js +0 -2806
- package/dist/babel-CVYK62HY.js +0 -7246
- package/dist/chunk-MKBO26DX.js +0 -12
- package/dist/estree-MDGIBSVU.js +0 -4395
- package/dist/flow-JY4PURRI.js +0 -27251
- package/dist/graphql-MN6GABOM.js +0 -1260
- package/dist/html-IVOJHMRV.js +0 -2796
- package/dist/markdown-57GKYE4Z.js +0 -3540
- package/dist/meriyah-CFHRTLLB.js +0 -2634
- package/dist/typescript-EHLMTNRR.js +0 -13208
- package/dist/yaml-2W2UYV55.js +0 -4226
package/dist/index.d.cts
CHANGED
|
@@ -173,6 +173,56 @@ declare function typeName(mode: NameMode, tsName: string, affix: ResolvedAffix):
|
|
|
173
173
|
*/
|
|
174
174
|
declare function validateAffix(affix?: AffixOptions, schemaSuffix?: string): AffixIssue[];
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Turning a SQL CHECK constraint into something a validator can enforce.
|
|
178
|
+
*
|
|
179
|
+
* No official Drizzle validator module does this. Verified against `drizzle-orm/zod` at
|
|
180
|
+
* 1.0.0-rc.4: a table with `check('age_adult', sql`${t.age} >= 18`)` produces an insert schema
|
|
181
|
+
* that accepts `{ age: 5 }`. The constraint is in the schema, the database will reject the row,
|
|
182
|
+
* and the validator says nothing.
|
|
183
|
+
*
|
|
184
|
+
* Only expressions whose meaning is unambiguous are translated. Everything else is reported and
|
|
185
|
+
* skipped, because a validator that quietly enforces a *guess* at your constraint is worse than
|
|
186
|
+
* one that enforces nothing: it rejects rows the database would have accepted.
|
|
187
|
+
*
|
|
188
|
+
* Two pieces of SQL semantics that a naive translation gets wrong:
|
|
189
|
+
*
|
|
190
|
+
* 1. **A CHECK passes when it evaluates to TRUE *or NULL*.** So `CHECK (age >= 18)` on a
|
|
191
|
+
* nullable column accepts NULL. Emitting `.gte(18)` on the inner type and applying
|
|
192
|
+
* `.nullable()` around it reproduces that exactly, which is why the constraint belongs on the
|
|
193
|
+
* base expression rather than on the whole field.
|
|
194
|
+
* 2. **A multi-column check cannot live on a field.** `start_date < end_date` is a statement
|
|
195
|
+
* about the row, so it is not returned here at all.
|
|
196
|
+
*/
|
|
197
|
+
/** A comparison of one column against one literal, which is the case worth translating. */
|
|
198
|
+
interface ColumnCheck {
|
|
199
|
+
/** Column the constraint is about, as it appears in the expression. */
|
|
200
|
+
column: string;
|
|
201
|
+
operator: '>=' | '>' | '<=' | '<' | '=' | '<>';
|
|
202
|
+
/** The literal, still as text: a 64 bit bound must not pass through a JS number. */
|
|
203
|
+
value: string;
|
|
204
|
+
/** Whether the literal was quoted, which distinguishes `'5'` from `5`. */
|
|
205
|
+
kind: 'number' | 'string';
|
|
206
|
+
/** Constraint name, used to say which one failed. */
|
|
207
|
+
name?: string;
|
|
208
|
+
}
|
|
209
|
+
/** A check that was understood, or the reason it was not. */
|
|
210
|
+
type ParsedCheck = {
|
|
211
|
+
ok: true;
|
|
212
|
+
checks: ColumnCheck[];
|
|
213
|
+
} | {
|
|
214
|
+
ok: false;
|
|
215
|
+
reason: string;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Parse one check expression.
|
|
219
|
+
*
|
|
220
|
+
* Deliberately narrow. `BETWEEN` is included because it is common and means exactly two
|
|
221
|
+
* inclusive bounds; `AND` of arbitrary predicates is not, because getting its scope wrong would
|
|
222
|
+
* silently change what is enforced.
|
|
223
|
+
*/
|
|
224
|
+
declare function parseCheck(expression: string | undefined, name?: string): ParsedCheck;
|
|
225
|
+
|
|
176
226
|
interface Table {
|
|
177
227
|
name: string;
|
|
178
228
|
tsName: string;
|
|
@@ -223,10 +273,24 @@ interface ValidationRenderer<TOptions extends ValidationGenerateOptions = Valida
|
|
|
223
273
|
renderIndex?(analysis: Analysis, opts?: TOptions): string;
|
|
224
274
|
generate(opts: TOptions): Promise<string[]>;
|
|
225
275
|
}
|
|
226
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Whether the database generates this column's value, so it cannot be written.
|
|
278
|
+
*
|
|
279
|
+
* `primaryKeyColumns` is accepted for backwards compatibility and no longer consulted. It used
|
|
280
|
+
* to make every primary key count as generated, which dropped it from the insert schema whether
|
|
281
|
+
* or not the database supplied it. Right for a MySQL autoincrement column; wrong for a Postgres
|
|
282
|
+
* `integer('id').primaryKey()`, which Postgres does not generate, and for any natural key such
|
|
283
|
+
* as `text('slug').primaryKey()`. Those inserts became impossible to express: the required
|
|
284
|
+
* column was simply absent, with no way to provide it.
|
|
285
|
+
*
|
|
286
|
+
* Being a key says nothing about who supplies the value. `isGenerated` marks a column that
|
|
287
|
+
* cannot be written; `hasDefault` marks one that need not be, and those stay in the schema as
|
|
288
|
+
* optional.
|
|
289
|
+
*/
|
|
290
|
+
declare function isGeneratedColumn(c: Column, _primaryKeyColumns?: string[]): boolean;
|
|
227
291
|
declare function insertColumns(table: Table): Column[];
|
|
228
292
|
declare function updateColumns(table: Table): Column[];
|
|
229
293
|
declare function selectColumns(table: Table): Column[];
|
|
230
294
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
231
295
|
|
|
232
|
-
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ResolvedAffix, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, formatCode, importSpecifier, insertColumns, isGeneratedColumn, moduleFileName, moduleSpecifier, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
|
296
|
+
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, type ColumnCheck, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, formatCode, importSpecifier, insertColumns, isGeneratedColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
package/dist/index.d.ts
CHANGED
|
@@ -173,6 +173,56 @@ declare function typeName(mode: NameMode, tsName: string, affix: ResolvedAffix):
|
|
|
173
173
|
*/
|
|
174
174
|
declare function validateAffix(affix?: AffixOptions, schemaSuffix?: string): AffixIssue[];
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Turning a SQL CHECK constraint into something a validator can enforce.
|
|
178
|
+
*
|
|
179
|
+
* No official Drizzle validator module does this. Verified against `drizzle-orm/zod` at
|
|
180
|
+
* 1.0.0-rc.4: a table with `check('age_adult', sql`${t.age} >= 18`)` produces an insert schema
|
|
181
|
+
* that accepts `{ age: 5 }`. The constraint is in the schema, the database will reject the row,
|
|
182
|
+
* and the validator says nothing.
|
|
183
|
+
*
|
|
184
|
+
* Only expressions whose meaning is unambiguous are translated. Everything else is reported and
|
|
185
|
+
* skipped, because a validator that quietly enforces a *guess* at your constraint is worse than
|
|
186
|
+
* one that enforces nothing: it rejects rows the database would have accepted.
|
|
187
|
+
*
|
|
188
|
+
* Two pieces of SQL semantics that a naive translation gets wrong:
|
|
189
|
+
*
|
|
190
|
+
* 1. **A CHECK passes when it evaluates to TRUE *or NULL*.** So `CHECK (age >= 18)` on a
|
|
191
|
+
* nullable column accepts NULL. Emitting `.gte(18)` on the inner type and applying
|
|
192
|
+
* `.nullable()` around it reproduces that exactly, which is why the constraint belongs on the
|
|
193
|
+
* base expression rather than on the whole field.
|
|
194
|
+
* 2. **A multi-column check cannot live on a field.** `start_date < end_date` is a statement
|
|
195
|
+
* about the row, so it is not returned here at all.
|
|
196
|
+
*/
|
|
197
|
+
/** A comparison of one column against one literal, which is the case worth translating. */
|
|
198
|
+
interface ColumnCheck {
|
|
199
|
+
/** Column the constraint is about, as it appears in the expression. */
|
|
200
|
+
column: string;
|
|
201
|
+
operator: '>=' | '>' | '<=' | '<' | '=' | '<>';
|
|
202
|
+
/** The literal, still as text: a 64 bit bound must not pass through a JS number. */
|
|
203
|
+
value: string;
|
|
204
|
+
/** Whether the literal was quoted, which distinguishes `'5'` from `5`. */
|
|
205
|
+
kind: 'number' | 'string';
|
|
206
|
+
/** Constraint name, used to say which one failed. */
|
|
207
|
+
name?: string;
|
|
208
|
+
}
|
|
209
|
+
/** A check that was understood, or the reason it was not. */
|
|
210
|
+
type ParsedCheck = {
|
|
211
|
+
ok: true;
|
|
212
|
+
checks: ColumnCheck[];
|
|
213
|
+
} | {
|
|
214
|
+
ok: false;
|
|
215
|
+
reason: string;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Parse one check expression.
|
|
219
|
+
*
|
|
220
|
+
* Deliberately narrow. `BETWEEN` is included because it is common and means exactly two
|
|
221
|
+
* inclusive bounds; `AND` of arbitrary predicates is not, because getting its scope wrong would
|
|
222
|
+
* silently change what is enforced.
|
|
223
|
+
*/
|
|
224
|
+
declare function parseCheck(expression: string | undefined, name?: string): ParsedCheck;
|
|
225
|
+
|
|
176
226
|
interface Table {
|
|
177
227
|
name: string;
|
|
178
228
|
tsName: string;
|
|
@@ -223,10 +273,24 @@ interface ValidationRenderer<TOptions extends ValidationGenerateOptions = Valida
|
|
|
223
273
|
renderIndex?(analysis: Analysis, opts?: TOptions): string;
|
|
224
274
|
generate(opts: TOptions): Promise<string[]>;
|
|
225
275
|
}
|
|
226
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Whether the database generates this column's value, so it cannot be written.
|
|
278
|
+
*
|
|
279
|
+
* `primaryKeyColumns` is accepted for backwards compatibility and no longer consulted. It used
|
|
280
|
+
* to make every primary key count as generated, which dropped it from the insert schema whether
|
|
281
|
+
* or not the database supplied it. Right for a MySQL autoincrement column; wrong for a Postgres
|
|
282
|
+
* `integer('id').primaryKey()`, which Postgres does not generate, and for any natural key such
|
|
283
|
+
* as `text('slug').primaryKey()`. Those inserts became impossible to express: the required
|
|
284
|
+
* column was simply absent, with no way to provide it.
|
|
285
|
+
*
|
|
286
|
+
* Being a key says nothing about who supplies the value. `isGenerated` marks a column that
|
|
287
|
+
* cannot be written; `hasDefault` marks one that need not be, and those stay in the schema as
|
|
288
|
+
* optional.
|
|
289
|
+
*/
|
|
290
|
+
declare function isGeneratedColumn(c: Column, _primaryKeyColumns?: string[]): boolean;
|
|
227
291
|
declare function insertColumns(table: Table): Column[];
|
|
228
292
|
declare function updateColumns(table: Table): Column[];
|
|
229
293
|
declare function selectColumns(table: Table): Column[];
|
|
230
294
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
231
295
|
|
|
232
|
-
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ResolvedAffix, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, formatCode, importSpecifier, insertColumns, isGeneratedColumn, moduleFileName, moduleSpecifier, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
|
296
|
+
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, type ColumnCheck, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, formatCode, importSpecifier, insertColumns, isGeneratedColumn, moduleFileName, moduleSpecifier, parseCheck, pascalCase, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-ZZGILH5A.js";
|
|
2
|
+
|
|
3
|
+
// src/checks.ts
|
|
4
|
+
var COMPARISON = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*(>=|<=|<>|!=|>|<|=)\s*(.+?)\s*$/;
|
|
5
|
+
var BETWEEN = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s+BETWEEN\s+(.+?)\s+AND\s+(.+?)\s*$/i;
|
|
6
|
+
function literal(raw) {
|
|
7
|
+
const t = raw.trim();
|
|
8
|
+
if (/^-?\d+(\.\d+)?$/.test(t)) return { value: t, kind: "number" };
|
|
9
|
+
const m = t.match(/^'((?:[^']|'')*)'$/);
|
|
10
|
+
if (m) return { value: m[1].replace(/''/g, "'"), kind: "string" };
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
function parseCheck(expression, name) {
|
|
14
|
+
const expr = (expression ?? "").trim();
|
|
15
|
+
if (!expr) return { ok: false, reason: "empty expression" };
|
|
16
|
+
if (expr.includes("?")) return { ok: false, reason: "expression contains an unresolved value" };
|
|
17
|
+
const between = expr.match(BETWEEN);
|
|
18
|
+
if (between) {
|
|
19
|
+
const lo = literal(between[2]);
|
|
20
|
+
const hi = literal(between[3]);
|
|
21
|
+
if (!lo || !hi) return { ok: false, reason: "BETWEEN bounds are not literals" };
|
|
22
|
+
if (lo.kind !== hi.kind) return { ok: false, reason: "BETWEEN bounds are of mixed types" };
|
|
23
|
+
return {
|
|
24
|
+
ok: true,
|
|
25
|
+
checks: [
|
|
26
|
+
{ column: between[1], operator: ">=", value: lo.value, kind: lo.kind, name },
|
|
27
|
+
{ column: between[1], operator: "<=", value: hi.value, kind: hi.kind, name }
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const cmp = expr.match(COMPARISON);
|
|
32
|
+
if (!cmp) return { ok: false, reason: "not a single comparison this version understands" };
|
|
33
|
+
const value = literal(cmp[3]);
|
|
34
|
+
if (!value) {
|
|
35
|
+
return { ok: false, reason: "right side is not a literal" };
|
|
36
|
+
}
|
|
37
|
+
const op = cmp[2] === "!=" ? "<>" : cmp[2];
|
|
38
|
+
return { ok: true, checks: [{ column: cmp[1], operator: op, value: value.value, kind: value.kind, name }] };
|
|
39
|
+
}
|
|
2
40
|
|
|
3
41
|
// src/files.ts
|
|
4
42
|
import nodeFs from "fs";
|
|
@@ -166,12 +204,11 @@ function validateAffix(affix, schemaSuffix) {
|
|
|
166
204
|
}
|
|
167
205
|
|
|
168
206
|
// src/index.ts
|
|
169
|
-
function isGeneratedColumn(c,
|
|
170
|
-
return c.isGenerated
|
|
207
|
+
function isGeneratedColumn(c, _primaryKeyColumns = []) {
|
|
208
|
+
return c.isGenerated;
|
|
171
209
|
}
|
|
172
210
|
function insertColumns(table) {
|
|
173
|
-
|
|
174
|
-
return table.columns.filter((c) => !isGeneratedColumn(c, pkCols));
|
|
211
|
+
return table.columns.filter((c) => !isGeneratedColumn(c));
|
|
175
212
|
}
|
|
176
213
|
function updateColumns(table) {
|
|
177
214
|
const pkCols = table.primaryKey?.columns ?? [];
|
|
@@ -185,7 +222,7 @@ async function formatCode(code, filePath, fmt) {
|
|
|
185
222
|
const engine = fmt?.engine ?? "auto";
|
|
186
223
|
try {
|
|
187
224
|
if (engine === "prettier" || engine === "auto") {
|
|
188
|
-
const prettier = await import("./prettier-
|
|
225
|
+
const prettier = await import("./prettier-LT6G5PW7.js");
|
|
189
226
|
const cfgRef = fmt?.configPath ?? filePath;
|
|
190
227
|
const cfg = await prettier.resolveConfig(cfgRef).catch(() => null);
|
|
191
228
|
return prettier.format(code, { ...cfg ?? {}, parser: "typescript", filepath: filePath });
|
|
@@ -220,6 +257,7 @@ export {
|
|
|
220
257
|
isGeneratedColumn,
|
|
221
258
|
moduleFileName,
|
|
222
259
|
moduleSpecifier,
|
|
260
|
+
parseCheck,
|
|
223
261
|
pascalCase,
|
|
224
262
|
resolveAffix,
|
|
225
263
|
resolveConfiguredImport,
|