@drzl/validation-core 3.20.0 → 3.22.1

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/README.md CHANGED
@@ -25,7 +25,8 @@ Shared interfaces and helpers used by validation generators.
25
25
 
26
26
  - Every dollar speeds up CI hardware and offsets long test runs on my aging laptop.
27
27
  - Sponsors get roadmap input and priority responses in GitHub Issues.
28
- - Prefer a quick overview? Check `docs/sponsor.md` for the current goals and thank-yous.
28
+ - Prefer a quick overview? The current goals and thank-yous are at
29
+ https://use-drzl.github.io/drzl/sponsor.
29
30
 
30
31
  ## Exports (essentials)
31
32
 
@@ -53,20 +54,45 @@ Shared interfaces and helpers used by validation generators.
53
54
  - CHECK constraints (shared by every generator that reads them)
54
55
  - `parseCheck(expression, name)` -> the parts of a `CHECK` that can be stated with certainty:
55
56
  column comparisons, `BETWEEN`, `IN (...)`, top-level `AND`, `length()`/`char_length()`,
56
- `cardinality()`/`array_length(col, 1)`, and comparisons between two columns. A disjunction, a
57
- negation, `octet_length`, an unrecognised function call and a regex match are all refused
58
- whole rather than half-applied.
59
- - `COLUMN_FORMATS` -> patterns for the column formats that are expressible. Only `numeric` is:
60
- Postgres accepts `today`, `January 8, 1999` and `allballs`, so a date or time pattern would
61
- reject rows the database takes.
57
+ `octet_length()`, `cardinality()`/`array_length(col, 1)`, and comparisons between two columns.
58
+ A negation, an unrecognised function call and a regex match are all refused whole rather than
59
+ half-applied, and a disjunction is read only where the whole of it pins one column to a set.
60
+ - `lengthMeasure(column, check)` -> how to answer a count on a given column, as one of
61
+ `'codePoints'`, `'utf8Bytes'` or `'byteLength'`, or nothing where no expression answers it.
62
+ The unit is on the check and the answer needs the column too: measured on PostgreSQL 17.5,
63
+ `length()` is the character count on a `text` and the byte count on a `bytea`, and
64
+ `char_length(bytea)` is not a function that exists. `measureExpression(measure, variable)`
65
+ renders it and `lengthCheckLabel(check)` renders the message the ledger keys on.
66
+ - `COLUMN_FORMATS` -> patterns for the column formats that are expressible, which is a short
67
+ list: Postgres accepts `today`, `January 8, 1999` and `allballs`, so a date or time pattern
68
+ would reject rows the database takes. `numeric` is Postgres's numeric input grammar, and
69
+ `pgBigint`/`mysqlBigint` are the two answers a `bigint({ mode: 'string' })` column has, since
70
+ Postgres parses that text as an integer literal (`0x1f` and `1_000` included) and MySQL parses
71
+ it as a decimal number it then rounds (`12.5` becomes 13). Each was measured against its own
72
+ server; neither states the magnitude, and the entry says why.
62
73
  - `CODEPOINT_LENGTH` -> `[...v].length`, since `varchar(n)` counts characters and JavaScript's
63
74
  `.length` counts UTF-16 units. All four generators use it.
64
75
  - `isIntegerColumn(c)`
76
+ - Constraints as data (shared by the generators that emit a ledger)
77
+ - `tableConstraints(table)` -> every CHECK, unique constraint, primary key and foreign key on a
78
+ table, each with a stable `id`, the columns it names, the rule as a sentence, whether a
79
+ generated schema enforces it, and, where it does, the exact message it attaches. A folded
80
+ numeric CHECK carries its `bounds` and a folded `IN` list its `values`, because those are what
81
+ is left to match on once the library writes the failure message itself.
82
+ - `classifyTableChecks(table)` -> the one reading of `parseCheck` plus the column-shape guards,
83
+ shared with `meta`, so "the database also checks this and no schema does" is one answer rather
84
+ than two.
85
+ - `renderConstraintsModule(tables, opts)` -> the source of `constraints.ts`: the data above plus,
86
+ unless `errorMap` is false, `constraintForIssue(table, issue)`. Plain objects with no import of
87
+ any kind, and the matcher reads zod's path items and valibot's alike.
88
+ - `resolveConstraints(option)` expands the `true` shorthand; `CONSTRAINTS_MODULE` is the file
89
+ name every generator writes it to.
65
90
  - Uniqueness
66
91
  - `renderDuplicateFinder(table, fnName, rowType)` -> the source of a function returning the rows
67
- in a batch that collide with an earlier row on a unique constraint. Plain TypeScript with no
68
- reference to any validation library, so all four generators emit the same one. Null and absent
69
- columns skip a constraint, matching SQL.
92
+ in a batch that collide with an earlier row on the primary key or a unique constraint. Plain
93
+ TypeScript with no reference to any validation library, so every validator generator emits the
94
+ same one. Null and absent columns skip a constraint, matching SQL, so rows that leave a
95
+ generated key to the database report nothing on it.
70
96
  - Naming (shared by every generator that emits a schema name)
71
97
  - `resolveAffix({ affix, schemaSuffix })` -> `ResolvedAffix`
72
98
  - `schemaName(mode, tsName, resolved)`, `typeName(mode, tsName, resolved)`