@drzl/validation-core 3.16.4 → 3.17.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/index.cjs +102 -0
- package/dist/index.d.cts +153 -2
- package/dist/index.d.ts +153 -2
- package/dist/index.js +93 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -36,11 +36,15 @@ __export(index_exports, {
|
|
|
36
36
|
COLUMN_FORMATS: () => COLUMN_FORMATS,
|
|
37
37
|
DEFAULT_IMPORT_EXTENSION: () => DEFAULT_IMPORT_EXTENSION,
|
|
38
38
|
DEFAULT_MODE_PREFIX: () => DEFAULT_MODE_PREFIX,
|
|
39
|
+
DEFAULT_NESTED_DEPTH: () => DEFAULT_NESTED_DEPTH,
|
|
39
40
|
DEFAULT_SCHEMA_SUFFIX: () => DEFAULT_SCHEMA_SUFFIX,
|
|
40
41
|
DEFAULT_TYPE_SUFFIX: () => DEFAULT_TYPE_SUFFIX,
|
|
41
42
|
IMPORT_EXTENSIONS: () => IMPORT_EXTENSIONS,
|
|
43
|
+
MAX_NESTED_DEPTH: () => MAX_NESTED_DEPTH,
|
|
42
44
|
NAME_MODES: () => NAME_MODES,
|
|
45
|
+
NESTED_PREFIX: () => NESTED_PREFIX,
|
|
43
46
|
applyTableCase: () => applyTableCase,
|
|
47
|
+
buildNestedPlan: () => buildNestedPlan,
|
|
44
48
|
describeSet: () => describeSet,
|
|
45
49
|
formatCode: () => formatCode,
|
|
46
50
|
importSpecifier: () => importSpecifier,
|
|
@@ -49,6 +53,10 @@ __export(index_exports, {
|
|
|
49
53
|
isIntegerColumn: () => isIntegerColumn,
|
|
50
54
|
moduleFileName: () => moduleFileName,
|
|
51
55
|
moduleSpecifier: () => moduleSpecifier,
|
|
56
|
+
nestedArmNotes: () => nestedArmNotes,
|
|
57
|
+
nestedNodeColumns: () => nestedNodeColumns,
|
|
58
|
+
nestedSchemaName: () => nestedSchemaName,
|
|
59
|
+
nestedTypeName: () => nestedTypeName,
|
|
52
60
|
nonFiniteAccepted: () => nonFiniteAccepted,
|
|
53
61
|
parseCheck: () => parseCheck,
|
|
54
62
|
parsesToADate: () => parsesToADate,
|
|
@@ -56,6 +64,7 @@ __export(index_exports, {
|
|
|
56
64
|
renderDuplicateFinder: () => renderDuplicateFinder,
|
|
57
65
|
resolveAffix: () => resolveAffix,
|
|
58
66
|
resolveConfiguredImport: () => resolveConfiguredImport,
|
|
67
|
+
resolveNestedDepth: () => resolveNestedDepth,
|
|
59
68
|
schemaName: () => schemaName,
|
|
60
69
|
selectColumns: () => selectColumns,
|
|
61
70
|
typeName: () => typeName,
|
|
@@ -448,6 +457,90 @@ function validateAffix(affix, schemaSuffix) {
|
|
|
448
457
|
return issues;
|
|
449
458
|
}
|
|
450
459
|
|
|
460
|
+
// src/nested.ts
|
|
461
|
+
var NESTED_PREFIX = "Nested";
|
|
462
|
+
function nestedSchemaName(mode, tsName, affix) {
|
|
463
|
+
return NESTED_PREFIX + schemaName(mode, tsName, affix);
|
|
464
|
+
}
|
|
465
|
+
function nestedTypeName(mode, tsName, affix) {
|
|
466
|
+
return NESTED_PREFIX + typeName(mode, tsName, affix);
|
|
467
|
+
}
|
|
468
|
+
var DEFAULT_NESTED_DEPTH = 1;
|
|
469
|
+
var MAX_NESTED_DEPTH = 3;
|
|
470
|
+
function resolveNestedDepth(depth, warn) {
|
|
471
|
+
if (depth === void 0) return DEFAULT_NESTED_DEPTH;
|
|
472
|
+
if (!Number.isFinite(depth)) return DEFAULT_NESTED_DEPTH;
|
|
473
|
+
const whole = Math.trunc(depth);
|
|
474
|
+
const clamped = Math.min(Math.max(whole, 1), MAX_NESTED_DEPTH);
|
|
475
|
+
if (clamped !== depth && warn) {
|
|
476
|
+
warn(
|
|
477
|
+
`[drzl] nestedDepth ${depth} is outside 1..${MAX_NESTED_DEPTH} and was read as ${clamped}.`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
return clamped;
|
|
481
|
+
}
|
|
482
|
+
var KINDS_BY_MODE = {
|
|
483
|
+
insert: /* @__PURE__ */ new Set(["many", "manyToMany"]),
|
|
484
|
+
select: /* @__PURE__ */ new Set(["one", "many", "manyToMany"])
|
|
485
|
+
};
|
|
486
|
+
var KIND_ORDER = { many: 0, manyToMany: 1, one: 2 };
|
|
487
|
+
function omittedColumnsFor(parent, child) {
|
|
488
|
+
const back = (child.foreignKeys ?? []).filter((fk) => fk.foreignTable === parent.name);
|
|
489
|
+
if (back.length === 1) return { omitted: [...back[0].columns] };
|
|
490
|
+
if (back.length === 0) return { omitted: [] };
|
|
491
|
+
const named = back.map((fk) => fk.columns.join("+")).join(", ");
|
|
492
|
+
return {
|
|
493
|
+
omitted: [],
|
|
494
|
+
note: `${child.tsName} has ${back.length} foreign keys to ${parent.name} (${named}), so which one this relation uses is not stated. None were omitted: supply them yourself.`
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function buildNestedPlan(root, tables, relations, mode, depth) {
|
|
498
|
+
const node = buildNode(root, [], tables, relations, mode, depth);
|
|
499
|
+
return node.arms.length ? node : void 0;
|
|
500
|
+
}
|
|
501
|
+
function buildNode(table, omitted, tables, relations, mode, depth) {
|
|
502
|
+
if (depth <= 0) return { table, omitted, arms: [] };
|
|
503
|
+
const byDbName = new Map(tables.map((t) => [t.name, t]));
|
|
504
|
+
const allowed = KINDS_BY_MODE[mode];
|
|
505
|
+
const columnNames = new Set(table.columns.map((c) => c.name));
|
|
506
|
+
const taken = /* @__PURE__ */ new Set();
|
|
507
|
+
const arms = [];
|
|
508
|
+
const candidates = relations.filter((r) => r.from === table.name && allowed.has(r.kind)).sort((a, b) => KIND_ORDER[a.kind] - KIND_ORDER[b.kind]);
|
|
509
|
+
for (const rel of candidates) {
|
|
510
|
+
const child = byDbName.get(rel.to);
|
|
511
|
+
if (!child) continue;
|
|
512
|
+
const key = child.tsName;
|
|
513
|
+
if (columnNames.has(key)) continue;
|
|
514
|
+
if (taken.has(key)) continue;
|
|
515
|
+
taken.add(key);
|
|
516
|
+
const { omitted: childOmitted, note } = rel.kind === "many" && mode === "insert" ? omittedColumnsFor(table, child) : { omitted: [], note: void 0 };
|
|
517
|
+
arms.push({
|
|
518
|
+
key,
|
|
519
|
+
kind: rel.kind,
|
|
520
|
+
via: rel.via,
|
|
521
|
+
single: rel.kind === "one",
|
|
522
|
+
note,
|
|
523
|
+
child: buildNode(child, childOmitted, tables, relations, mode, depth - 1)
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
return { table, omitted, arms };
|
|
527
|
+
}
|
|
528
|
+
function nestedArmNotes(arm) {
|
|
529
|
+
const out = [];
|
|
530
|
+
if (arm.kind === "manyToMany") {
|
|
531
|
+
out.push(
|
|
532
|
+
`Through ${arm.via ?? "a join table"}. The join row is not described: its columns are the two foreign keys, and the two ends of this payload supply both.`
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
if (arm.note) out.push(arm.note);
|
|
536
|
+
return out;
|
|
537
|
+
}
|
|
538
|
+
function nestedNodeColumns(columnsForMode, node) {
|
|
539
|
+
if (!node.omitted.length) return [...columnsForMode];
|
|
540
|
+
const drop = new Set(node.omitted);
|
|
541
|
+
return columnsForMode.filter((c) => !drop.has(c.name));
|
|
542
|
+
}
|
|
543
|
+
|
|
451
544
|
// src/duplicates.ts
|
|
452
545
|
function usableKeys(table) {
|
|
453
546
|
return (table.unique ?? []).filter((k) => k.columns.length > 0);
|
|
@@ -632,11 +725,15 @@ async function formatCode(code, filePath, fmt) {
|
|
|
632
725
|
COLUMN_FORMATS,
|
|
633
726
|
DEFAULT_IMPORT_EXTENSION,
|
|
634
727
|
DEFAULT_MODE_PREFIX,
|
|
728
|
+
DEFAULT_NESTED_DEPTH,
|
|
635
729
|
DEFAULT_SCHEMA_SUFFIX,
|
|
636
730
|
DEFAULT_TYPE_SUFFIX,
|
|
637
731
|
IMPORT_EXTENSIONS,
|
|
732
|
+
MAX_NESTED_DEPTH,
|
|
638
733
|
NAME_MODES,
|
|
734
|
+
NESTED_PREFIX,
|
|
639
735
|
applyTableCase,
|
|
736
|
+
buildNestedPlan,
|
|
640
737
|
describeSet,
|
|
641
738
|
formatCode,
|
|
642
739
|
importSpecifier,
|
|
@@ -645,6 +742,10 @@ async function formatCode(code, filePath, fmt) {
|
|
|
645
742
|
isIntegerColumn,
|
|
646
743
|
moduleFileName,
|
|
647
744
|
moduleSpecifier,
|
|
745
|
+
nestedArmNotes,
|
|
746
|
+
nestedNodeColumns,
|
|
747
|
+
nestedSchemaName,
|
|
748
|
+
nestedTypeName,
|
|
648
749
|
nonFiniteAccepted,
|
|
649
750
|
parseCheck,
|
|
650
751
|
parsesToADate,
|
|
@@ -652,6 +753,7 @@ async function formatCode(code, filePath, fmt) {
|
|
|
652
753
|
renderDuplicateFinder,
|
|
653
754
|
resolveAffix,
|
|
654
755
|
resolveConfiguredImport,
|
|
756
|
+
resolveNestedDepth,
|
|
655
757
|
schemaName,
|
|
656
758
|
selectColumns,
|
|
657
759
|
typeName,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Table as Table$1, Column, Analysis } from '@drzl/analyzer';
|
|
1
|
+
import { Relation, Table as Table$1, Column, Analysis } from '@drzl/analyzer';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* One place that decides what a generated module is called, on disk and in an import.
|
|
@@ -284,6 +284,127 @@ declare function parseCheck(expression: string | undefined, name?: string): Pars
|
|
|
284
284
|
*/
|
|
285
285
|
declare function describeSet(set: ColumnSet): string;
|
|
286
286
|
|
|
287
|
+
/**
|
|
288
|
+
* What a relations-aware nested schema describes, decided once for all four generators.
|
|
289
|
+
*
|
|
290
|
+
* A caller who inserts a parent and its children in one payload, `{ ...user, posts: [...] }`, has
|
|
291
|
+
* nothing to validate it against. Every first-party Drizzle validator emits columns only: measured
|
|
292
|
+
* at drizzle-orm 1.0.0-rc.4 and at the 0.4x `drizzle-zod`/`drizzle-valibot`/`drizzle-typebox`/
|
|
293
|
+
* `drizzle-arktype` packages, `createInsertSchema(users)` yields exactly `['id', 'name']` and never
|
|
294
|
+
* a `posts` key, in every mode and every library. Handing the relations object in as the second
|
|
295
|
+
* argument does not change that either: it lands in the refine slot and is dropped, because its
|
|
296
|
+
* keys are not column names. Handing it in first throws inside `getColumns`.
|
|
297
|
+
*
|
|
298
|
+
* And the payload is not merely unvalidated, it is silently discarded. `db.insert(users).values({
|
|
299
|
+
* name: 'a', posts: [{ title: 't' }] })` emits `insert into "users" ("id", "name") values
|
|
300
|
+
* (default, $1)` on both majors: the relation key is dropped, no error is raised, and the children
|
|
301
|
+
* are simply never written.
|
|
302
|
+
*
|
|
303
|
+
* This module states the *shape* of such a payload from the analysis. It renders nothing: each
|
|
304
|
+
* generator walks the plan and emits it in its own library, so the four cannot disagree about
|
|
305
|
+
* which relations appear or which columns a child carries.
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Which modes get a nested variant.
|
|
310
|
+
*
|
|
311
|
+
* `update` is deliberately absent, and it is the one decision here that is a refusal rather than a
|
|
312
|
+
* design. A nested update payload has no single meaning: `{ name: 'x', posts: [...] }` could mean
|
|
313
|
+
* replace every child, upsert them, or patch the ones that match, and choosing needs an operation
|
|
314
|
+
* vocabulary (Prisma spells it `create` / `connect` / `set` / `deleteMany`) that neither DRZL nor
|
|
315
|
+
* Drizzle has. Worse, it could not be acted on even if the meaning were fixed: `updateColumns`
|
|
316
|
+
* drops the primary key, so a child inside an update payload carries nothing that identifies which
|
|
317
|
+
* row it patches. A schema whose meaning the tool emitting it cannot state is worse than no schema.
|
|
318
|
+
*/
|
|
319
|
+
type NestedMode = 'insert' | 'select';
|
|
320
|
+
/** Prefix in front of the ordinary resolved name, so affixes keep working underneath it. */
|
|
321
|
+
declare const NESTED_PREFIX = "Nested";
|
|
322
|
+
/** e.g. `NestedInsertusersSchema`. */
|
|
323
|
+
declare function nestedSchemaName(mode: NestedMode, tsName: string, affix: ResolvedAffix): string;
|
|
324
|
+
/** e.g. `NestedInsertusersInput`. */
|
|
325
|
+
declare function nestedTypeName(mode: NestedMode, tsName: string, affix: ResolvedAffix): string;
|
|
326
|
+
/**
|
|
327
|
+
* How many levels of children a nested schema describes, when nothing says.
|
|
328
|
+
*
|
|
329
|
+
* One, because one is what the payload in the plan item is: a parent and its children. Deeper is
|
|
330
|
+
* available and is not the default, because the output grows multiplicatively in this number and
|
|
331
|
+
* generated code ships in the consumer's bundle.
|
|
332
|
+
*/
|
|
333
|
+
declare const DEFAULT_NESTED_DEPTH = 1;
|
|
334
|
+
/**
|
|
335
|
+
* The most levels `nestedDepth` will honour.
|
|
336
|
+
*
|
|
337
|
+
* Not a taste limit. Nesting is expanded inline rather than by reference, so a schema whose tables
|
|
338
|
+
* average R relations emits R^depth child shapes per root table, and both directions of a
|
|
339
|
+
* many-to-many count. At 3 that is already an eightfold expansion of every column list in the
|
|
340
|
+
* schema; past it the emitted file stops being something a person can open.
|
|
341
|
+
*/
|
|
342
|
+
declare const MAX_NESTED_DEPTH = 3;
|
|
343
|
+
/** Clamp a configured depth into the range that is actually emitted, saying so if it moved. */
|
|
344
|
+
declare function resolveNestedDepth(depth: number | undefined, warn?: (msg: string) => void): number;
|
|
345
|
+
/** One relation as it appears in a payload. */
|
|
346
|
+
interface NestedArm {
|
|
347
|
+
/** The key the payload uses. The child table's Drizzle export name, since nothing else names it. */
|
|
348
|
+
key: string;
|
|
349
|
+
kind: Relation['kind'];
|
|
350
|
+
/** Join table of a many-to-many, carried only so the emitted comment can name it. */
|
|
351
|
+
via?: string;
|
|
352
|
+
/** `true` when the value is one object rather than an array of them. Only a `one` relation. */
|
|
353
|
+
single: boolean;
|
|
354
|
+
/** The child payload, itself possibly carrying relations. */
|
|
355
|
+
child: NestedNode;
|
|
356
|
+
/**
|
|
357
|
+
* Something true about this arm that the shape alone does not say, emitted as a comment beside
|
|
358
|
+
* it. Absent when there is nothing to say.
|
|
359
|
+
*/
|
|
360
|
+
note?: string;
|
|
361
|
+
}
|
|
362
|
+
/** One object in a nested payload: a table, minus what the enclosing parent supplies. */
|
|
363
|
+
interface NestedNode {
|
|
364
|
+
table: Table$1;
|
|
365
|
+
/**
|
|
366
|
+
* Columns dropped from this object because the row that encloses it supplies them.
|
|
367
|
+
*
|
|
368
|
+
* Always empty at the root and always empty in `select`, where every column of the row really is
|
|
369
|
+
* returned. On `insert` it holds the child's foreign key to its parent; see `armFor`.
|
|
370
|
+
*/
|
|
371
|
+
omitted: string[];
|
|
372
|
+
arms: NestedArm[];
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* The nested payload for one table, expanded `depth` levels.
|
|
376
|
+
*
|
|
377
|
+
* Recursion is bounded rather than expressed. All four libraries can state a cyclic schema, and
|
|
378
|
+
* each does it differently: zod through a property getter, valibot through `v.lazy`, ArkType only
|
|
379
|
+
* inside a `scope` (a plain forward reference throws `Cannot access 'Post' before initialization`
|
|
380
|
+
* at module load), TypeBox only inside a `Type.Module` (a bare `Type.Ref` constructs happily and
|
|
381
|
+
* then throws `Unable to dereference schema with $id` the first time anything checks a value).
|
|
382
|
+
* Every one of those was run.
|
|
383
|
+
*
|
|
384
|
+
* None is used. Expanding inline to a fixed depth needs no recursion API, so no emitted module can
|
|
385
|
+
* throw on import from an unresolvable reference, no zod or valibot schema needs the explicit type
|
|
386
|
+
* annotation a self-referential one demands from TypeScript, and the four outputs stay structurally
|
|
387
|
+
* identical instead of diverging into four different recursion mechanisms. A cycle in the relations
|
|
388
|
+
* simply stops at the depth: `users -> posts -> users` at depth 1 emits the posts and no more.
|
|
389
|
+
*/
|
|
390
|
+
declare function buildNestedPlan(root: Table$1, tables: readonly Table$1[], relations: readonly Relation[], mode: NestedMode, depth: number): NestedNode | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* The comment lines that go above an arm, without their `//`.
|
|
393
|
+
*
|
|
394
|
+
* Shared so the four generators say the same thing about the same relation, and returned unmarked
|
|
395
|
+
* because each of them indents its object literal differently.
|
|
396
|
+
*/
|
|
397
|
+
declare function nestedArmNotes(arm: NestedArm): string[];
|
|
398
|
+
/**
|
|
399
|
+
* Which columns a node contributes, given the mode's column list for its table.
|
|
400
|
+
*
|
|
401
|
+
* The list is passed in rather than derived, so this cannot drift from `insertColumns` and
|
|
402
|
+
* `selectColumns` and so `validation-core`'s entry point stays free of a cycle back into itself.
|
|
403
|
+
*/
|
|
404
|
+
declare function nestedNodeColumns<T extends {
|
|
405
|
+
name: string;
|
|
406
|
+
}>(columnsForMode: readonly T[], node: NestedNode): T[];
|
|
407
|
+
|
|
287
408
|
/**
|
|
288
409
|
* A duplicate finder for a batch of rows, emitted beside the schemas.
|
|
289
410
|
*
|
|
@@ -403,6 +524,29 @@ interface ValidationGenerateOptions {
|
|
|
403
524
|
*/
|
|
404
525
|
affix?: AffixOptions;
|
|
405
526
|
coerceDates?: 'input' | 'all' | 'none';
|
|
527
|
+
/**
|
|
528
|
+
* Also emit `NestedInsert<Table>` and `NestedSelect<Table>`: the table's own schema plus one key
|
|
529
|
+
* per relation, so `{ ...user, posts: [...] }` can be validated whole.
|
|
530
|
+
*
|
|
531
|
+
* Nothing in the Drizzle validator ecosystem describes this payload. Measured across both majors
|
|
532
|
+
* and all four libraries, `createInsertSchema(users)` emits column keys only, and
|
|
533
|
+
* `db.insert(users).values({ name, posts: [...] })` drops the `posts` key without a word rather
|
|
534
|
+
* than refusing it, so the children are silently never written.
|
|
535
|
+
*
|
|
536
|
+
* Off by default, like every other option that adds bytes to the consumer's bundle. See
|
|
537
|
+
* `NestedMode` in `@drzl/validation-core` for why there is no nested update schema, and
|
|
538
|
+
* `KINDS_BY_MODE` for why a `one` relation appears on select and not on insert.
|
|
539
|
+
*/
|
|
540
|
+
nestedSchemas?: boolean;
|
|
541
|
+
/**
|
|
542
|
+
* How many levels of children a nested schema describes. Defaults to 1, capped at
|
|
543
|
+
* `MAX_NESTED_DEPTH`.
|
|
544
|
+
*
|
|
545
|
+
* Nesting is expanded inline rather than by reference, so this multiplies the emitted size: a
|
|
546
|
+
* schema whose tables average R relations emits R^depth child shapes per root table. It is also
|
|
547
|
+
* what terminates a cycle, since `users -> posts -> users` simply stops here.
|
|
548
|
+
*/
|
|
549
|
+
nestedDepth?: number;
|
|
406
550
|
emit?: {
|
|
407
551
|
select?: boolean;
|
|
408
552
|
insert?: boolean;
|
|
@@ -411,6 +555,13 @@ interface ValidationGenerateOptions {
|
|
|
411
555
|
}
|
|
412
556
|
interface ValidationRenderer<TOptions extends ValidationGenerateOptions = ValidationGenerateOptions> {
|
|
413
557
|
readonly library: ValidationLibrary;
|
|
558
|
+
/**
|
|
559
|
+
* One table's schemas, without the nested variants even under `nestedSchemas`.
|
|
560
|
+
*
|
|
561
|
+
* Structural rather than an omission: relations live on the `Analysis` and this is handed a
|
|
562
|
+
* `Table`, so there is nothing here to read them from. `typedJson` is absent for the same
|
|
563
|
+
* reason. Nothing but the generators' own tests calls this; `generate` is the path that emits.
|
|
564
|
+
*/
|
|
414
565
|
renderTable(table: Table, opts?: TOptions): string;
|
|
415
566
|
renderIndex?(analysis: Analysis, opts?: TOptions): string;
|
|
416
567
|
generate(opts: TOptions): Promise<string[]>;
|
|
@@ -629,4 +780,4 @@ declare function selectColumns(table: Table): Column[];
|
|
|
629
780
|
*/
|
|
630
781
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
631
782
|
|
|
632
|
-
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, nonFiniteAccepted, parseCheck, parsesToADate, pascalCase, renderDuplicateFinder, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
|
783
|
+
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, MAX_NESTED_DEPTH, NAME_MODES, NESTED_PREFIX, type NameMode, type NestedArm, type NestedMode, type NestedNode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, buildNestedPlan, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, parseCheck, parsesToADate, pascalCase, renderDuplicateFinder, resolveAffix, resolveConfiguredImport, resolveNestedDepth, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Table as Table$1, Column, Analysis } from '@drzl/analyzer';
|
|
1
|
+
import { Relation, Table as Table$1, Column, Analysis } from '@drzl/analyzer';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* One place that decides what a generated module is called, on disk and in an import.
|
|
@@ -284,6 +284,127 @@ declare function parseCheck(expression: string | undefined, name?: string): Pars
|
|
|
284
284
|
*/
|
|
285
285
|
declare function describeSet(set: ColumnSet): string;
|
|
286
286
|
|
|
287
|
+
/**
|
|
288
|
+
* What a relations-aware nested schema describes, decided once for all four generators.
|
|
289
|
+
*
|
|
290
|
+
* A caller who inserts a parent and its children in one payload, `{ ...user, posts: [...] }`, has
|
|
291
|
+
* nothing to validate it against. Every first-party Drizzle validator emits columns only: measured
|
|
292
|
+
* at drizzle-orm 1.0.0-rc.4 and at the 0.4x `drizzle-zod`/`drizzle-valibot`/`drizzle-typebox`/
|
|
293
|
+
* `drizzle-arktype` packages, `createInsertSchema(users)` yields exactly `['id', 'name']` and never
|
|
294
|
+
* a `posts` key, in every mode and every library. Handing the relations object in as the second
|
|
295
|
+
* argument does not change that either: it lands in the refine slot and is dropped, because its
|
|
296
|
+
* keys are not column names. Handing it in first throws inside `getColumns`.
|
|
297
|
+
*
|
|
298
|
+
* And the payload is not merely unvalidated, it is silently discarded. `db.insert(users).values({
|
|
299
|
+
* name: 'a', posts: [{ title: 't' }] })` emits `insert into "users" ("id", "name") values
|
|
300
|
+
* (default, $1)` on both majors: the relation key is dropped, no error is raised, and the children
|
|
301
|
+
* are simply never written.
|
|
302
|
+
*
|
|
303
|
+
* This module states the *shape* of such a payload from the analysis. It renders nothing: each
|
|
304
|
+
* generator walks the plan and emits it in its own library, so the four cannot disagree about
|
|
305
|
+
* which relations appear or which columns a child carries.
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Which modes get a nested variant.
|
|
310
|
+
*
|
|
311
|
+
* `update` is deliberately absent, and it is the one decision here that is a refusal rather than a
|
|
312
|
+
* design. A nested update payload has no single meaning: `{ name: 'x', posts: [...] }` could mean
|
|
313
|
+
* replace every child, upsert them, or patch the ones that match, and choosing needs an operation
|
|
314
|
+
* vocabulary (Prisma spells it `create` / `connect` / `set` / `deleteMany`) that neither DRZL nor
|
|
315
|
+
* Drizzle has. Worse, it could not be acted on even if the meaning were fixed: `updateColumns`
|
|
316
|
+
* drops the primary key, so a child inside an update payload carries nothing that identifies which
|
|
317
|
+
* row it patches. A schema whose meaning the tool emitting it cannot state is worse than no schema.
|
|
318
|
+
*/
|
|
319
|
+
type NestedMode = 'insert' | 'select';
|
|
320
|
+
/** Prefix in front of the ordinary resolved name, so affixes keep working underneath it. */
|
|
321
|
+
declare const NESTED_PREFIX = "Nested";
|
|
322
|
+
/** e.g. `NestedInsertusersSchema`. */
|
|
323
|
+
declare function nestedSchemaName(mode: NestedMode, tsName: string, affix: ResolvedAffix): string;
|
|
324
|
+
/** e.g. `NestedInsertusersInput`. */
|
|
325
|
+
declare function nestedTypeName(mode: NestedMode, tsName: string, affix: ResolvedAffix): string;
|
|
326
|
+
/**
|
|
327
|
+
* How many levels of children a nested schema describes, when nothing says.
|
|
328
|
+
*
|
|
329
|
+
* One, because one is what the payload in the plan item is: a parent and its children. Deeper is
|
|
330
|
+
* available and is not the default, because the output grows multiplicatively in this number and
|
|
331
|
+
* generated code ships in the consumer's bundle.
|
|
332
|
+
*/
|
|
333
|
+
declare const DEFAULT_NESTED_DEPTH = 1;
|
|
334
|
+
/**
|
|
335
|
+
* The most levels `nestedDepth` will honour.
|
|
336
|
+
*
|
|
337
|
+
* Not a taste limit. Nesting is expanded inline rather than by reference, so a schema whose tables
|
|
338
|
+
* average R relations emits R^depth child shapes per root table, and both directions of a
|
|
339
|
+
* many-to-many count. At 3 that is already an eightfold expansion of every column list in the
|
|
340
|
+
* schema; past it the emitted file stops being something a person can open.
|
|
341
|
+
*/
|
|
342
|
+
declare const MAX_NESTED_DEPTH = 3;
|
|
343
|
+
/** Clamp a configured depth into the range that is actually emitted, saying so if it moved. */
|
|
344
|
+
declare function resolveNestedDepth(depth: number | undefined, warn?: (msg: string) => void): number;
|
|
345
|
+
/** One relation as it appears in a payload. */
|
|
346
|
+
interface NestedArm {
|
|
347
|
+
/** The key the payload uses. The child table's Drizzle export name, since nothing else names it. */
|
|
348
|
+
key: string;
|
|
349
|
+
kind: Relation['kind'];
|
|
350
|
+
/** Join table of a many-to-many, carried only so the emitted comment can name it. */
|
|
351
|
+
via?: string;
|
|
352
|
+
/** `true` when the value is one object rather than an array of them. Only a `one` relation. */
|
|
353
|
+
single: boolean;
|
|
354
|
+
/** The child payload, itself possibly carrying relations. */
|
|
355
|
+
child: NestedNode;
|
|
356
|
+
/**
|
|
357
|
+
* Something true about this arm that the shape alone does not say, emitted as a comment beside
|
|
358
|
+
* it. Absent when there is nothing to say.
|
|
359
|
+
*/
|
|
360
|
+
note?: string;
|
|
361
|
+
}
|
|
362
|
+
/** One object in a nested payload: a table, minus what the enclosing parent supplies. */
|
|
363
|
+
interface NestedNode {
|
|
364
|
+
table: Table$1;
|
|
365
|
+
/**
|
|
366
|
+
* Columns dropped from this object because the row that encloses it supplies them.
|
|
367
|
+
*
|
|
368
|
+
* Always empty at the root and always empty in `select`, where every column of the row really is
|
|
369
|
+
* returned. On `insert` it holds the child's foreign key to its parent; see `armFor`.
|
|
370
|
+
*/
|
|
371
|
+
omitted: string[];
|
|
372
|
+
arms: NestedArm[];
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* The nested payload for one table, expanded `depth` levels.
|
|
376
|
+
*
|
|
377
|
+
* Recursion is bounded rather than expressed. All four libraries can state a cyclic schema, and
|
|
378
|
+
* each does it differently: zod through a property getter, valibot through `v.lazy`, ArkType only
|
|
379
|
+
* inside a `scope` (a plain forward reference throws `Cannot access 'Post' before initialization`
|
|
380
|
+
* at module load), TypeBox only inside a `Type.Module` (a bare `Type.Ref` constructs happily and
|
|
381
|
+
* then throws `Unable to dereference schema with $id` the first time anything checks a value).
|
|
382
|
+
* Every one of those was run.
|
|
383
|
+
*
|
|
384
|
+
* None is used. Expanding inline to a fixed depth needs no recursion API, so no emitted module can
|
|
385
|
+
* throw on import from an unresolvable reference, no zod or valibot schema needs the explicit type
|
|
386
|
+
* annotation a self-referential one demands from TypeScript, and the four outputs stay structurally
|
|
387
|
+
* identical instead of diverging into four different recursion mechanisms. A cycle in the relations
|
|
388
|
+
* simply stops at the depth: `users -> posts -> users` at depth 1 emits the posts and no more.
|
|
389
|
+
*/
|
|
390
|
+
declare function buildNestedPlan(root: Table$1, tables: readonly Table$1[], relations: readonly Relation[], mode: NestedMode, depth: number): NestedNode | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* The comment lines that go above an arm, without their `//`.
|
|
393
|
+
*
|
|
394
|
+
* Shared so the four generators say the same thing about the same relation, and returned unmarked
|
|
395
|
+
* because each of them indents its object literal differently.
|
|
396
|
+
*/
|
|
397
|
+
declare function nestedArmNotes(arm: NestedArm): string[];
|
|
398
|
+
/**
|
|
399
|
+
* Which columns a node contributes, given the mode's column list for its table.
|
|
400
|
+
*
|
|
401
|
+
* The list is passed in rather than derived, so this cannot drift from `insertColumns` and
|
|
402
|
+
* `selectColumns` and so `validation-core`'s entry point stays free of a cycle back into itself.
|
|
403
|
+
*/
|
|
404
|
+
declare function nestedNodeColumns<T extends {
|
|
405
|
+
name: string;
|
|
406
|
+
}>(columnsForMode: readonly T[], node: NestedNode): T[];
|
|
407
|
+
|
|
287
408
|
/**
|
|
288
409
|
* A duplicate finder for a batch of rows, emitted beside the schemas.
|
|
289
410
|
*
|
|
@@ -403,6 +524,29 @@ interface ValidationGenerateOptions {
|
|
|
403
524
|
*/
|
|
404
525
|
affix?: AffixOptions;
|
|
405
526
|
coerceDates?: 'input' | 'all' | 'none';
|
|
527
|
+
/**
|
|
528
|
+
* Also emit `NestedInsert<Table>` and `NestedSelect<Table>`: the table's own schema plus one key
|
|
529
|
+
* per relation, so `{ ...user, posts: [...] }` can be validated whole.
|
|
530
|
+
*
|
|
531
|
+
* Nothing in the Drizzle validator ecosystem describes this payload. Measured across both majors
|
|
532
|
+
* and all four libraries, `createInsertSchema(users)` emits column keys only, and
|
|
533
|
+
* `db.insert(users).values({ name, posts: [...] })` drops the `posts` key without a word rather
|
|
534
|
+
* than refusing it, so the children are silently never written.
|
|
535
|
+
*
|
|
536
|
+
* Off by default, like every other option that adds bytes to the consumer's bundle. See
|
|
537
|
+
* `NestedMode` in `@drzl/validation-core` for why there is no nested update schema, and
|
|
538
|
+
* `KINDS_BY_MODE` for why a `one` relation appears on select and not on insert.
|
|
539
|
+
*/
|
|
540
|
+
nestedSchemas?: boolean;
|
|
541
|
+
/**
|
|
542
|
+
* How many levels of children a nested schema describes. Defaults to 1, capped at
|
|
543
|
+
* `MAX_NESTED_DEPTH`.
|
|
544
|
+
*
|
|
545
|
+
* Nesting is expanded inline rather than by reference, so this multiplies the emitted size: a
|
|
546
|
+
* schema whose tables average R relations emits R^depth child shapes per root table. It is also
|
|
547
|
+
* what terminates a cycle, since `users -> posts -> users` simply stops here.
|
|
548
|
+
*/
|
|
549
|
+
nestedDepth?: number;
|
|
406
550
|
emit?: {
|
|
407
551
|
select?: boolean;
|
|
408
552
|
insert?: boolean;
|
|
@@ -411,6 +555,13 @@ interface ValidationGenerateOptions {
|
|
|
411
555
|
}
|
|
412
556
|
interface ValidationRenderer<TOptions extends ValidationGenerateOptions = ValidationGenerateOptions> {
|
|
413
557
|
readonly library: ValidationLibrary;
|
|
558
|
+
/**
|
|
559
|
+
* One table's schemas, without the nested variants even under `nestedSchemas`.
|
|
560
|
+
*
|
|
561
|
+
* Structural rather than an omission: relations live on the `Analysis` and this is handed a
|
|
562
|
+
* `Table`, so there is nothing here to read them from. `typedJson` is absent for the same
|
|
563
|
+
* reason. Nothing but the generators' own tests calls this; `generate` is the path that emits.
|
|
564
|
+
*/
|
|
414
565
|
renderTable(table: Table, opts?: TOptions): string;
|
|
415
566
|
renderIndex?(analysis: Analysis, opts?: TOptions): string;
|
|
416
567
|
generate(opts: TOptions): Promise<string[]>;
|
|
@@ -629,4 +780,4 @@ declare function selectColumns(table: Table): Column[];
|
|
|
629
780
|
*/
|
|
630
781
|
declare function formatCode(code: string, filePath: string, fmt?: FormatOptions): Promise<any>;
|
|
631
782
|
|
|
632
|
-
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, NAME_MODES, type NameMode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, nonFiniteAccepted, parseCheck, parsesToADate, pascalCase, renderDuplicateFinder, resolveAffix, resolveConfiguredImport, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
|
783
|
+
export { AFFIX_PROBE_TABLE, type AffixIssue, type AffixOptions, type AffixValue, CODEPOINT_LENGTH, COERCIBLE_DATE_STRING, COLUMN_FORMATS, type CardinalityCheck, type ColumnCheck, type ColumnSet, DEFAULT_IMPORT_EXTENSION, DEFAULT_MODE_PREFIX, DEFAULT_NESTED_DEPTH, DEFAULT_SCHEMA_SUFFIX, DEFAULT_TYPE_SUFFIX, type FormatOptions, IMPORT_EXTENSIONS, type ImportExtension, type LengthCheck, MAX_NESTED_DEPTH, NAME_MODES, NESTED_PREFIX, type NameMode, type NestedArm, type NestedMode, type NestedNode, type ParsedCheck, type ResolvedAffix, type RowCheck, type Table, type TableCase, type ValidationGenerateOptions, type ValidationLibrary, type ValidationRenderer, applyTableCase, buildNestedPlan, describeSet, formatCode, importSpecifier, insertColumns, isGeneratedColumn, isIntegerColumn, moduleFileName, moduleSpecifier, nestedArmNotes, nestedNodeColumns, nestedSchemaName, nestedTypeName, nonFiniteAccepted, parseCheck, parsesToADate, pascalCase, renderDuplicateFinder, resolveAffix, resolveConfiguredImport, resolveNestedDepth, schemaName, selectColumns, typeName, updateColumns, validateAffix };
|
package/dist/index.js
CHANGED
|
@@ -384,6 +384,90 @@ function validateAffix(affix, schemaSuffix) {
|
|
|
384
384
|
return issues;
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
+
// src/nested.ts
|
|
388
|
+
var NESTED_PREFIX = "Nested";
|
|
389
|
+
function nestedSchemaName(mode, tsName, affix) {
|
|
390
|
+
return NESTED_PREFIX + schemaName(mode, tsName, affix);
|
|
391
|
+
}
|
|
392
|
+
function nestedTypeName(mode, tsName, affix) {
|
|
393
|
+
return NESTED_PREFIX + typeName(mode, tsName, affix);
|
|
394
|
+
}
|
|
395
|
+
var DEFAULT_NESTED_DEPTH = 1;
|
|
396
|
+
var MAX_NESTED_DEPTH = 3;
|
|
397
|
+
function resolveNestedDepth(depth, warn) {
|
|
398
|
+
if (depth === void 0) return DEFAULT_NESTED_DEPTH;
|
|
399
|
+
if (!Number.isFinite(depth)) return DEFAULT_NESTED_DEPTH;
|
|
400
|
+
const whole = Math.trunc(depth);
|
|
401
|
+
const clamped = Math.min(Math.max(whole, 1), MAX_NESTED_DEPTH);
|
|
402
|
+
if (clamped !== depth && warn) {
|
|
403
|
+
warn(
|
|
404
|
+
`[drzl] nestedDepth ${depth} is outside 1..${MAX_NESTED_DEPTH} and was read as ${clamped}.`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
return clamped;
|
|
408
|
+
}
|
|
409
|
+
var KINDS_BY_MODE = {
|
|
410
|
+
insert: /* @__PURE__ */ new Set(["many", "manyToMany"]),
|
|
411
|
+
select: /* @__PURE__ */ new Set(["one", "many", "manyToMany"])
|
|
412
|
+
};
|
|
413
|
+
var KIND_ORDER = { many: 0, manyToMany: 1, one: 2 };
|
|
414
|
+
function omittedColumnsFor(parent, child) {
|
|
415
|
+
const back = (child.foreignKeys ?? []).filter((fk) => fk.foreignTable === parent.name);
|
|
416
|
+
if (back.length === 1) return { omitted: [...back[0].columns] };
|
|
417
|
+
if (back.length === 0) return { omitted: [] };
|
|
418
|
+
const named = back.map((fk) => fk.columns.join("+")).join(", ");
|
|
419
|
+
return {
|
|
420
|
+
omitted: [],
|
|
421
|
+
note: `${child.tsName} has ${back.length} foreign keys to ${parent.name} (${named}), so which one this relation uses is not stated. None were omitted: supply them yourself.`
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function buildNestedPlan(root, tables, relations, mode, depth) {
|
|
425
|
+
const node = buildNode(root, [], tables, relations, mode, depth);
|
|
426
|
+
return node.arms.length ? node : void 0;
|
|
427
|
+
}
|
|
428
|
+
function buildNode(table, omitted, tables, relations, mode, depth) {
|
|
429
|
+
if (depth <= 0) return { table, omitted, arms: [] };
|
|
430
|
+
const byDbName = new Map(tables.map((t) => [t.name, t]));
|
|
431
|
+
const allowed = KINDS_BY_MODE[mode];
|
|
432
|
+
const columnNames = new Set(table.columns.map((c) => c.name));
|
|
433
|
+
const taken = /* @__PURE__ */ new Set();
|
|
434
|
+
const arms = [];
|
|
435
|
+
const candidates = relations.filter((r) => r.from === table.name && allowed.has(r.kind)).sort((a, b) => KIND_ORDER[a.kind] - KIND_ORDER[b.kind]);
|
|
436
|
+
for (const rel of candidates) {
|
|
437
|
+
const child = byDbName.get(rel.to);
|
|
438
|
+
if (!child) continue;
|
|
439
|
+
const key = child.tsName;
|
|
440
|
+
if (columnNames.has(key)) continue;
|
|
441
|
+
if (taken.has(key)) continue;
|
|
442
|
+
taken.add(key);
|
|
443
|
+
const { omitted: childOmitted, note } = rel.kind === "many" && mode === "insert" ? omittedColumnsFor(table, child) : { omitted: [], note: void 0 };
|
|
444
|
+
arms.push({
|
|
445
|
+
key,
|
|
446
|
+
kind: rel.kind,
|
|
447
|
+
via: rel.via,
|
|
448
|
+
single: rel.kind === "one",
|
|
449
|
+
note,
|
|
450
|
+
child: buildNode(child, childOmitted, tables, relations, mode, depth - 1)
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return { table, omitted, arms };
|
|
454
|
+
}
|
|
455
|
+
function nestedArmNotes(arm) {
|
|
456
|
+
const out = [];
|
|
457
|
+
if (arm.kind === "manyToMany") {
|
|
458
|
+
out.push(
|
|
459
|
+
`Through ${arm.via ?? "a join table"}. The join row is not described: its columns are the two foreign keys, and the two ends of this payload supply both.`
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
if (arm.note) out.push(arm.note);
|
|
463
|
+
return out;
|
|
464
|
+
}
|
|
465
|
+
function nestedNodeColumns(columnsForMode, node) {
|
|
466
|
+
if (!node.omitted.length) return [...columnsForMode];
|
|
467
|
+
const drop = new Set(node.omitted);
|
|
468
|
+
return columnsForMode.filter((c) => !drop.has(c.name));
|
|
469
|
+
}
|
|
470
|
+
|
|
387
471
|
// src/duplicates.ts
|
|
388
472
|
function usableKeys(table) {
|
|
389
473
|
return (table.unique ?? []).filter((k) => k.columns.length > 0);
|
|
@@ -567,11 +651,15 @@ export {
|
|
|
567
651
|
COLUMN_FORMATS,
|
|
568
652
|
DEFAULT_IMPORT_EXTENSION,
|
|
569
653
|
DEFAULT_MODE_PREFIX,
|
|
654
|
+
DEFAULT_NESTED_DEPTH,
|
|
570
655
|
DEFAULT_SCHEMA_SUFFIX,
|
|
571
656
|
DEFAULT_TYPE_SUFFIX,
|
|
572
657
|
IMPORT_EXTENSIONS,
|
|
658
|
+
MAX_NESTED_DEPTH,
|
|
573
659
|
NAME_MODES,
|
|
660
|
+
NESTED_PREFIX,
|
|
574
661
|
applyTableCase,
|
|
662
|
+
buildNestedPlan,
|
|
575
663
|
describeSet,
|
|
576
664
|
formatCode,
|
|
577
665
|
importSpecifier,
|
|
@@ -580,6 +668,10 @@ export {
|
|
|
580
668
|
isIntegerColumn,
|
|
581
669
|
moduleFileName,
|
|
582
670
|
moduleSpecifier,
|
|
671
|
+
nestedArmNotes,
|
|
672
|
+
nestedNodeColumns,
|
|
673
|
+
nestedSchemaName,
|
|
674
|
+
nestedTypeName,
|
|
583
675
|
nonFiniteAccepted,
|
|
584
676
|
parseCheck,
|
|
585
677
|
parsesToADate,
|
|
@@ -587,6 +679,7 @@ export {
|
|
|
587
679
|
renderDuplicateFinder,
|
|
588
680
|
resolveAffix,
|
|
589
681
|
resolveConfiguredImport,
|
|
682
|
+
resolveNestedDepth,
|
|
590
683
|
schemaName,
|
|
591
684
|
selectColumns,
|
|
592
685
|
typeName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drzl/validation-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"sideEffects": false,
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@drzl/analyzer": "^1.17.
|
|
27
|
+
"@drzl/analyzer": "^1.17.7"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"prettier": ">=3"
|