@inixiative/json-rules 3.10.0 → 3.12.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/README.md CHANGED
@@ -628,6 +628,21 @@ declares: on Json, `contains` / `startsWith` / `endsWith` become `string_contain
628
628
  becomes one `equals` per value; on a scalar list, `contains` becomes `has` and emptiness
629
629
  `isEmpty`; `caseInsensitive` adds `mode: 'insensitive'` on text only.
630
630
 
631
+ ### A value the row doesn't carry
632
+
633
+ By default `check()` reads an absent path as null, as a column is on the compiled rails.
634
+ `check(rule, row, { absent: 'unknown' })` reads it as unknown instead: `null === null`, and
635
+ `undefined` is not null. Every operator fails on an unknown field or compared `path`, `equals
636
+ null` and `in [null]` included, except the ones that hold on a missing value (`isEmpty`,
637
+ `notExists` and the negations), which keep their meaning. Use it when the row is a partial stand-in
638
+ for real rows (a pseudo record a grant is checked against), so a rule passes only on what the row
639
+ pins. `check()` only; the compilers read real columns.
640
+
641
+ `validateRule(rule, { positive: true })` refuses every shape that can hold on a missing value —
642
+ `if`/`then`/`else`, array and aggregate rules, the negations, `isEmpty` and `notExists` — so a rule
643
+ checked that way passes only on what the row carries. A rule that means "no value" says `equals
644
+ null`.
645
+
631
646
  ## Engine Globals
632
647
 
633
648
  `engineGlobals` holds process-wide defaults. Keys are dotted paths into one state object.
@@ -1492,7 +1507,7 @@ const holds = forRecheck.filter((row) => check(narrowRule(rule, narrowing), row,
1492
1507
  | Function | Purpose |
1493
1508
  | --- | --- |
1494
1509
  | `toLensSelect(lensOrNarrowing, options?)` | `{ select }` for `findMany` at the base model. It selects each visit's visible columns and the relations turned on there (one that is off is not fetched; the model-default tree bounds it), and every column a `where` on the way reads. A to-many relation carries its visit's clamps compiled as its `where`, so related rows come pre-narrowed — unless a clamp reads that list: a clamp reads it whole, as the database does, so it is fetched whole and `projectRows` cuts it. A to-one relation takes no `where` in Prisma, so `projectRows` drops one its clamp hides. A relation that shows no column — one turned on with all its columns hidden, or one a clamp reads only for presence or a count — is fetched by its key alone — the join key, else `id` — even a hidden one, as a clamp's columns are; never another column. The fetch carries it for the re-check and a viewer's projection drops it; a model with no key is not fetched, and presence on it can't be re-checked from fetched rows. A root that shows no column is selected by its `id` likewise. Bridges are skipped. It also selects what each projected source reads — the value, its label and axes, and every column and relation its option query's condition reads — as it does a clamp's columns, so `materializeSources` over the fetched rows offers what the database does; a viewer's projection drops them. For a source across a bridge that is its local reads: what it reads on this side, hidden or not, and each crossed bridge's local `on` key, so the rows plus the far side loaded under its bridge field answer it. A to-many relation's clamp that needs a counting step (a count or an aggregate), or has a window toPrisma can't compile, is refused (a `LensRefusal`, which `validateNarrowing` reports) before anything compiles. `options` is the clock for compiling the clamps. The root's own clamps are the query's `where`: `toPrisma(rule, { lens })`. |
1495
- | `projectRows(lensOrNarrowing, rows, options?)` | Rows cut to what the lens shows, recursively. Hidden columns, and relations that are off or omitted, are removed. A row a visit's `where` hides is dropped from the root or a list, and a to-one row becomes `null`. `keepClampColumns: true` keeps the columns those `where`s and the projected sources read, even hidden ones, and a hidden to-one row, or a hidden row of a list a clamp reads, as those columns alone, so `check(narrowRule(rule, lens), row)` re-tests the clamps as the database does, for any rule the lens admits; that output carries hidden values, so never return it to a viewer. The other options (`now`, `bindings`) are what each `where` is checked with. Plain JSON in and out. |
1510
+ | `projectRows(lensOrNarrowing, rows, options?)` | Rows cut to what the lens shows, recursively. Hidden columns, and relations that are off or omitted, are removed. A row a visit's `where` hides is dropped from the root or a list, and a to-one row becomes `null`. `keepClampColumns: true` keeps the columns those `where`s and the projected sources read, even hidden ones, and a hidden to-one row, or a hidden row of a list a clamp reads, as those columns alone, so `check(narrowRule(rule, lens), row)` re-tests the clamps as the database does, for any rule the lens admits; that output carries hidden values, so never return it to a viewer. The other options (`now`, `bindings`) are what each `where` is checked with. A `Decimal` column's value — a Decimal.js-like object such as Prisma's `Decimal` (anything with `toNumber()`), or a numeric string — comes back a number, a list column element by element; a non-numeric value passes through. Plain JSON out. |
1496
1511
 
1497
1512
  ### Evaluating Across Bridges
1498
1513