@inixiative/json-rules 2.27.0 → 3.0.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/dist/index.d.cts CHANGED
@@ -18,7 +18,9 @@ declare const Operator: {
18
18
  readonly exists: "exists";
19
19
  readonly notExists: "notExists";
20
20
  readonly startsWith: "startsWith";
21
+ readonly notStartsWith: "notStartsWith";
21
22
  readonly endsWith: "endsWith";
23
+ readonly notEndsWith: "notEndsWith";
22
24
  };
23
25
  type Operator = (typeof Operator)[keyof typeof Operator];
24
26
  declare const ArrayOperator: {
@@ -48,12 +50,95 @@ declare const DateOperator: {
48
50
  };
49
51
  type DateOperator = (typeof DateOperator)[keyof typeof DateOperator];
50
52
 
53
+ /** A selectable option — the standard `<select>` shape: a value with an optional display
54
+ * label, plus the partition keys (index-aligned with the source's `groupBy` axes)
55
+ * when the source is grouped. */
56
+ type SourceOption = {
57
+ value: string;
58
+ label?: string;
59
+ groups?: string[];
60
+ };
61
+ type FieldMapEntry = {
62
+ kind: 'scalar' | 'object' | 'enum' | 'bridge';
63
+ type: string;
64
+ isList?: boolean;
65
+ /**
66
+ * Whether the column is NOT NULL. `toPrisma` reads this to decide if a negated
67
+ * operator needs an explicit `equals: null` arm (Prisma's `not`/`notIn` follow SQL
68
+ * three-valued logic and drop NULL rows); absent = unknown = no arm.
69
+ */
70
+ isRequired?: boolean;
71
+ fromFields?: string[];
72
+ toFields?: string[];
73
+ relationName?: string;
74
+ /**
75
+ * Per-field allowed values, primarily for enum fields. Takes precedence over
76
+ * `FieldMap.enums[type]` if both are set. Pass-through from codegen
77
+ * (e.g. prisma-map's `EnumField.values`). Consumed by `validateRuleInLens`.
78
+ */
79
+ values?: readonly string[];
80
+ /**
81
+ * A field's selectable option set as `{ value, label? }` pairs — the display
82
+ * shape a picker consumes. On projection/surface output this is populated for
83
+ * every value-gated field (enum members normalized to `{ value, label: value }`)
84
+ * and for sourced fields (the fetched pairs from a materialized `SourceValues`).
85
+ */
86
+ options?: readonly SourceOption[];
87
+ /**
88
+ * Present on projection/surface output when the field's source partitions its
89
+ * options: the dotted to-one axes (relative to this model) whose values are
90
+ * each option's `groups`, index-aligned.
91
+ */
92
+ groupBy?: readonly string[];
93
+ };
94
+ type ModelEntry = {
95
+ dbName?: string | null;
96
+ fields: Record<string, FieldMapEntry>;
97
+ };
98
+ /**
99
+ * A schema map: models keyed by name, plus an optional enum registry scoped to
100
+ * this source. In multi-source setups (Prisma + Salesforce + CRM) each FieldMap
101
+ * carries its own enums so namespaces don't collide across sources.
102
+ */
103
+ type FieldMap = {
104
+ models: Record<string, ModelEntry>;
105
+ /** Enum name → allowed values, e.g. `{ UserRole: ['ADMIN', 'USER'] }`. */
106
+ enums?: Record<string, readonly string[]>;
107
+ };
108
+ type BridgeEndpoint = {
109
+ fieldMap: string;
110
+ model: string;
111
+ on: string;
112
+ };
113
+ type BridgeCardinality = 'oneToOne' | 'oneToMany';
114
+ /**
115
+ * A cross-source edge between two endpoints.
116
+ *
117
+ * Endpoint ordering convention for `oneToMany`:
118
+ * - `endpoints[0]` is the "one" side — its `on` field must be unique per row
119
+ * (typically a primary key).
120
+ * - `endpoints[1]` is the "many" side — its `on` field may repeat across rows
121
+ * (typically a foreign key).
122
+ *
123
+ * Mis-ordering produces wrong `isList` flags during stitching and silent
124
+ * row-dedup when building bridge dictionaries. `indexBridges` throws
125
+ * at runtime if endpoint[0]'s data has duplicate `on` values to catch this.
126
+ *
127
+ * For `oneToOne`, both `on` fields must be unique; endpoint order is symmetric.
128
+ */
129
+ type Bridge = {
130
+ endpoints: [BridgeEndpoint, BridgeEndpoint];
131
+ cardinality: BridgeCardinality;
132
+ };
133
+ type FieldMapSet = {
134
+ maps: Record<string, FieldMap>;
135
+ bridges?: Bridge[];
136
+ };
137
+
51
138
  type FuzzyConfig = {
52
139
  maxDistance?: number;
53
140
  maxRatio?: number;
54
141
  };
55
- declare const maxFuzzyDistance: (length: number) => number;
56
- declare const fuzzyContains: (haystack: string, query: string, config?: FuzzyConfig) => boolean;
57
142
 
58
143
  declare const FieldKind: {
59
144
  readonly String: "String";
@@ -69,11 +154,7 @@ declare const FieldKind: {
69
154
  };
70
155
  type FieldKind = (typeof FieldKind)[keyof typeof FieldKind];
71
156
  declare const NUMERIC_KINDS: readonly FieldKind[];
72
- declare const ORDERABLE_KINDS: readonly FieldKind[];
73
- declare const STRINGY_KINDS: readonly FieldKind[];
74
- declare const EQUATABLE_KINDS: readonly FieldKind[];
75
157
  declare const ALL_KINDS: readonly FieldKind[];
76
- declare const NULLABLE_KINDS: readonly FieldKind[];
77
158
  declare const RuleTarget: {
78
159
  readonly check: "check";
79
160
  readonly toPrisma: "toPrisma";
@@ -96,139 +177,15 @@ declare const ValueShape: {
96
177
  readonly predicate: "predicate";
97
178
  };
98
179
  type ValueShape = (typeof ValueShape)[keyof typeof ValueShape];
99
- type CatalogEntry = {
100
- kinds: readonly FieldKind[];
101
- targets: readonly RuleTarget[];
102
- valueShape: ValueShape;
103
- acceptsExpr?: boolean;
104
- };
105
- declare const FIELD_OPERATOR_CATALOG: Record<Operator, CatalogEntry>;
106
- declare const DATE_OPERATOR_CATALOG: Record<DateOperator, CatalogEntry>;
107
- type ArrayCatalogEntry = {
108
- targets: readonly RuleTarget[];
109
- valueShape: ValueShape;
110
- };
111
- declare const ARRAY_OPERATOR_CATALOG: Record<ArrayOperator, ArrayCatalogEntry>;
112
- declare const WindowSupport: {
113
- readonly full: "full";
114
- readonly extremal: "extremal";
115
- readonly none: "none";
116
- };
117
- type WindowSupport = (typeof WindowSupport)[keyof typeof WindowSupport];
118
- declare const WINDOW_SELECTOR: {
119
- readonly fields: readonly ["filter", "orderBy", "take", "skip"];
120
- readonly sortDirs: readonly ["asc", "desc"];
121
- readonly support: {
122
- readonly array: {
123
- readonly check: "full";
124
- readonly toPrisma: "extremal";
125
- readonly toSql: "none";
126
- };
127
- readonly aggregate: {
128
- readonly check: "full";
129
- readonly toPrisma: "none";
130
- readonly toSql: "none";
131
- };
132
- };
133
- };
134
- type WindowRuleType = keyof typeof WINDOW_SELECTOR.support;
135
- declare const getWindowSupport: (ruleType: WindowRuleType, target: RuleTarget) => WindowSupport;
136
- declare const AGGREGATE_OPERATORS: readonly Operator[];
137
- /** The aggregate threshold comparisons `target` can compile — all of them when no
138
- * target is given. The one source for both the validator's rejection and a builder's
139
- * threshold picker, so neither has to restate which target drops which operator. */
140
- declare const getAggregateOperators: (target?: RuleTarget) => readonly Operator[];
141
- declare const isAggregateSingleOperator: (operator: Operator) => boolean;
142
- declare const isAggregateRangeOperator: (operator: Operator) => boolean;
143
- declare const getValueShape: (operator: Operator | DateOperator | ArrayOperator) => ValueShape;
144
- declare const isOperatorSupportedForTarget: (operator: Operator | DateOperator | ArrayOperator, target: RuleTarget) => boolean;
180
+ /** Which catalog an operator belongs to — `between` is both a field and a date operator. */
181
+ type OperatorFamily = 'field' | 'date' | 'array';
182
+ declare const getValueShape: (operator: string, family: OperatorFamily) => ValueShape;
145
183
  declare const getOperatorsForKind: (kind: FieldKind, target?: RuleTarget) => {
146
184
  field: Operator[];
147
185
  date: DateOperator[];
148
186
  };
149
187
  declare const getArrayOperators: (target?: RuleTarget) => ArrayOperator[];
150
- /** Operators that read no comparison value. */
151
- declare const NO_VALUE_OPERATORS: readonly string[];
152
- /** Field comparisons with an order: `<`, `<=`, `>`, `>=`. */
153
- declare const ORDERED_OPERATORS: readonly string[];
154
- /** A window expression (`within`), not a pair. */
155
- declare const WINDOW_OPERATORS: readonly string[];
156
- /** Operators that compare against two ends. */
157
- declare const RANGE_OPERATORS: readonly string[];
158
- /** Operators with a point to move: the comparisons and both ends of a pair. */
159
- declare const OFFSET_OPERATORS: readonly string[];
160
- /** The negations: each is the complement of its positive form and keeps NULL fields
161
- * (the 2.19.0 ruling). */
162
- declare const NEGATED_OPERATORS: readonly string[];
163
- /** Negations of a two-ended range. */
164
- declare const NEGATED_RANGE_OPERATORS: string[];
165
- /** Negated comparisons an offset can move; with nothing to compare against they still keep a
166
- * null field. */
167
- declare const NEGATED_COMPARISON_OPERATORS: string[];
168
- /** Negations of one literal (`notEquals`, `notContains`). */
169
- declare const NEGATED_SINGLE_VALUE_OPERATORS: string[];
170
- /** Comparisons that bound a field from above / below — what a window's extremal rewrite reads. */
171
- declare const UPPER_BOUND_OPERATORS: readonly string[];
172
- declare const LOWER_BOUND_OPERATORS: readonly string[];
173
- /** Kinds a calendar unit amount can read: whole numbers. */
174
- declare const INTEGER_KINDS: readonly FieldKind[];
175
- /** Kinds check() coerces a literal to (see coerceScalar in src/field.ts). */
176
- declare const COERCIBLE_KINDS: readonly FieldKind[];
177
- /** Kinds whose literal the compilers coerce exactly as check() does — Prisma rejects a string on
178
- * Int/Float/Boolean; BigInt compares as Int. Decimal keeps its literal: Prisma and Postgres take
179
- * the numeric string losslessly, and a JS number would not. */
180
- declare const COMPILE_COERCED_KINDS: readonly FieldKind[];
181
- /** Value shapes that take one literal. */
182
- declare const SINGLE_VALUE_SHAPES: readonly ValueShape[];
183
- /** Each relative unit: the Postgres interval field it adds to, its size there, and whether it is
184
- * a calendar unit (whole steps). Applied months, then days, then time, as Postgres does. */
185
- declare const RELATIVE_UNITS: {
186
- readonly years: {
187
- readonly interval: "months";
188
- readonly factor: 12;
189
- readonly calendar: true;
190
- };
191
- readonly quarters: {
192
- readonly interval: "months";
193
- readonly factor: 3;
194
- readonly calendar: true;
195
- };
196
- readonly months: {
197
- readonly interval: "months";
198
- readonly factor: 1;
199
- readonly calendar: true;
200
- };
201
- readonly weeks: {
202
- readonly interval: "days";
203
- readonly factor: 7;
204
- readonly calendar: true;
205
- };
206
- readonly days: {
207
- readonly interval: "days";
208
- readonly factor: 1;
209
- readonly calendar: true;
210
- };
211
- readonly hours: {
212
- readonly interval: "secs";
213
- readonly factor: 3600;
214
- readonly calendar: false;
215
- };
216
- readonly minutes: {
217
- readonly interval: "secs";
218
- readonly factor: 60;
219
- readonly calendar: false;
220
- };
221
- readonly seconds: {
222
- readonly interval: "secs";
223
- readonly factor: 1;
224
- readonly calendar: false;
225
- };
226
- };
227
- type RelativeUnit = keyof typeof RELATIVE_UNITS;
228
- declare const INTERVAL_FIELDS: readonly ["months", "days", "secs"];
229
- declare const isRelativeUnit: (unit: string) => unit is RelativeUnit;
230
- declare const isCalendarUnit: (unit: string) => boolean;
231
- declare const PERIOD_UNITS: readonly string[];
188
+ declare const getAggregateOperators: () => readonly Operator[];
232
189
 
233
190
  type OperatorValues = typeof Operator;
234
191
  type ArrayOperatorValues = typeof ArrayOperator;
@@ -313,7 +270,7 @@ type StrictOrderedComparisonRule = (RuleBase<OperatorValues['lessThan']> & Value
313
270
  type StrictMembershipRule<TValue = RuleValue> = (RuleBase<OperatorValues['in']> & ValueSource<TValue[]>) | (RuleBase<OperatorValues['notIn']> & ValueSource<TValue[]>);
314
271
  type StrictContainsRule<TValue = RuleValue> = (RuleBase<OperatorValues['contains']> & ValueSource<TValue>) | (RuleBase<OperatorValues['notContains']> & ValueSource<TValue>);
315
272
  type StrictPatternRule = (RuleBase<OperatorValues['matches']> & ValueSource<RegExp | string>) | (RuleBase<OperatorValues['notMatches']> & ValueSource<RegExp | string>);
316
- type StrictStringBoundaryRule = (RuleBase<OperatorValues['startsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['endsWith']> & ValueSource<string>);
273
+ type StrictStringBoundaryRule = (RuleBase<OperatorValues['startsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['notStartsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['endsWith']> & ValueSource<string>) | (RuleBase<OperatorValues['notEndsWith']> & ValueSource<string>);
317
274
  type StrictRangeRule = (RuleBase<OperatorValues['between']> & ValueSource<[OrderedRuleValue, OrderedRuleValue], NumberOffset>) | (RuleBase<OperatorValues['notBetween']> & ValueSource<[OrderedRuleValue, OrderedRuleValue], NumberOffset>);
318
275
  type StrictPresenceRule = (RuleBase<OperatorValues['isEmpty']> & NoValueSource) | (RuleBase<OperatorValues['notEmpty']> & NoValueSource) | (RuleBase<OperatorValues['exists']> & NoValueSource) | (RuleBase<OperatorValues['notExists']> & NoValueSource);
319
276
  type StrictRule<TValue = RuleValue> = StrictEqualityRule<TValue> | StrictOrderedComparisonRule | StrictMembershipRule<TValue> | StrictContainsRule<TValue> | StrictPatternRule | StrictStringBoundaryRule | StrictRangeRule | StrictPresenceRule;
@@ -443,45 +400,36 @@ type StrictIfThenElse<TRuleValue = RuleValue, TDateValue = DateRuleValue> = {
443
400
  error?: string;
444
401
  };
445
402
  type StrictCondition<TRuleValue = RuleValue, TDateValue = DateRuleValue> = StrictRule<TRuleValue> | StrictAggregateRule<TRuleValue, TDateValue> | StrictArrayRule<TRuleValue, TDateValue> | StrictDateRule | StrictAll<TRuleValue, TDateValue> | StrictAny<TRuleValue, TDateValue> | StrictIfThenElse<TRuleValue, TDateValue> | boolean;
403
+ /** A row as a rule reads it: a record of fields. */
404
+ type Row = Record<string, unknown>;
405
+ /** What both compilers take: the schema (a FieldMap, or a FieldMapSet with `mapName`), the
406
+ * model the rule reads, the context `$` refs read, and the clock. */
407
+ type CompileOptions = {
408
+ map?: FieldMap | FieldMapSet;
409
+ mapName?: string;
410
+ model?: string;
411
+ context?: Row;
412
+ } & DateConfig;
413
+ /** What check() evaluates: one row, or a root array of them. */
414
+ type CheckData = Row | unknown[];
446
415
 
447
- type ScopeRef = {
448
- depth: number;
449
- path: string;
416
+ /** `required`: leave out the names an optional bind (`bindOptional`) may go unsupplied. */
417
+ type ListBindingsOptions = {
418
+ required?: boolean;
450
419
  };
451
- declare const parseScopeRef: (ref: string) => ScopeRef | null;
452
- type ScopedRef<S> = {
453
- scope: S;
454
- path: string;
455
- };
456
- type ScopeOutOfBounds = {
457
- outOfBounds: string;
458
- };
459
- declare const resolveScopeRef: <S>(ref: string, scopes: readonly S[]) => ScopedRef<S> | ScopeOutOfBounds;
460
-
461
- /**
462
- * The value of one `{ bind }` at evaluation. Key presence is the contract: an unsupplied
463
- * binding is a caller bug (a forgotten scope must never silently run) unless the source marks
464
- * it `bindOptional`, which reads as null. A supplied-but-undefined binding is null.
465
- */
466
- declare const readBinding: (name: string, optional: boolean | undefined, bindings: Record<string, RuleValue> | undefined) => RuleValue;
467
-
468
- /** Names of every `{ bind }` token in the tree, optional or not — what a lens declares. */
469
- declare const bindingNames: (condition: Condition) => Set<string>;
470
420
  /**
471
- * Names a bindings map must cover: every `{ bind }` token not marked `bindOptional`. A
472
- * name that is optional at one leaf and required at another is required. An optional
473
- * name left unsupplied evaluates and compiles as `null`.
421
+ * The bind names a rule reads, sorted. With `required`, only those a bindings map must cover —
422
+ * not `bindOptional` (unsupplied, it reads null); a name optional at one leaf and required at
423
+ * another is required.
474
424
  */
475
- declare const requiredBindings: (condition: Condition) => Set<string>;
425
+ declare const listBindings: (condition: Condition, { required }?: ListBindingsOptions) => string[];
476
426
  /**
477
427
  * Substitute covered binds with their values; uncovered tokens stay in place (partial
478
428
  * resolution). A supplied-but-undefined binding becomes null to stay serializable.
479
429
  * Non-mutating.
480
430
  */
481
- declare const resolveBindings: (condition: Condition, bindings: Record<string, RuleValue>) => Condition;
431
+ declare const bindRule: (condition: Condition, bindings: Record<string, RuleValue>) => Condition;
482
432
 
483
- type Row$3 = Record<string, unknown>;
484
- type CheckData = Row$3 | unknown[];
485
433
  type CheckOptions = {
486
434
  context?: CheckData;
487
435
  bindings?: Record<string, RuleValue>;
@@ -498,6 +446,9 @@ type EngineGlobalsState = {
498
446
  datasource: {
499
447
  provider: PrismaProvider;
500
448
  };
449
+ /** Prisma's `AnyNull` — matches a DB NULL, a JSON null and an absent Json path. Defaults to
450
+ * your installed @prisma/client's; set it only to use another. */
451
+ anyNull?: unknown;
501
452
  };
502
453
  };
503
454
  type DeepPartial<T> = {
@@ -509,137 +460,33 @@ declare const engineGlobals: {
509
460
  reset: () => void;
510
461
  with: <T>(partial: DeepPartial<EngineGlobalsState>, fn: () => T) => T;
511
462
  };
512
- declare const supportsQueryMode: (provider: PrismaProvider) => boolean;
513
- declare const resolveCaseInsensitive: (ruleFlag?: boolean) => boolean;
514
- declare const resolveFuzzy: (ruleFlag?: boolean | FuzzyConfig) => FuzzyConfig | false;
515
-
516
- type PrismaWhere = Record<string, unknown>;
517
- /** A selectable option — the standard `<select>` shape: a value with an optional display
518
- * label, plus the partition keys (index-aligned with the source's `groupBy` axes)
519
- * when the source is grouped. */
520
- type SourceOption = {
521
- value: string;
522
- label?: string;
523
- groups?: string[];
524
- };
525
- type FieldMapEntry = {
526
- kind: 'scalar' | 'object' | 'enum' | 'bridge';
527
- type: string;
528
- isList?: boolean;
529
- /**
530
- * Whether the column is NOT NULL. `toPrisma` reads this to decide if a negated
531
- * operator needs an explicit `equals: null` arm (Prisma's `not`/`notIn` follow SQL
532
- * three-valued logic and drop NULL rows); absent = unknown = no arm.
533
- */
534
- isRequired?: boolean;
535
- fromFields?: string[];
536
- toFields?: string[];
537
- relationName?: string;
538
- /**
539
- * Per-field allowed values, primarily for enum fields. Takes precedence over
540
- * `FieldMap.enums[type]` if both are set. Pass-through from codegen
541
- * (e.g. prisma-map's `EnumField.values`). Consumed by `checkRuleAgainstLens`.
542
- */
543
- values?: readonly string[];
544
- /**
545
- * A field's selectable option set as `{ value, label? }` pairs — the display
546
- * shape a picker consumes. On projection/surface output this is populated for
547
- * every value-gated field (enum members normalized to `{ value, label: value }`)
548
- * and for sourced fields (the fetched pairs from a materialized `SourceValues`).
549
- */
550
- options?: readonly SourceOption[];
551
- /**
552
- * Present on projection/surface output when the field's source partitions its
553
- * options: the dotted to-one axes (relative to this model) whose values are
554
- * each option's `groups`, index-aligned.
555
- */
556
- groupBy?: readonly string[];
557
- };
558
- type ModelEntry = {
559
- dbName?: string | null;
560
- fields: Record<string, FieldMapEntry>;
561
- };
562
- /**
563
- * A schema map: models keyed by name, plus an optional enum registry scoped to
564
- * this source. In multi-source setups (Prisma + Salesforce + CRM) each FieldMap
565
- * carries its own enums so namespaces don't collide across sources.
566
- */
567
- type FieldMap = {
568
- models: Record<string, ModelEntry>;
569
- /** Enum name → allowed values, e.g. `{ UserRole: ['ADMIN', 'USER'] }`. */
570
- enums?: Record<string, readonly string[]>;
571
- };
572
- type StepRef = {
573
- __step: number;
574
- };
575
- type GroupByStep = {
576
- operation: 'groupBy';
577
- model: string;
578
- args: {
579
- by: string[];
580
- where: Record<string, unknown>;
581
- having: Record<string, unknown>;
582
- };
583
- extract: string;
584
- };
585
- type WhereStep = {
586
- operation: 'where';
587
- where: Record<string, unknown>;
588
- };
589
- type PrismaStep = GroupByStep | WhereStep;
590
- type ToPrismaResult = {
591
- steps: PrismaStep[];
592
- };
593
- type BuildOptions = {
594
- map?: FieldMap | FieldMapSet;
595
- mapName?: string;
596
- model?: string;
597
- context?: Record<string, unknown>;
598
- datasource?: {
599
- provider?: PrismaProvider;
600
- };
601
- } & DateConfig;
602
-
603
- type BridgeEndpoint = {
604
- fieldMap: string;
605
- model: string;
606
- on: string;
607
- };
608
- type BridgeCardinality = 'oneToOne' | 'oneToMany';
609
- /**
610
- * A cross-source edge between two endpoints.
611
- *
612
- * Endpoint ordering convention for `oneToMany`:
613
- * - `endpoints[0]` is the "one" side — its `on` field must be unique per row
614
- * (typically a primary key).
615
- * - `endpoints[1]` is the "many" side — its `on` field may repeat across rows
616
- * (typically a foreign key).
617
- *
618
- * Mis-ordering produces wrong `isList` flags during stitching and silent
619
- * row-dedup when building bridge dictionaries. `buildBridgeDictionary` throws
620
- * at runtime if endpoint[0]'s data has duplicate `on` values to catch this.
621
- *
622
- * For `oneToOne`, both `on` fields must be unique; endpoint order is symmetric.
623
- */
624
- type Bridge = {
625
- endpoints: [BridgeEndpoint, BridgeEndpoint];
626
- cardinality: BridgeCardinality;
627
- };
628
- type FieldMapSet = {
629
- maps: Record<string, FieldMap>;
630
- bridges?: Bridge[];
631
- };
632
463
 
633
- type Row$2 = Record<string, unknown>;
634
464
  type BridgeDictionary = Record<string, // map name
635
465
  Record<string, // model name
636
- Record<string, Record<string, Row$2 | Row$2[]>>>>;
637
- declare const buildBridgeDictionary: (set: FieldMapSet, rawData: Record<string, Row$2[]>) => BridgeDictionary;
466
+ Record<string, Record<string, Row | Row[]>>>>;
467
+ declare const indexBridges: (set: FieldMapSet, rawData: Record<string, Row[]>) => BridgeDictionary;
638
468
 
639
469
  declare const stitchFieldMaps: (set: FieldMapSet) => FieldMapSet;
640
470
 
641
- declare const validateFieldMapSet: (set: FieldMapSet) => void;
642
- declare const validateFieldMap: (fieldMap: FieldMap, mapName?: string) => void;
471
+ type ValidationIssue = {
472
+ path: string;
473
+ message: string;
474
+ code: string;
475
+ };
476
+ type ValidationResult = {
477
+ ok: boolean;
478
+ errors: ValidationIssue[];
479
+ };
480
+ /** Which engine a rule must compile for; `check` (the default) accepts every rule. */
481
+ type ValidateRuleOptions = {
482
+ target?: RuleTarget;
483
+ };
484
+ declare const validateRule: (condition: unknown, options?: ValidateRuleOptions) => ValidationResult;
485
+ declare const assertValidRule: (condition: unknown, options?: ValidateRuleOptions) => asserts condition is Condition;
486
+
487
+ /** Field names are plain identifiers: `.` walks a path and `:` names a bridge target. */
488
+ declare const validateFieldMaps: (set: FieldMapSet) => ValidationResult;
489
+ declare const assertValidFieldMaps: (set: FieldMapSet) => void;
643
490
 
644
491
  type Lens = FieldMapSet & {
645
492
  mapName: string;
@@ -653,8 +500,8 @@ type Lens = FieldMapSet & {
653
500
  * - SCHEMA narrowing (picks/omits/enumPicks/enumOmits): controls what's visible
654
501
  * in the type surface. AI/SDK consumers can't see narrowed-away fields.
655
502
  * - DATA narrowing (where): controls which ROWS are in scope. Filter-first
656
- * semantic, anchored to the model. Under arrayOperator: 'all', applied via
657
- * implication (negate) to preserve filter-first meaning — see applyLens.
503
+ * semantic, anchored to the model. Under arrayOperator: 'all', it becomes the window filter
504
+ * (filter-first) — see narrowRule.
658
505
  */
659
506
  type ModelDefaultNarrowing = {
660
507
  picks?: string[];
@@ -677,7 +524,7 @@ type ModelDefaultNarrowing = {
677
524
  * model that path resolves to. The `where` composes AND-only across layers (general
678
525
  * via `mapDefaults`, path-specific via `root`/`relations`); a later layer's `label` wins.
679
526
  */
680
- sources?: Record<string, SourceValue>;
527
+ sources?: Record<string, SourceEntry>;
681
528
  };
682
529
  /**
683
530
  * A sourced field's eligibility `where` plus an optional display-label column — a
@@ -701,7 +548,7 @@ type SourceSpec = {
701
548
  groupBy: string | string[];
702
549
  };
703
550
  /** A `sources` entry: a bare eligibility `Condition`, or a richer `SourceSpec`. */
704
- type SourceValue = Condition | SourceSpec;
551
+ type SourceEntry = Condition | SourceSpec;
705
552
  /** Narrowing for a model at a specific traversal path. Adds relations to the default shape. */
706
553
  type ModelNarrowing = ModelDefaultNarrowing & {
707
554
  relations?: Record<string, ModelNarrowing>;
@@ -730,8 +577,6 @@ type LensNarrowing = {
730
577
  mapDefaults?: Record<string, NarrowingDefaults>;
731
578
  };
732
579
 
733
- declare const applyLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => Condition;
734
-
735
580
  /**
736
581
  * Every bind name a lens (its whole narrowing chain) needs supplied to execute —
737
582
  * `bindOptional` tokens are not required (unsupplied, they resolve to null).
@@ -740,29 +585,74 @@ declare const applyLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing
740
585
  * this lens require" answer; pass `narrowing.parent` to see the names a child must
741
586
  * not collide with.
742
587
  */
743
- declare const lensRequiredBindings: (lensOrNarrowing: Lens | LensNarrowing) => Set<string>;
588
+ declare const listLensBindings: (lensOrNarrowing: Lens | LensNarrowing) => string[];
744
589
  /**
745
590
  * Preprocess a lens: resolve every `{ bind }` token the map covers in the chain's
746
591
  * `where`/`sources`, returning a structurally-new lens with concrete conditions.
747
592
  * Partial — uncovered tokens stay, so stages bind progressively. Once resolved,
748
- * `applyLens` / `toPrisma` / `toSql` / `sourceQueries` / `projectByPath` consume the
593
+ * `narrowRule` / `toPrisma` / `toSql` / `toSourceQueries` / `projectPaths` consume the
749
594
  * lens unchanged: a bind needs nothing new downstream. `parent:name` draws the same
750
595
  * value as the ancestor's `name`. Does not mutate the input.
751
596
  */
752
- declare const resolveLensBindings: (lensOrNarrowing: Lens | LensNarrowing, bindings: Record<string, RuleValue>) => Lens | LensNarrowing;
597
+ declare const bindLens: (lensOrNarrowing: Lens | LensNarrowing, bindings: Record<string, RuleValue>) => Lens | LensNarrowing;
598
+
599
+ declare const coerceRule: (condition: Condition, lensOrNarrowing: Lens | LensNarrowing) => Condition;
600
+
601
+ /** A lens over field maps, its bridges stitched into the maps as fields. */
602
+ declare const createLens: ({ maps, bridges, mapName, model }: Lens) => Lens;
603
+
604
+ type RuleDescription = {
605
+ sources: string[];
606
+ bridgesCrossed: boolean;
607
+ supportedTargets: RuleTarget[];
608
+ /** What the lens refuses in the rule — validateRuleInLens's issues. */
609
+ errors: ValidationIssue[];
610
+ };
611
+ declare const describeRule: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleDescription;
612
+
753
613
  /**
754
- * Bind names are unique across a composed chain: a layer may not re-declare a name
755
- * an ancestor already declares — rename it, or reference the inherited one read-only
756
- * as `parent:name`. A `parent:name` reference must point at a name some ancestor
757
- * actually declares. Returns the violation messages (folded into `validateNarrowing`).
614
+ * The values one rule compares at one declared source — keyed the way `projectPaths`
615
+ * keys a source (`path` + `field`), so the caller can join it back to the source's
616
+ * model without spelling a path of its own. A `mapDefaults`-declared source resolves
617
+ * wherever its model appears, so `path` may name a relation chain the narrowing never
618
+ * spelled under `root.relations`; the dotted format is the same.
758
619
  */
759
- declare const validateBindNames: (narrowing: LensNarrowing) => string[];
620
+ type RuleSourceDescription = {
621
+ path: string;
622
+ mapName: string;
623
+ model: string;
624
+ field: string;
625
+ /** Every literal a leaf at this source named; list operators flattened, deduped by content. */
626
+ values: RuleValue[];
627
+ /**
628
+ * The set of values cannot be enumerated from literals: a leaf read a value at evaluation
629
+ * (a `path` / `bind` on its comparison value, an offset or an amount) or moved it by an offset, used an operator that describes values without naming them
630
+ * (substring, pattern, range, date window), or used an operator the catalog does not
631
+ * know. A caller deciding anything from `values` must fail closed.
632
+ */
633
+ dynamic: boolean;
634
+ };
635
+ /**
636
+ * Which values a rule names at each source the lens declares — the lens owns the
637
+ * vocabulary, so it answers questions about it; callers never spell a path. A leaf reaches a
638
+ * source by its absolute path through the lens: nested (`{ field: 'orders', arrayOperator,
639
+ * condition: { field: 'sku' } }`) and dotted (`{ field: 'orders.sku' }`) spellings are one path,
640
+ * resolved by `lensPathEnd` — visibility, `mapDefaults`, and the Json boundary all apply, so a
641
+ * source declared in `mapDefaults` answers wherever its model appears. Quantifier-blind on
642
+ * purpose — a `none` relation names its value as much as an `any` one, `notIn` as much as `in` —
643
+ * but shape-aware via the operator catalog: only literal-naming shapes contribute `values`;
644
+ * substring / pattern / range / window operators, and operators the catalog does not know, mark
645
+ * the source `dynamic` instead of inventing values. A relation node's own comparison (an
646
+ * aggregate's threshold, an array `count`) belongs to the node, not to a source. Paths invisible
647
+ * under the lens, unmapped segments, and sub-paths beneath a Json column are silent.
648
+ */
649
+ declare const describeRuleSources: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleSourceDescription[];
760
650
 
761
651
  type LensPathHop = {
762
652
  field: string;
763
653
  entry: FieldMapEntry;
764
654
  mapName: string;
765
- modelName: string;
655
+ model: string;
766
656
  /** The relation path from the lens anchor to the model this hop reads. */
767
657
  relPath: string[];
768
658
  };
@@ -783,35 +673,9 @@ type LensPathResolution = {
783
673
  hops: LensPathHop[];
784
674
  };
785
675
 
786
- type RuleLensViolation = {
787
- path: string;
788
- reason: string;
789
- };
790
- type RuleLensCheck = {
791
- ok: boolean;
792
- violations: RuleLensViolation[];
793
- };
794
- declare const checkRuleAgainstLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleLensCheck;
795
-
796
- type CreateLensInput = {
797
- maps: Record<string, FieldMap>;
798
- bridges?: Bridge[];
799
- mapName: string;
800
- model: string;
801
- };
802
- declare const createLens: (input: CreateLensInput) => Lens;
803
-
804
- type RuleDescription = {
805
- sources: string[];
806
- bridgesCrossed: boolean;
807
- supportedTargets: RuleTarget[];
808
- violations: string[];
809
- };
810
- declare const describeRule: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => RuleDescription;
811
-
812
676
  type ProjectedVisit = {
813
677
  mapName: string;
814
- modelName: string;
678
+ model: string;
815
679
  fields: Record<string, FieldMapEntry>;
816
680
  whereClauses: Condition[];
817
681
  /** Per-field source eligibility wheres, composed across layers (general + path). */
@@ -822,12 +686,13 @@ type ProjectedVisit = {
822
686
  /** Per-field option-partition axes for a sourced field (from a SourceSpec's `groupBy`). */
823
687
  sourceGroupBys: Record<string, string[]>;
824
688
  };
825
- type PathProjection = Map<string, ProjectedVisit>;
689
+ /** Each declared path's projected visit, keyed by dotted path from the lens model. */
690
+ type PathProjection = Record<string, ProjectedVisit>;
826
691
  /**
827
692
  * The materialized option set for one sourced field — the fetched companion to a
828
693
  * serializable lens. Its `options` are `{ value, label? }` pairs (the standard
829
- * `<select>` shape); it feeds both projections: `projectByPath` keys by
830
- * `path`+`field` (exact), `exposedSurface` by `mapName`+`model`+`field` (union).
694
+ * `<select>` shape); it feeds both projections: `projectPaths` keys by
695
+ * `path`+`field` (exact), `projectModels` by `mapName`+`model`+`field` (union).
831
696
  */
832
697
  type SourceValues = {
833
698
  path: string;
@@ -836,61 +701,37 @@ type SourceValues = {
836
701
  field: string;
837
702
  options: readonly SourceOption[];
838
703
  };
839
- type ProjectOptions = {
704
+ type ProjectLensOptions = {
840
705
  sourceValues?: readonly SourceValues[];
841
706
  };
842
- declare const projectByPath: (lensOrNarrowing: Lens | LensNarrowing, opts?: ProjectOptions) => PathProjection;
843
-
844
- declare const exposedSurface: (lensOrNarrowing: Lens | LensNarrowing, opts?: ProjectOptions) => Lens;
845
707
 
846
- declare const validateNarrowing: (narrowing: LensNarrowing) => void;
847
-
848
- /**
849
- * Resolve one dotted path through a lens, hop by hop, verifying as it walks: every hop is checked
850
- * against the narrowing at that visit, so a relation the narrowing dropped is `hidden`, a column the
851
- * model lacks is `missing`, and a segment past a scalar is `pastScalar`. This is the walk
852
- * `checkRuleAgainstLens` gates a rule's field with, exposed for consumers that resolve paths of their
853
- * own (template tokens, loop bindings, presence guards).
854
- */
855
- declare const resolveLensPath: (lensOrNarrowing: Lens | LensNarrowing, path: string) => LensPathResolution;
856
-
857
- /**
858
- * The values one rule compares at one declared source — keyed the way `projectByPath`
859
- * keys a source (`path` + `field`), so the caller can join it back to the source's
860
- * model without spelling a path of its own. A `mapDefaults`-declared source resolves
861
- * wherever its model appears, so `path` may name a relation chain the narrowing never
862
- * spelled under `root.relations`; the dotted format is the same.
863
- */
864
- type RuleSourceValues = {
865
- path: string;
866
- mapName: string;
708
+ type PrismaWhere = Record<string, unknown>;
709
+ type StepRef = {
710
+ __step: number;
711
+ };
712
+ type GroupByStep = {
713
+ operation: 'groupBy';
867
714
  model: string;
868
- field: string;
869
- /** Every literal a leaf at this source named; list operators flattened, deduped by content. */
870
- values: RuleValue[];
871
- /**
872
- * The set of values cannot be enumerated from literals: a leaf took its value from
873
- * `path` / `bind`, used an operator that describes values without naming them
874
- * (substring, pattern, range, date window), or used an operator the catalog does not
875
- * know. A caller deciding anything from `values` must fail closed.
876
- */
877
- dynamic: boolean;
715
+ args: {
716
+ by: string[];
717
+ where: Record<string, unknown>;
718
+ having: Record<string, unknown>;
719
+ };
720
+ extract: string;
721
+ };
722
+ type WhereStep = {
723
+ operation: 'where';
724
+ where: Record<string, unknown>;
725
+ };
726
+ type PrismaStep = GroupByStep | WhereStep;
727
+ type ToPrismaResult = {
728
+ steps: PrismaStep[];
729
+ };
730
+ type ToPrismaOptions = CompileOptions & {
731
+ datasource?: {
732
+ provider?: PrismaProvider;
733
+ };
878
734
  };
879
- /**
880
- * Which values a rule names at each source the lens declares — the lens owns the
881
- * vocabulary, so it answers questions about it; callers never spell a path. A leaf reaches a
882
- * source by its absolute path through the lens: nested (`{ field: 'orders', arrayOperator,
883
- * condition: { field: 'sku' } }`) and dotted (`{ field: 'orders.sku' }`) spellings are one path,
884
- * resolved by `walkLensPath` — visibility, `mapDefaults`, and the Json boundary all apply, so a
885
- * source declared in `mapDefaults` answers wherever its model appears. Quantifier-blind on
886
- * purpose — a `none` relation names its value as much as an `any` one, `notIn` as much as `in` —
887
- * but shape-aware via the operator catalog: only literal-naming shapes contribute `values`;
888
- * substring / pattern / range / window operators, and operators the catalog does not know, mark
889
- * the source `dynamic` instead of inventing values. A relation node's own comparison (an
890
- * aggregate's threshold, an array `count`) belongs to the node, not to a source. Paths invisible
891
- * under the lens, unmapped segments, and sub-paths beneath a Json column are silent.
892
- */
893
- declare const ruleSourceValues: (lensOrNarrowing: Lens | LensNarrowing, rule: Condition) => RuleSourceValues[];
894
735
 
895
736
  /** Prisma `select` shape — nested for a grouped source's relation path. */
896
737
  type SourceSelect = {
@@ -901,11 +742,11 @@ type SourceSelect = {
901
742
  type SourcePrismaQuery = {
902
743
  model: string;
903
744
  /** Absent for grouped sources — DISTINCT on the value column alone would collapse
904
- * same-value rows across groups; dedup happens in `sourceValuesFromQueryRows`. */
745
+ * same-value rows across groups; dedup happens in `materializeSourceQuery`. */
905
746
  distinct?: string[];
906
747
  select: SourceSelect;
907
748
  where: PrismaWhere;
908
- /** Present only if the composed where used count operators (run via executePrismaQueryPlan). */
749
+ /** Present only if the composed where used count operators (run via executePrismaPlan). */
909
750
  steps?: PrismaStep[];
910
751
  };
911
752
  /** `sql` is null when the composed where uses a predicate SQL can't express
@@ -937,41 +778,103 @@ type SourceQuery = {
937
778
  * the projected lens. The WHERE is the field's composed eligibility: the model's
938
779
  * own narrowing at that path AND its source where(s). The app runs these (with
939
780
  * its own client) to materialize each field's option set — feed the fetched rows
940
- * to `sourceValuesFromQueryRows`.
781
+ * to `materializeSourceQuery`.
941
782
  */
942
- declare const sourceQueries: (lensOrNarrowing: Lens | LensNarrowing) => SourceQuery[];
783
+ declare const toSourceQueries: (lensOrNarrowing: Lens | LensNarrowing) => SourceQuery[];
943
784
 
944
- type Row$1 = Record<string, unknown>;
945
785
  /** Which executor produced the rows — the caller always knows; never guessed. */
946
786
  type SourceRowShape = 'prisma' | 'sql';
947
787
  /**
948
788
  * Materialize one compiled `SourceQuery`'s fetched rows into its `SourceValues` —
949
- * the executor-side counterpart of `sourceQueries`, so apps never hand-map rows.
789
+ * the executor-side counterpart of `toSourceQueries`, so apps never hand-map rows.
950
790
  * `rowShape` names the wire format: prisma rows (default) nest each `groupBy` axis
951
791
  * (and a dotted `label`) as related objects; sql rows carry them flat under the
952
792
  * statement's `__group_i` / `__label` aliases. Grouped queries fetch without
953
793
  * DISTINCT, so dedup per (groups, value) happens here.
954
794
  */
955
- declare const sourceValuesFromQueryRows: (query: SourceQuery, rows: readonly Row$1[], opts?: {
795
+ /** `rowShape`: how the rows came back — nested Prisma rows (the default) or flat SQL rows. */
796
+ type MaterializeSourceQueryOptions = {
956
797
  rowShape?: SourceRowShape;
957
- }) => SourceValues;
798
+ };
799
+ declare const materializeSourceQuery: (query: SourceQuery, rows: readonly Row[], opts?: MaterializeSourceQueryOptions) => SourceValues;
958
800
 
959
- type Row = Record<string, unknown>;
960
801
  /**
961
802
  * Materialize each sourced field's option set from an already-fetched collection —
962
- * the in-memory executor of `sources` declarations, alongside `sourceQueries`
803
+ * the in-memory executor of `sources` declarations, alongside `toSourceQueries`
963
804
  * (which compiles the same declarations to DISTINCT queries for a DB). Rows are
964
- * the collection fetched UNDER the lens (relations inline), so they are already
965
- * lens-scoped: eligibility here is the field's source `where` only, evaluated via
966
- * `check()` (`options` feeds `{bind}` clauses). Scalar-list fields contribute one
805
+ * the collection fetched under the lens (relations inline). Each row must meet the field's
806
+ * eligibility as `toSourceQueries` composes it — its source `where`, the grants above it, the
807
+ * guards of the relations it crosses and any allowed values — evaluated with `check()`
808
+ * (`options` feeds `{bind}` clauses). Scalar-list fields contribute one
967
809
  * option per element, labels take the first non-null value of the label column
968
810
  * (a sibling, or a dotted to-one path read through the nested rows), and sorting is
969
- * numeric-aware in a fixed locale. Feed the result to `exposedSurface` /
970
- * `projectByPath` as `{ sourceValues }`.
811
+ * numeric-aware in a fixed locale. Feed the result to `projectLens` as `{ sourceValues }`.
812
+ */
813
+ declare const materializeSources: (lensOrNarrowing: Lens | LensNarrowing, rows: readonly Row[], options?: CheckOptions) => SourceValues[];
814
+
815
+ declare const validateNarrowing: (narrowing: LensNarrowing) => ValidationResult;
816
+ declare const assertValidNarrowing: (narrowing: LensNarrowing) => void;
817
+
818
+ declare const narrowRule: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => Condition;
819
+
820
+ /**
821
+ * What a narrowed lens exposes. `by: 'path'` (the default) projects each declared path — its
822
+ * visible fields, `where` clauses and sources — keyed by dotted path. `by: 'model'` flattens the
823
+ * whole surface into a Lens: every model a path or relation reaches, each field the union of its
824
+ * visits, bridges kept only where an exposed field crosses them.
825
+ */
826
+ declare function projectLens(lensOrNarrowing: Lens | LensNarrowing, options?: ProjectLensOptions & {
827
+ by?: 'path';
828
+ }): PathProjection;
829
+ declare function projectLens(lensOrNarrowing: Lens | LensNarrowing, options: ProjectLensOptions & {
830
+ by: 'model';
831
+ }): Lens;
832
+
833
+ /**
834
+ * A lens as stored, one record per layer: its `id`, the ids of every layer it composes with —
835
+ * the base lens first, the nearest parent last — and its own part. The base lens is the
836
+ * root-most layer: the lens itself, with no parents.
837
+ */
838
+ type StoredLens = {
839
+ id: string;
840
+ parents: string[];
841
+ } & (Lens | Omit<LensNarrowing, 'parent'>);
842
+ /**
843
+ * The composed lens a stored layer resolves to: its parents, read from `records`, nested from
844
+ * the base down, each layer validated against the ones above it. Fails closed on a missing
845
+ * record, a base that isn't first, or a parent whose own parents disagree with the list.
846
+ */
847
+ declare const composeLens: (id: string, records: Record<string, StoredLens>) => Lens | LensNarrowing;
848
+ /** A composed lens as the records `composeLens` reads back: one per layer, the base first,
849
+ * named by `ids` in the same order. */
850
+ declare const storeLens: (lens: Lens | LensNarrowing, ids: readonly string[]) => StoredLens[];
851
+
852
+ /** Gate a rule against a lens: every field and value-side ref resolves through it, and every
853
+ * operator, value and amount fits the field it reaches. */
854
+ declare const validateRuleInLens: (rule: Condition, lensOrNarrowing: Lens | LensNarrowing) => ValidationResult;
855
+
856
+ /**
857
+ * Resolve one dotted path through a lens, hop by hop, verifying as it walks: every hop is checked
858
+ * against the narrowing at that visit, so a relation the narrowing dropped is `hidden`, a column the
859
+ * model lacks is `missing`, and a segment past a scalar is `pastScalar`. This is the walk
860
+ * `validateRuleInLens` gates a rule's field with, exposed for consumers that resolve paths of their
861
+ * own (template tokens, loop bindings, presence guards).
971
862
  */
972
- declare const sourceValuesFromRows: (lensOrNarrowing: Lens | LensNarrowing, rows: readonly Row[], options?: CheckOptions) => SourceValues[];
863
+ declare const walkLensPath: (lensOrNarrowing: Lens | LensNarrowing, path: string) => LensPathResolution;
973
864
 
974
- declare const stampCoercions: (condition: Condition, lensOrNarrowing: Lens | LensNarrowing) => Condition;
865
+ type ScopeRef = {
866
+ depth: number;
867
+ path: string;
868
+ };
869
+ declare const parseScopeRef: (ref: string) => ScopeRef | null;
870
+ type ScopedRef<S> = {
871
+ scope: S;
872
+ path: string;
873
+ };
874
+ type ScopeOutOfBounds = {
875
+ outOfBounds: string;
876
+ };
877
+ declare const readScopeRef: <S>(ref: string, scopes: readonly S[]) => ScopedRef<S> | ScopeOutOfBounds;
975
878
 
976
879
  /**
977
880
  * Execute a Prisma query plan produced by toPrisma().
@@ -987,75 +890,39 @@ declare const stampCoercions: (condition: Condition, lensOrNarrowing: Lens | Len
987
890
  *
988
891
  * @example
989
892
  * const plan = toPrisma(condition, { map, model: 'User' });
990
- * const where = await executePrismaQueryPlan(plan, { post: prisma.post });
893
+ * const where = await executePrismaPlan(plan, { post: prisma.post });
991
894
  * await prisma.user.findMany({ where });
992
895
  */
993
- declare const executePrismaQueryPlan: (result: ToPrismaResult, prismaDelegate: Record<string, Record<string, (...args: unknown[]) => unknown>>) => Promise<Record<string, unknown>>;
896
+ declare const executePrismaPlan: (plan: ToPrismaResult, prismaDelegate: Record<string, Record<string, (...args: unknown[]) => unknown>>) => Promise<Record<string, unknown>>;
994
897
 
995
898
  /**
996
- * Convert a json-rules Condition to a Prisma query plan.
997
- *
998
- * Returns a `ToPrismaResult` with:
999
- * - `where` – the Prisma WHERE clause
1000
- * - `steps` – optional array of groupBy steps for count-based relation filters
1001
- * (only present when `atLeast`/`atMost`/`exactly` operators are used with a map)
1002
- *
1003
- * When `steps` is present, pass the result to `executePrismaQueryPlan` to
1004
- * resolve step refs before using `where` in a Prisma query.
1005
- *
1006
- * @param condition - The rule condition to convert
1007
- * @param options - Optional map, model, and context
899
+ * Compile a condition to a Prisma query plan: `steps`, any groupBy steps (counts and relation
900
+ * aggregates, which need `{ map, model }`) and then the final `where`. Run a plan with
901
+ * `executePrismaPlan(plan, client)` to resolve step refs; a single-step plan's `where` is its
902
+ * last step's.
1008
903
  *
1009
904
  * @example
1010
905
  * ```typescript
1011
- * // Simple scalar
1012
- * toPrisma({ field: 'status', operator: Operator.equals, value: 'active' })
1013
- * // → { where: { status: { equals: 'active' } } }
1014
- *
1015
- * // JSON field detection (map required)
1016
- * toPrisma({ field: 'metadata.theme', operator: Operator.equals, value: 'dark' }, { map, model: 'User' })
1017
- * // → { where: { metadata: { path: ['theme'], equals: 'dark' } } }
906
+ * toPrisma({ field: 'status', operator: Operator.equals, value: 'active' }).steps
907
+ * // → [{ operation: 'where', where: { status: { equals: 'active' } } }]
1018
908
  *
1019
- * // Context path ref
1020
- * toPrisma({ field: 'userId', operator: Operator.equals, path: 'currentUser.id' }, { context: { currentUser: { id: '123' } } })
1021
- * // → { where: { userId: { equals: '123' } } }
1022
- *
1023
- * // Multi-step (map required)
1024
- * const plan = toPrisma({ field: 'posts', arrayOperator: 'atLeast', count: 3, condition: {...} }, { map, model: 'User' });
1025
- * const where = await executePrismaQueryPlan(plan, { post: prisma.post });
909
+ * const plan = toPrisma({ field: 'posts', arrayOperator: 'atLeast', count: 3, condition }, { map, model: 'User' });
910
+ * const where = await executePrismaPlan(plan, prisma);
1026
911
  * await prisma.user.findMany({ where });
1027
912
  * ```
1028
913
  */
1029
- declare const toPrisma: (condition: Condition, options?: BuildOptions) => ToPrismaResult;
914
+ declare const toPrisma: (condition: Condition, options?: ToPrismaOptions) => ToPrismaResult;
1030
915
 
1031
- type SqlResult = {
916
+ type ToSqlResult = {
1032
917
  sql: string;
1033
918
  params: unknown[];
1034
919
  joins: string[];
1035
920
  };
1036
-
1037
- type SqlBuildOptions = {
1038
- map?: FieldMap;
1039
- model?: string;
921
+ type ToSqlOptions = CompileOptions & {
922
+ /** The root table alias; `t0` when a map is given. */
1040
923
  alias?: string;
1041
- context?: Record<string, unknown>;
1042
- } & DateConfig;
1043
- declare const toSql: (condition: Condition, options?: SqlBuildOptions) => SqlResult;
1044
-
1045
- type ValidationIssue = {
1046
- path: string;
1047
- message: string;
1048
- code: string;
1049
924
  };
1050
- type ValidationResult = {
1051
- ok: boolean;
1052
- errors: ValidationIssue[];
1053
- };
1054
- declare const validateRule: (condition: unknown, options?: {
1055
- target?: RuleTarget;
1056
- }) => ValidationResult;
1057
- declare const assertValidRule: (condition: unknown, options?: {
1058
- target?: RuleTarget;
1059
- }) => asserts condition is Condition;
1060
925
 
1061
- export { AGGREGATE_OPERATORS, ALL_KINDS, ARRAY_OPERATOR_CATALOG, type AggregateMode, type AggregateRule, type All, type Any, type ArrayCatalogEntry, ArrayOperator, type ArrayRule, type Bridge, type BridgeCardinality, type BridgeDictionary, type BridgeEndpoint, type BuildOptions, COERCIBLE_KINDS, COMPILE_COERCED_KINDS, type CatalogEntry, type CheckOptions, type Condition, type CreateLensInput, DATE_OPERATOR_CATALOG, type DateConfig, type DateExpr, type DateInputOrExpr, type DateInputValue, type DateOffset, DateOperator, type DateRule, type DateRuleValue, EQUATABLE_KINDS, type EdgeExpr, type EngineGlobalsState, type EnumNarrowing, FIELD_OPERATOR_CATALOG, FieldKind, type FieldMap, type FieldMapEntry, type FieldMapSet, type FuzzyConfig, type GroupByStep, INTEGER_KINDS, INTERVAL_FIELDS, type IfThenElse, LOWER_BOUND_OPERATORS, type Lens, type LensNarrowing, type LensPathHop, type LensPathResolution, type Magnitude, type ModelDefaultNarrowing, type ModelNarrowing, NEGATED_COMPARISON_OPERATORS, NEGATED_OPERATORS, NEGATED_RANGE_OPERATORS, NEGATED_SINGLE_VALUE_OPERATORS, NO_VALUE_OPERATORS, NULLABLE_KINDS, NUMERIC_KINDS, type NarrowingDefaults, type NumberOffset, OFFSET_OPERATORS, ORDERABLE_KINDS, ORDERED_OPERATORS, Operator, type OrderBy, type OrderedRuleValue, PERIOD_UNITS, type PathProjection, type PeriodExpr, type PeriodUnit, type PrismaProvider, type PrismaStep, type PrismaWhere, type ProjectOptions, type ProjectedVisit, RANGE_OPERATORS, RELATIVE_UNITS, type RelativeUnit, type RelativeUnits, type RollingExpr, type Rule, type RuleDescription, type RuleLensCheck, type RuleLensViolation, type RuleScalar, type RuleSourceValues, RuleTarget, type RuleValue, SINGLE_VALUE_SHAPES, STRINGY_KINDS, type ScopeOutOfBounds, type ScopeRef, type ScopedRef, type SortDir, type SourceOption, type SourcePrismaQuery, type SourceQuery, type SourceRowShape, type SourceSpec, type SourceSqlQuery, type SourceValue, type SourceValues, type SqlResult, type StepRef, type StrictAggregateRule, type StrictAll, type StrictAny, type StrictArrayCountRule, type StrictArrayPredicateRule, type StrictArrayPresenceRule, type StrictArrayRule, type StrictCondition, type StrictContainsRule, type StrictDateComparisonRule, type StrictDateDayRule, type StrictDateRangeRule, type StrictDateRule, type StrictEqualityRule, type StrictIfThenElse, type StrictMembershipRule, type StrictOrderedComparisonRule, type StrictPatternRule, type StrictPresenceRule, type StrictRangeRule, type StrictRule, type StrictStringBoundaryRule, type TimeZoneConfig, type ToPrismaResult, UPPER_BOUND_OPERATORS, type ValidationIssue, type ValidationResult, ValueShape, type ValueSourceFields, type ValueSourceOf, WINDOW_OPERATORS, WINDOW_SELECTOR, type WeekStart, type WhereStep, type WindowFields, type WindowRuleType, WindowSupport, applyLens, assertValidRule, bindingNames, buildBridgeDictionary, check, checkRuleAgainstLens, createLens, describeRule, engineGlobals, executePrismaQueryPlan, exposedSurface, fuzzyContains, getAggregateOperators, getArrayOperators, getOperatorsForKind, getValueShape, getWindowSupport, isAggregateRangeOperator, isAggregateSingleOperator, isCalendarUnit, isOperatorSupportedForTarget, isRelativeUnit, lensRequiredBindings, maxFuzzyDistance, parseScopeRef, projectByPath, readBinding, requiredBindings, resolveBindings, resolveCaseInsensitive, resolveFuzzy, resolveLensBindings, resolveLensPath, resolveScopeRef, ruleSourceValues, sourceQueries, sourceValuesFromQueryRows, sourceValuesFromRows, stampCoercions, stitchFieldMaps, supportsQueryMode, toPrisma, toSql, validateBindNames, validateFieldMap, validateFieldMapSet, validateNarrowing, validateRule };
926
+ declare const toSql: (condition: Condition, options?: ToSqlOptions) => ToSqlResult;
927
+
928
+ export { ALL_KINDS, type AggregateMode, type AggregateRule, type All, type Any, ArrayOperator, type ArrayRule, type Bridge, type BridgeCardinality, type BridgeDictionary, type BridgeEndpoint, type CheckData, type CheckOptions, type CompileOptions, type Condition, type DateConfig, type DateExpr, type DateInputOrExpr, type DateInputValue, type DateOffset, DateOperator, type DateRule, type DateRuleValue, type EdgeExpr, type EngineGlobalsState, type EnumNarrowing, FieldKind, type FieldMap, type FieldMapEntry, type FieldMapSet, type FuzzyConfig, type GroupByStep, type IfThenElse, type Lens, type LensNarrowing, type LensPathHop, type LensPathResolution, type ListBindingsOptions, type Magnitude, type MaterializeSourceQueryOptions, type ModelDefaultNarrowing, type ModelEntry, type ModelNarrowing, NUMERIC_KINDS, type NarrowingDefaults, type NumberOffset, Operator, type OperatorFamily, type OrderBy, type OrderedRuleValue, type PathProjection, type PeriodExpr, type PeriodUnit, type PrismaProvider, type PrismaStep, type PrismaWhere, type ProjectLensOptions, type ProjectedVisit, type RelativeUnits, type RollingExpr, type Row, type Rule, type RuleDescription, type RuleScalar, type RuleSourceDescription, RuleTarget, type RuleValue, type ScopeOutOfBounds, type ScopeRef, type ScopedRef, type SortDir, type SourceEntry, type SourceOption, type SourcePrismaQuery, type SourceQuery, type SourceRowShape, type SourceSelect, type SourceSpec, type SourceSqlQuery, type SourceValues, type StepRef, type StoredLens, type StrictAggregateRule, type StrictAll, type StrictAny, type StrictArrayCountRule, type StrictArrayPredicateRule, type StrictArrayPresenceRule, type StrictArrayRule, type StrictCondition, type StrictContainsRule, type StrictDateComparisonRule, type StrictDateDayRule, type StrictDateRangeRule, type StrictDateRule, type StrictEqualityRule, type StrictIfThenElse, type StrictMembershipRule, type StrictOrderedComparisonRule, type StrictPatternRule, type StrictPresenceRule, type StrictRangeRule, type StrictRule, type StrictStringBoundaryRule, type TimeZoneConfig, type ToPrismaOptions, type ToPrismaResult, type ToSqlOptions, type ToSqlResult, type ValidateRuleOptions, type ValidationIssue, type ValidationResult, ValueShape, type ValueSourceFields, type ValueSourceOf, type WeekStart, type WhereStep, type WindowFields, assertValidFieldMaps, assertValidNarrowing, assertValidRule, bindLens, bindRule, check, coerceRule, composeLens, createLens, describeRule, describeRuleSources, engineGlobals, executePrismaPlan, getAggregateOperators, getArrayOperators, getOperatorsForKind, getValueShape, indexBridges, listBindings, listLensBindings, materializeSourceQuery, materializeSources, narrowRule, parseScopeRef, projectLens, readScopeRef, stitchFieldMaps, storeLens, toPrisma, toSourceQueries, toSql, validateFieldMaps, validateNarrowing, validateRule, validateRuleInLens, walkLensPath };