@drzl/validation-core 3.0.0 → 3.2.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 +60511 -76202
- package/dist/index.d.cts +76 -1
- package/dist/index.d.ts +76 -1
- package/dist/index.js +41 -2
- 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;
|
|
@@ -189,6 +239,31 @@ interface FormatOptions {
|
|
|
189
239
|
}
|
|
190
240
|
interface ValidationGenerateOptions {
|
|
191
241
|
outDir: string;
|
|
242
|
+
/**
|
|
243
|
+
* Path to the Drizzle schema module, as written in the config.
|
|
244
|
+
*
|
|
245
|
+
* Only needed by `typedJson`, which has to import the table back in order to reference the
|
|
246
|
+
* type Drizzle inferred for a column.
|
|
247
|
+
*/
|
|
248
|
+
schemaPath?: string;
|
|
249
|
+
/**
|
|
250
|
+
* Type `json` and `jsonb` columns from the schema instead of leaving them wide.
|
|
251
|
+
*
|
|
252
|
+
* `.$type<T>()` is a compile-time cast: Drizzle's implementation is literally
|
|
253
|
+
* `$type() { return this }`, so the type exists only in TypeScript and nothing about it
|
|
254
|
+
* survives to runtime. Every runtime-derived validator is therefore blind to it, and
|
|
255
|
+
* `drizzle-orm/zod` types a json column as its generic `Json` no matter what you declared.
|
|
256
|
+
*
|
|
257
|
+
* A generator can do better without resolving any types itself, because Drizzle already did
|
|
258
|
+
* the work: `typeof users.$inferSelect['prefs']` *is* the declared type, resolved by
|
|
259
|
+
* TypeScript at the point of use. So the emitted schema references that rather than trying to
|
|
260
|
+
* reconstruct it, which is why this works for generics, unions and imported interfaces alike,
|
|
261
|
+
* the cases that defeat source-parsing approaches.
|
|
262
|
+
*
|
|
263
|
+
* Off by default: it makes the generated file import your schema module, and that coupling
|
|
264
|
+
* should be a choice rather than a surprise.
|
|
265
|
+
*/
|
|
266
|
+
typedJson?: boolean;
|
|
192
267
|
format?: FormatOptions;
|
|
193
268
|
/**
|
|
194
269
|
* What every generated file is called after the Drizzle export name, e.g. `.zod.ts`
|
|
@@ -243,4 +318,4 @@ declare function updateColumns(table: Table): Column[];
|
|
|
243
318
|
declare function selectColumns(table: Table): Column[];
|
|
244
319
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
245
320
|
|
|
246
|
-
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 };
|
|
321
|
+
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;
|
|
@@ -189,6 +239,31 @@ interface FormatOptions {
|
|
|
189
239
|
}
|
|
190
240
|
interface ValidationGenerateOptions {
|
|
191
241
|
outDir: string;
|
|
242
|
+
/**
|
|
243
|
+
* Path to the Drizzle schema module, as written in the config.
|
|
244
|
+
*
|
|
245
|
+
* Only needed by `typedJson`, which has to import the table back in order to reference the
|
|
246
|
+
* type Drizzle inferred for a column.
|
|
247
|
+
*/
|
|
248
|
+
schemaPath?: string;
|
|
249
|
+
/**
|
|
250
|
+
* Type `json` and `jsonb` columns from the schema instead of leaving them wide.
|
|
251
|
+
*
|
|
252
|
+
* `.$type<T>()` is a compile-time cast: Drizzle's implementation is literally
|
|
253
|
+
* `$type() { return this }`, so the type exists only in TypeScript and nothing about it
|
|
254
|
+
* survives to runtime. Every runtime-derived validator is therefore blind to it, and
|
|
255
|
+
* `drizzle-orm/zod` types a json column as its generic `Json` no matter what you declared.
|
|
256
|
+
*
|
|
257
|
+
* A generator can do better without resolving any types itself, because Drizzle already did
|
|
258
|
+
* the work: `typeof users.$inferSelect['prefs']` *is* the declared type, resolved by
|
|
259
|
+
* TypeScript at the point of use. So the emitted schema references that rather than trying to
|
|
260
|
+
* reconstruct it, which is why this works for generics, unions and imported interfaces alike,
|
|
261
|
+
* the cases that defeat source-parsing approaches.
|
|
262
|
+
*
|
|
263
|
+
* Off by default: it makes the generated file import your schema module, and that coupling
|
|
264
|
+
* should be a choice rather than a surprise.
|
|
265
|
+
*/
|
|
266
|
+
typedJson?: boolean;
|
|
192
267
|
format?: FormatOptions;
|
|
193
268
|
/**
|
|
194
269
|
* What every generated file is called after the Drizzle export name, e.g. `.zod.ts`
|
|
@@ -243,4 +318,4 @@ declare function updateColumns(table: Table): Column[];
|
|
|
243
318
|
declare function selectColumns(table: Table): Column[];
|
|
244
319
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
245
320
|
|
|
246
|
-
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 };
|
|
321
|
+
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";
|
|
@@ -184,7 +222,7 @@ async function formatCode(code, filePath, fmt) {
|
|
|
184
222
|
const engine = fmt?.engine ?? "auto";
|
|
185
223
|
try {
|
|
186
224
|
if (engine === "prettier" || engine === "auto") {
|
|
187
|
-
const prettier = await import("./prettier-
|
|
225
|
+
const prettier = await import("./prettier-LT6G5PW7.js");
|
|
188
226
|
const cfgRef = fmt?.configPath ?? filePath;
|
|
189
227
|
const cfg = await prettier.resolveConfig(cfgRef).catch(() => null);
|
|
190
228
|
return prettier.format(code, { ...cfg ?? {}, parser: "typescript", filepath: filePath });
|
|
@@ -219,6 +257,7 @@ export {
|
|
|
219
257
|
isGeneratedColumn,
|
|
220
258
|
moduleFileName,
|
|
221
259
|
moduleSpecifier,
|
|
260
|
+
parseCheck,
|
|
222
261
|
pascalCase,
|
|
223
262
|
resolveAffix,
|
|
224
263
|
resolveConfiguredImport,
|